diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 87cb569978..bd35b608c6 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -70,6 +70,6 @@ jobs: ./.sonar/scanner/dotnet-sonarscanner begin /k:"${{ vars.SONAR_PROJECT_KEY }}" /o:"${{ vars.SONAR_ORGANIZATION }}" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.vscoveragexml.reportsPaths=src/coverage.xml dotnet build src cd src - dotnet-coverage collect 'dotnet test --filter FullyQualifiedName\!~Org.Eclipse.TractusX.Portal.Backend.EndToEnd.Tests --no-restore --verbosity normal' -s 'settings-coverage.xml' -f xml -o 'coverage.xml' + dotnet-coverage collect 'dotnet test --filter Category!=PortalHC&Category!=InterfaceHC&Category!=Portal&Category!=Registration --no-restore --verbosity normal' -s 'settings-coverage.xml' -f xml -o 'coverage.xml' cd .. ./.sonar/scanner/dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}" diff --git a/CHANGELOG.md b/CHANGELOG.md index 60e16d895b..c97e5eff21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,54 @@ New features, fixed bugs, known defects and other noteworthy changes to each release of the Catena-X Portal Backend. +## 1.7.0-RC1 + +### Change +* Apps Service + * instead of creating the notification for an app subscription after triggering the provider, the notification will directly be created when subscribing to an offer + * enhanced POST /{appId}/subscribe endpoint business logic enhanced to set offer_subscriptions.date_created value when running the endpoint + * enhanced GET /api/apps/{appId} logic to fetch the "isSubscribe" value by the latest subscription record + * enhanced GET /api/Apps/provided/subscription-status & GET /api/Apps/{appId}/subscription/{subscriptionId}/provider by adding processStepTypeId responding with the latest subscription processStepTypeId +* Services Service + * instead of creating the notification for an app subscription after triggering the provider, the notification will directly be created when subscribing to an offer + * POST {appId}/subscribe endpoint business logic enhanced to set offer_subscriptions.date_created value when running the endpoint +* Administration + * endpoint GET api/administration/partnernetwork/memberCompanies enhanced to allow to send specific set of BPNs inside the request payload to request membership status for those BPNLs only +* implemented business/backend logic to set/update company_applications.date_last_changed when running an update on the companyApplication + +### Feature +* App Service + * added endpoint to AppChange controller to allow app document change process - fetch app documents api: GET /apps/appchange/{appId}/documents +* Onboarding Service Provider *new function since 1.7.0 alpha* - released onboarding service provider functionality, incl.: + * moved creation of the users for network registrations in keycloak to the process step; if the call to keycloak fails operator can retrigger the process without impact to OSP/3rd party + * added /api/administration/identityprovider/network/identityproviders/managed/{identityProviderId} endpoint to retrieve idp information regarding IdP connected companies + +### Technical Support +* Removed auth trail from the provisioning settings and added the use of the keycloak settings to set the correct useAuthTrail value +* adjusted process worker workflow to build the process worker when changes within the networkRegistration directory appear +* Controller slimlined + * removse all identity related code from controllers + * added identityservice to buisnessLogic to access idenitity +* Mask sensitive information in portal logs +* Extended logs for external service/component calls +* Portal DB + * added inside portal.offer_subscription new attribute "date_created", incl. a migration to set all existing offer subscriptiond dates to "1970-01-01" +* check constraints is_external_type_use_case, is_credential_type_use_case & is_connector_managed changed from function constraint to trigger function constraint +* Add new process to synchronize keycloak user with company service account to set the correct user entity id + +### Bugfix +* Application approval/verification process: adjusted bpdm businessPartnerNumber pull process to handle an unset SharingProcessStarted and retry the process +* Onboarding Service Provider *new function since 1.7.0 alpha* + * OSP 3rd party customer registration submit endpoint run fixed by adding NetworkBusinessLogic Registration + * updated POST /partnerregistration endpoint - bpn propoerty value NULL allowed +* Seeding data typo fixes (agreements.json) +* Updated userRole for service endpoint PUT api/services/{subscriptionId}/unsubscribe to "unsubscribe_services" +* Add user entity id when creating a company service account + +### Known Knowns +* POST /api/registration/application/{applicationId}/inviteNewUser runs on error if user email is already known/existing in the portal db (no matter to which company the user is connected) + + ## 1.7.0 alpha ### Change @@ -40,16 +88,16 @@ New features, fixed bugs, known defects and other noteworthy changes to each rel * Notification Service * GET /api/notifications search string enabled to support search by notification content * Onboarding Service Provider *new function* - released onboarding service provider functionality, incl.: - * add new database structure for network to network - * add seeding for n2n + * added new database structure for network to network + * added seeding for n2n * enhanced POST /api/administration/identityprovider/owncompany/identityproviders endpoint by identityProviderType (managed; own; shared) * network process worker registered to use process worker for onboarding service provider registration flow - * add seeding (test data only) for the osp realm and company including users + * added seeding (test data only) for the osp realm and company including users * added POST /api/administration/registration/network/partnerRegistration/submit endpoint * added POST registration/network/partnerRegistration to register partners to the network - * add new process to synchronize users with central keycloak instance for the partnerRegistration - * add endpoint to get the callback url of an osp - * add endpoint to set the callback url of an osp + * added new process to synchronize users with central keycloak instance for the partnerRegistration + * added endpoint to get the callback url of an osp + * added endpoint to set the callback url of an osp * Email templates * released new email template 'offer release approval' * released new email tempülate 'welcome onboarding service provider registration company' (connected to feature release Onboarding Service Provider) diff --git a/DEPENDENCIES b/DEPENDENCIES index 2586121a24..ee9e80d8a6 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -35,6 +35,7 @@ nuget/nuget/-/Serilog.AspNetCore/7.0.0, Apache-2.0 AND MIT, approved, #10084 nuget/nuget/-/Serilog.Enrichers.CorrelationId/3.0.1, MIT, approved, clearlydefined nuget/nuget/-/Serilog.Enrichers.Environment/2.2.0, Apache-2.0, approved, clearlydefined nuget/nuget/-/Serilog.Enrichers.Process/2.0.2, Apache-2.0, approved, clearlydefined +nuget/nuget/-/Serilog.Enrichers.Sensitive/1.7.3, MIT, approved, clearlydefined nuget/nuget/-/Serilog.Enrichers.Thread/3.1.0, Apache-2.0, approved, clearlydefined nuget/nuget/-/Serilog.Extensions.Hosting/7.0.0, Apache-2.0, approved, #10078 nuget/nuget/-/Serilog.Extensions.Logging/7.0.0, Apache-2.0, approved, #10070 diff --git a/src/Directory.Build.props b/src/Directory.Build.props index af0536aea8..475a70a66e 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -21,6 +21,6 @@ 1.7.0 - alpha + RC1 diff --git a/src/Portal.Backend.sln b/src/Portal.Backend.sln index b493ebc00f..dc58bb4387 100644 --- a/src/Portal.Backend.sln +++ b/src/Portal.Backend.sln @@ -232,6 +232,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnboardingServiceProvider.L EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetworkRegistration.Executor.Tests", "..\tests\processes\NetworkRegistration.Executor.Tests\NetworkRegistration.Executor.Tests.csproj", "{F1A5A73C-2B8C-4959-A128-CC5A8DECCB1B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Framework.Logging.Tests", "..\tests\framework\Framework.Logging.Tests\Framework.Logging.Tests.csproj", "{146865E5-7DFF-4CC2-8521-9E22CFCEEA20}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceAccountSync.Executor", "processes\ServiceAccountSync.Executor\ServiceAccountSync.Executor.csproj", "{B2E5EBAB-AE49-47B6-8220-4844AC9DA456}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceAccountSync.Executor.Tests", "..\tests\processes\ServiceAccountSync.Executor.Tests\ServiceAccountSync.Executor.Tests.csproj", "{571DA63A-6B96-4C6C-8D82-D2C1F10BDAE5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1466,6 +1472,42 @@ Global {F1A5A73C-2B8C-4959-A128-CC5A8DECCB1B}.Release|x64.Build.0 = Release|Any CPU {F1A5A73C-2B8C-4959-A128-CC5A8DECCB1B}.Release|x86.ActiveCfg = Release|Any CPU {F1A5A73C-2B8C-4959-A128-CC5A8DECCB1B}.Release|x86.Build.0 = Release|Any CPU + {146865E5-7DFF-4CC2-8521-9E22CFCEEA20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {146865E5-7DFF-4CC2-8521-9E22CFCEEA20}.Debug|Any CPU.Build.0 = Debug|Any CPU + {146865E5-7DFF-4CC2-8521-9E22CFCEEA20}.Debug|x64.ActiveCfg = Debug|Any CPU + {146865E5-7DFF-4CC2-8521-9E22CFCEEA20}.Debug|x64.Build.0 = Debug|Any CPU + {146865E5-7DFF-4CC2-8521-9E22CFCEEA20}.Debug|x86.ActiveCfg = Debug|Any CPU + {146865E5-7DFF-4CC2-8521-9E22CFCEEA20}.Debug|x86.Build.0 = Debug|Any CPU + {146865E5-7DFF-4CC2-8521-9E22CFCEEA20}.Release|Any CPU.ActiveCfg = Release|Any CPU + {146865E5-7DFF-4CC2-8521-9E22CFCEEA20}.Release|Any CPU.Build.0 = Release|Any CPU + {146865E5-7DFF-4CC2-8521-9E22CFCEEA20}.Release|x64.ActiveCfg = Release|Any CPU + {146865E5-7DFF-4CC2-8521-9E22CFCEEA20}.Release|x64.Build.0 = Release|Any CPU + {146865E5-7DFF-4CC2-8521-9E22CFCEEA20}.Release|x86.ActiveCfg = Release|Any CPU + {146865E5-7DFF-4CC2-8521-9E22CFCEEA20}.Release|x86.Build.0 = Release|Any CPU + {B2E5EBAB-AE49-47B6-8220-4844AC9DA456}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B2E5EBAB-AE49-47B6-8220-4844AC9DA456}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B2E5EBAB-AE49-47B6-8220-4844AC9DA456}.Debug|x64.ActiveCfg = Debug|Any CPU + {B2E5EBAB-AE49-47B6-8220-4844AC9DA456}.Debug|x64.Build.0 = Debug|Any CPU + {B2E5EBAB-AE49-47B6-8220-4844AC9DA456}.Debug|x86.ActiveCfg = Debug|Any CPU + {B2E5EBAB-AE49-47B6-8220-4844AC9DA456}.Debug|x86.Build.0 = Debug|Any CPU + {B2E5EBAB-AE49-47B6-8220-4844AC9DA456}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B2E5EBAB-AE49-47B6-8220-4844AC9DA456}.Release|Any CPU.Build.0 = Release|Any CPU + {B2E5EBAB-AE49-47B6-8220-4844AC9DA456}.Release|x64.ActiveCfg = Release|Any CPU + {B2E5EBAB-AE49-47B6-8220-4844AC9DA456}.Release|x64.Build.0 = Release|Any CPU + {B2E5EBAB-AE49-47B6-8220-4844AC9DA456}.Release|x86.ActiveCfg = Release|Any CPU + {B2E5EBAB-AE49-47B6-8220-4844AC9DA456}.Release|x86.Build.0 = Release|Any CPU + {571DA63A-6B96-4C6C-8D82-D2C1F10BDAE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {571DA63A-6B96-4C6C-8D82-D2C1F10BDAE5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {571DA63A-6B96-4C6C-8D82-D2C1F10BDAE5}.Debug|x64.ActiveCfg = Debug|Any CPU + {571DA63A-6B96-4C6C-8D82-D2C1F10BDAE5}.Debug|x64.Build.0 = Debug|Any CPU + {571DA63A-6B96-4C6C-8D82-D2C1F10BDAE5}.Debug|x86.ActiveCfg = Debug|Any CPU + {571DA63A-6B96-4C6C-8D82-D2C1F10BDAE5}.Debug|x86.Build.0 = Debug|Any CPU + {571DA63A-6B96-4C6C-8D82-D2C1F10BDAE5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {571DA63A-6B96-4C6C-8D82-D2C1F10BDAE5}.Release|Any CPU.Build.0 = Release|Any CPU + {571DA63A-6B96-4C6C-8D82-D2C1F10BDAE5}.Release|x64.ActiveCfg = Release|Any CPU + {571DA63A-6B96-4C6C-8D82-D2C1F10BDAE5}.Release|x64.Build.0 = Release|Any CPU + {571DA63A-6B96-4C6C-8D82-D2C1F10BDAE5}.Release|x86.ActiveCfg = Release|Any CPU + {571DA63A-6B96-4C6C-8D82-D2C1F10BDAE5}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1474,6 +1516,7 @@ Global SolutionGuid = {2EB6265F-323A-4BF3-969E-003D64A14B64} EndGlobalSection GlobalSection(NestedProjects) = preSolution + {146865E5-7DFF-4CC2-8521-9E22CFCEEA20} = {323C198D-A8C6-4EB0-8B79-72624275E35F} {A43B5ACA-1209-46E9-84DB-A48553ED623E} = {323C198D-A8C6-4EB0-8B79-72624275E35F} {1EAF34DA-6D16-4F5E-86F4-344185F53942} = {323C198D-A8C6-4EB0-8B79-72624275E35F} {A5BEDD89-7280-466E-8D14-EC5E177AAD07} = {323C198D-A8C6-4EB0-8B79-72624275E35F} @@ -1576,5 +1619,7 @@ Global {D22934D7-59B7-4779-AB59-E5BE12DE2F06} = {323C198D-A8C6-4EB0-8B79-72624275E35F} {B06A4F63-FE8C-40D2-B39F-8C15031A55CC} = {C8957230-4203-452C-A085-34091C5E370B} {F1A5A73C-2B8C-4959-A128-CC5A8DECCB1B} = {323C198D-A8C6-4EB0-8B79-72624275E35F} + {B2E5EBAB-AE49-47B6-8220-4844AC9DA456} = {282CEF03-292F-4A49-83C6-997567D0FF5F} + {571DA63A-6B96-4C6C-8D82-D2C1F10BDAE5} = {323C198D-A8C6-4EB0-8B79-72624275E35F} EndGlobalSection EndGlobal diff --git a/src/administration/Administration.Service/BusinessLogic/ConnectorsBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/ConnectorsBusinessLogic.cs index cd6dbd3e40..c41887bbaf 100644 --- a/src/administration/Administration.Service/BusinessLogic/ConnectorsBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/ConnectorsBusinessLogic.cs @@ -18,7 +18,6 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models; using Org.Eclipse.TractusX.Portal.Backend.Framework.Async; @@ -44,6 +43,7 @@ public class ConnectorsBusinessLogic : IConnectorsBusinessLogic private readonly IPortalRepositories _portalRepositories; private readonly ISdFactoryBusinessLogic _sdFactoryBusinessLogic; private readonly IIdentityService _identityService; + private readonly ILogger _logger; private readonly ConnectorsSettings _settings; private static readonly Regex bpnRegex = new(@"(\w|\d){16}", RegexOptions.None, TimeSpan.FromSeconds(1)); @@ -54,12 +54,14 @@ public class ConnectorsBusinessLogic : IConnectorsBusinessLogic /// The options /// Access to the connectorsSdFactory /// Access to the current logged in user - public ConnectorsBusinessLogic(IPortalRepositories portalRepositories, IOptions options, ISdFactoryBusinessLogic sdFactoryBusinessLogic, IIdentityService identityService) + /// Access to the logger + public ConnectorsBusinessLogic(IPortalRepositories portalRepositories, IOptions options, ISdFactoryBusinessLogic sdFactoryBusinessLogic, IIdentityService identityService, ILogger logger) { _portalRepositories = portalRepositories; _settings = options.Value; _sdFactoryBusinessLogic = sdFactoryBusinessLogic; _identityService = identityService; + _logger = logger; } /// @@ -351,6 +353,8 @@ public IAsyncEnumerable GetCompanyConnectorEndPointAsync( /// public async Task ProcessClearinghouseSelfDescription(SelfDescriptionResponseData data, CancellationToken cancellationToken) { + _logger.LogInformation("Process SelfDescription called with the following data {Data}", data); + var result = await _portalRepositories.GetInstance() .GetConnectorDataById(data.ExternalId) .ConfigureAwait(false); diff --git a/src/administration/Administration.Service/BusinessLogic/DocumentsBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/DocumentsBusinessLogic.cs index cf32908b8a..ebdd4d233d 100644 --- a/src/administration/Administration.Service/BusinessLogic/DocumentsBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/DocumentsBusinessLogic.cs @@ -26,6 +26,7 @@ using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities; namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLogic; @@ -35,22 +36,24 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLog public class DocumentsBusinessLogic : IDocumentsBusinessLogic { private readonly IPortalRepositories _portalRepositories; + private readonly IIdentityService _identityService; private readonly DocumentSettings _settings; /// /// Creates a new instance /// - public DocumentsBusinessLogic(IPortalRepositories portalRepositories, IOptions options) + public DocumentsBusinessLogic(IPortalRepositories portalRepositories, IIdentityService identityService, IOptions options) { _portalRepositories = portalRepositories; + _identityService = identityService; _settings = options.Value; } /// - public async Task<(string FileName, byte[] Content, string MediaType)> GetDocumentAsync(Guid documentId, Guid companyId) + public async Task<(string FileName, byte[] Content, string MediaType)> GetDocumentAsync(Guid documentId) { var documentDetails = await _portalRepositories.GetInstance() - .GetDocumentDataAndIsCompanyUserAsync(documentId, companyId) + .GetDocumentDataAndIsCompanyUserAsync(documentId, _identityService.IdentityData.CompanyId) .ConfigureAwait(false); if (documentDetails == default) { @@ -84,10 +87,10 @@ public DocumentsBusinessLogic(IPortalRepositories portalRepositories, IOptions - public async Task DeleteDocumentAsync(Guid documentId, Guid companyUserId) + public async Task DeleteDocumentAsync(Guid documentId) { var documentRepository = _portalRepositories.GetInstance(); - var details = await documentRepository.GetDocumentDetailsForIdUntrackedAsync(documentId, companyUserId).ConfigureAwait(false); + var details = await documentRepository.GetDocumentDetailsForIdUntrackedAsync(documentId, _identityService.IdentityData.UserId).ConfigureAwait(false); if (details.DocumentId == Guid.Empty) { diff --git a/src/administration/Administration.Service/BusinessLogic/IDocumentsBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/IDocumentsBusinessLogic.cs index cefe377cfe..cd90e89744 100644 --- a/src/administration/Administration.Service/BusinessLogic/IDocumentsBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/IDocumentsBusinessLogic.cs @@ -31,9 +31,8 @@ public interface IDocumentsBusinessLogic /// Gets the document with the given id /// /// Id of the document to get - /// Company of the user /// Returns the filename and content of the file - Task<(string FileName, byte[] Content, string MediaType)> GetDocumentAsync(Guid documentId, Guid companyId); + Task<(string FileName, byte[] Content, string MediaType)> GetDocumentAsync(Guid documentId); /// /// Gets the selfdescription document with the given id @@ -46,9 +45,8 @@ public interface IDocumentsBusinessLogic /// Deletes the document and the corresponding consent from the persistence layer. /// /// Id of the document that should be deleted - /// /// Returns true if the document and corresponding consent were deleted successfully. Otherwise a specific error is thrown. - Task DeleteDocumentAsync(Guid documentId, Guid companyUserId); + Task DeleteDocumentAsync(Guid documentId); /// /// Gets the document as json for the seeding data diff --git a/src/administration/Administration.Service/BusinessLogic/IIdentityProviderBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/IIdentityProviderBusinessLogic.cs index 07fa0078d3..d80c8a3ca8 100644 --- a/src/administration/Administration.Service/BusinessLogic/IIdentityProviderBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/IIdentityProviderBusinessLogic.cs @@ -33,11 +33,12 @@ public interface IIdentityProviderBusinessLogic ValueTask SetOwnCompanyIdentityProviderStatusAsync(Guid identityProviderId, bool enabled); ValueTask UpdateOwnCompanyIdentityProviderAsync(Guid identityProviderId, IdentityProviderEditableDetails details); ValueTask DeleteCompanyIdentityProviderAsync(Guid identityProviderId); - IAsyncEnumerable GetOwnCompanyUsersIdentityProviderDataAsync(IEnumerable identityProviderIds, Guid companyId, bool unlinkedUsersOnly); - (Stream FileStream, string ContentType, string FileName, Encoding Encoding) GetOwnCompanyUsersIdentityProviderLinkDataStream(IEnumerable identityProviderIds, Guid companyId, bool unlinkedUsersOnly); - ValueTask UploadOwnCompanyUsersIdentityProviderLinkDataAsync(IFormFile document, Guid companyId, CancellationToken cancellationToken); - ValueTask CreateOwnCompanyUserIdentityProviderLinkDataAsync(Guid companyUserId, UserIdentityProviderLinkData identityProviderLinkData, Guid companyId); - ValueTask CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync(Guid companyUserId, Guid identityProviderId, UserLinkData userLinkData, Guid companyId); - ValueTask GetOwnCompanyUserIdentityProviderLinkDataAsync(Guid companyUserId, Guid identityProviderId, Guid companyId); - ValueTask DeleteOwnCompanyUserIdentityProviderDataAsync(Guid companyUserId, Guid identityProviderId, Guid companyId); + IAsyncEnumerable GetOwnCompanyUsersIdentityProviderDataAsync(IEnumerable identityProviderIds, bool unlinkedUsersOnly); + (Stream FileStream, string ContentType, string FileName, Encoding Encoding) GetOwnCompanyUsersIdentityProviderLinkDataStream(IEnumerable identityProviderIds, bool unlinkedUsersOnly); + ValueTask UploadOwnCompanyUsersIdentityProviderLinkDataAsync(IFormFile document, CancellationToken cancellationToken); + ValueTask CreateOwnCompanyUserIdentityProviderLinkDataAsync(Guid companyUserId, UserIdentityProviderLinkData identityProviderLinkData); + ValueTask CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync(Guid companyUserId, Guid identityProviderId, UserLinkData userLinkData); + ValueTask GetOwnCompanyUserIdentityProviderLinkDataAsync(Guid companyUserId, Guid identityProviderId); + ValueTask DeleteOwnCompanyUserIdentityProviderDataAsync(Guid companyUserId, Guid identityProviderId); + ValueTask GetOwnIdentityProviderWithConnectedCompanies(Guid identityProviderId); } diff --git a/src/administration/Administration.Service/BusinessLogic/INetworkBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/INetworkBusinessLogic.cs index 180e8df421..5446b619d4 100644 --- a/src/administration/Administration.Service/BusinessLogic/INetworkBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/INetworkBusinessLogic.cs @@ -1,5 +1,4 @@ /******************************************************************************** - * Copyright (c) 2021, 2023 BMW Group AG * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional @@ -26,7 +25,5 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLog public interface INetworkBusinessLogic { Task HandlePartnerRegistration(PartnerRegistrationData data); - Task RetriggerProcessStep(Guid externalId, ProcessStepTypeId processStepTypeId); - Task Submit(PartnerSubmitData submitData, CancellationToken cancellationToken); } diff --git a/src/administration/Administration.Service/BusinessLogic/IPartnerNetworkBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/IPartnerNetworkBusinessLogic.cs index 886a6d3448..17ef29b9fa 100644 --- a/src/administration/Administration.Service/BusinessLogic/IPartnerNetworkBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/IPartnerNetworkBusinessLogic.cs @@ -22,6 +22,10 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLog { public interface IPartnerNetworkBusinessLogic { - IAsyncEnumerable GetAllMemberCompaniesBPNAsync(); + /// + /// Get all member activecompanies bpn + /// + /// Ids of BPN + IAsyncEnumerable GetAllMemberCompaniesBPNAsync(IEnumerable? bpnIds); } } diff --git a/src/administration/Administration.Service/BusinessLogic/IServiceAccountBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/IServiceAccountBusinessLogic.cs index 74972bb9df..3e80897454 100644 --- a/src/administration/Administration.Service/BusinessLogic/IServiceAccountBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/IServiceAccountBusinessLogic.cs @@ -27,11 +27,11 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLog public interface IServiceAccountBusinessLogic { - Task CreateOwnCompanyServiceAccountAsync(ServiceAccountCreationInfo serviceAccountCreationInfos, Guid companyId); - Task DeleteOwnCompanyServiceAccountAsync(Guid serviceAccountId, Guid companyId); - Task GetOwnCompanyServiceAccountDetailsAsync(Guid serviceAccountId, Guid companyId); - Task UpdateOwnCompanyServiceAccountDetailsAsync(Guid serviceAccountId, ServiceAccountEditableDetails serviceAccountDetails, Guid companyId); - Task ResetOwnCompanyServiceAccountSecretAsync(Guid serviceAccountId, Guid companyId); - Task> GetOwnCompanyServiceAccountsDataAsync(int page, int size, Guid companyId, string? clientId, bool? isOwner); - IAsyncEnumerable GetServiceAccountRolesAsync(Guid companyId, string? languageShortName); + Task CreateOwnCompanyServiceAccountAsync(ServiceAccountCreationInfo serviceAccountCreationInfos); + Task DeleteOwnCompanyServiceAccountAsync(Guid serviceAccountId); + Task GetOwnCompanyServiceAccountDetailsAsync(Guid serviceAccountId); + Task UpdateOwnCompanyServiceAccountDetailsAsync(Guid serviceAccountId, ServiceAccountEditableDetails serviceAccountDetails); + Task ResetOwnCompanyServiceAccountSecretAsync(Guid serviceAccountId); + Task> GetOwnCompanyServiceAccountsDataAsync(int page, int size, string? clientId, bool? isOwner); + IAsyncEnumerable GetServiceAccountRolesAsync(string? languageShortName); } diff --git a/src/administration/Administration.Service/BusinessLogic/ISubscriptionConfigurationBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/ISubscriptionConfigurationBusinessLogic.cs index c2ee708094..a4163be04e 100644 --- a/src/administration/Administration.Service/BusinessLogic/ISubscriptionConfigurationBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/ISubscriptionConfigurationBusinessLogic.cs @@ -60,12 +60,12 @@ public interface ISubscriptionConfigurationBusinessLogic /// /// Id of the users company /// The detail data - Task GetProviderCompanyDetailsAsync(Guid companyId); + Task GetProviderCompanyDetailsAsync(); /// /// Sets service provider company details /// /// Detail data for the service provider /// Id of the users company - Task SetProviderCompanyDetailsAsync(ProviderDetailData data, Guid companyId); + Task SetProviderCompanyDetailsAsync(ProviderDetailData data); } diff --git a/src/administration/Administration.Service/BusinessLogic/IUserBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/IUserBusinessLogic.cs index cbf8b21a2f..ce4289f661 100644 --- a/src/administration/Administration.Service/BusinessLogic/IUserBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/IUserBusinessLogic.cs @@ -29,16 +29,16 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLog /// public interface IUserBusinessLogic { - IAsyncEnumerable CreateOwnCompanyUsersAsync(IEnumerable userList, (Guid UserId, Guid CompanyId) identity); - Task CreateOwnCompanyIdpUserAsync(Guid identityProviderId, UserCreationInfoIdp userCreationInfo, (Guid UserId, Guid CompanyId) identity); - Task> GetOwnCompanyUserDatasAsync(Guid companyId, int page, int size, GetOwnCompanyUsersFilter filter); + IAsyncEnumerable CreateOwnCompanyUsersAsync(IEnumerable userList); + Task CreateOwnCompanyIdpUserAsync(Guid identityProviderId, UserCreationInfoIdp userCreationInfo); + Task> GetOwnCompanyUserDatasAsync(int page, int size, GetOwnCompanyUsersFilter filter); [Obsolete("to be replaced by UserRolesBusinessLogic.GetAppRolesAsync. Remove as soon frontend is adjusted")] IAsyncEnumerable GetClientRolesAsync(Guid appId, string? languageShortName = null); - Task GetOwnCompanyUserDetailsAsync(Guid userId, Guid companyId); - Task AddOwnCompanyUsersBusinessPartnerNumbersAsync(Guid userId, IEnumerable businessPartnerNumbers, Guid companyId); - Task AddOwnCompanyUsersBusinessPartnerNumberAsync(Guid userId, string businessPartnerNumber, Guid companyId); - Task GetOwnUserDetails(Guid userId); - Task UpdateOwnUserDetails(Guid companyUserId, OwnCompanyUserEditableDetails ownCompanyUserEditableDetails, Guid userId); + Task GetOwnCompanyUserDetailsAsync(Guid userId); + Task AddOwnCompanyUsersBusinessPartnerNumbersAsync(Guid userId, IEnumerable businessPartnerNumbers); + Task AddOwnCompanyUsersBusinessPartnerNumberAsync(Guid userId, string businessPartnerNumber); + Task GetOwnUserDetails(); + Task UpdateOwnUserDetails(Guid companyUserId, OwnCompanyUserEditableDetails ownCompanyUserEditableDetails); /// /// Delete User Own Account using userId @@ -46,9 +46,9 @@ public interface IUserBusinessLogic /// /// /// - Task DeleteOwnUserAsync(Guid companyUserId, Guid userId); - IAsyncEnumerable DeleteOwnCompanyUsersAsync(IEnumerable userIds, Guid companyId); - Task ExecuteOwnCompanyUserPasswordReset(Guid companyUserId, (Guid UserId, Guid CompanyId) identity); - Task> GetOwnCompanyAppUsersAsync(Guid appId, Guid userId, int page, int size, CompanyUserFilter filter); - Task DeleteOwnUserBusinessPartnerNumbersAsync(Guid userId, string businessPartnerNumber, (Guid UserId, Guid CompanyId) identity); + Task DeleteOwnUserAsync(Guid companyUserId); + IAsyncEnumerable DeleteOwnCompanyUsersAsync(IEnumerable userIds); + Task ExecuteOwnCompanyUserPasswordReset(Guid companyUserId); + Task> GetOwnCompanyAppUsersAsync(Guid appId, int page, int size, CompanyUserFilter filter); + Task DeleteOwnUserBusinessPartnerNumbersAsync(Guid userId, string businessPartnerNumber); } diff --git a/src/administration/Administration.Service/BusinessLogic/IUserRolesBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/IUserRolesBusinessLogic.cs index 1334043b2b..76f6022206 100644 --- a/src/administration/Administration.Service/BusinessLogic/IUserRolesBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/IUserRolesBusinessLogic.cs @@ -25,8 +25,8 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLog public interface IUserRolesBusinessLogic { - IAsyncEnumerable GetCoreOfferRoles(Guid companyId, string? languageShortName); - IAsyncEnumerable GetAppRolesAsync(Guid appId, Guid companyId, string? languageShortName); + IAsyncEnumerable GetCoreOfferRoles(string? languageShortName); + IAsyncEnumerable GetAppRolesAsync(Guid appId, string? languageShortName); /// /// Update Role to User @@ -34,9 +34,8 @@ public interface IUserRolesBusinessLogic /// /// /// - /// CompanyId of Admin User /// messages - Task> ModifyCoreOfferUserRolesAsync(Guid offerId, Guid companyUserId, IEnumerable roles, Guid companyId); + Task> ModifyCoreOfferUserRolesAsync(Guid offerId, Guid companyUserId, IEnumerable roles); /// /// Update Role to User @@ -44,17 +43,15 @@ public interface IUserRolesBusinessLogic /// /// /// - /// CompanyId of Admin User /// messages - Task> ModifyAppUserRolesAsync(Guid appId, Guid companyUserId, IEnumerable roles, Guid companyId); + Task> ModifyAppUserRolesAsync(Guid appId, Guid companyUserId, IEnumerable roles); /// /// Update Role to User /// /// app Id /// User and Role Information like CompanyUser Id and Role Name - /// CompanyId of Admin User /// messages [Obsolete("to be replaced by endpoint UserRolesBusinessLogic.ModifyAppUserRolesAsync. Remove as soon frontend is adjusted")] - Task> ModifyUserRoleAsync(Guid appId, UserRoleInfo userRoleInfo, Guid companyId); + Task> ModifyUserRoleAsync(Guid appId, UserRoleInfo userRoleInfo); } diff --git a/src/administration/Administration.Service/BusinessLogic/IUserUploadBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/IUserUploadBusinessLogic.cs index d984353291..95628f3ba7 100644 --- a/src/administration/Administration.Service/BusinessLogic/IUserUploadBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/IUserUploadBusinessLogic.cs @@ -24,6 +24,6 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLog public interface IUserUploadBusinessLogic { - ValueTask UploadOwnCompanyIdpUsersAsync(Guid identityProviderId, IFormFile document, (Guid UserId, Guid CompanyId) identity, CancellationToken cancellationToken); - ValueTask UploadOwnCompanySharedIdpUsersAsync(IFormFile document, (Guid UserId, Guid CompanyId) identity, CancellationToken cancellationToken); + ValueTask UploadOwnCompanyIdpUsersAsync(Guid identityProviderId, IFormFile document, CancellationToken cancellationToken); + ValueTask UploadOwnCompanySharedIdpUsersAsync(IFormFile document, CancellationToken cancellationToken); } diff --git a/src/administration/Administration.Service/BusinessLogic/IdentityProviderBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/IdentityProviderBusinessLogic.cs index af53fd38a1..b9f3c6e231 100644 --- a/src/administration/Administration.Service/BusinessLogic/IdentityProviderBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/IdentityProviderBusinessLogic.cs @@ -138,8 +138,7 @@ private async ValueTask CreateOwnCompanyIdentityProvide public async ValueTask GetOwnCompanyIdentityProviderAsync(Guid identityProviderId) { - var companyId = _identityService.IdentityData.CompanyId; - var (alias, category, typeId) = await ValidateGetOwnCompanyIdentityProviderArguments(identityProviderId, companyId).ConfigureAwait(false); + var (alias, category, typeId) = await ValidateGetOwnCompanyIdentityProviderArguments(identityProviderId).ConfigureAwait(false); return category switch { @@ -149,8 +148,9 @@ public async ValueTask GetOwnCompanyIdentityProviderAsy }; } - private async ValueTask<(string Alias, IdentityProviderCategoryId Category, IdentityProviderTypeId TypeId)> ValidateGetOwnCompanyIdentityProviderArguments(Guid identityProviderId, Guid companyId) + private async ValueTask<(string Alias, IdentityProviderCategoryId Category, IdentityProviderTypeId TypeId)> ValidateGetOwnCompanyIdentityProviderArguments(Guid identityProviderId) { + var companyId = _identityService.IdentityData.CompanyId; var (alias, category, isOwnOrOwnerCompany, typeId) = await _portalRepositories.GetInstance().GetOwnCompanyIdentityProviderAliasUntrackedAsync(identityProviderId, companyId).ConfigureAwait(false); if (!isOwnOrOwnerCompany) { @@ -172,8 +172,7 @@ public async ValueTask GetOwnCompanyIdentityProviderAsy public async ValueTask SetOwnCompanyIdentityProviderStatusAsync(Guid identityProviderId, bool enabled) { - var companyId = _identityService.IdentityData.CompanyId; - var (category, alias, typeId) = await ValidateSetOwnCompanyIdentityProviderStatusArguments(identityProviderId, enabled, companyId).ConfigureAwait(false); + var (category, alias, typeId) = await ValidateSetOwnCompanyIdentityProviderStatusArguments(identityProviderId, enabled).ConfigureAwait(false); switch (category) { @@ -191,8 +190,9 @@ public async ValueTask SetOwnCompanyIdentityProviderSta } } - private async ValueTask<(IdentityProviderCategoryId Category, string Alias, IdentityProviderTypeId TypeId)> ValidateSetOwnCompanyIdentityProviderStatusArguments(Guid identityProviderId, bool enabled, Guid companyId) + private async ValueTask<(IdentityProviderCategoryId Category, string Alias, IdentityProviderTypeId TypeId)> ValidateSetOwnCompanyIdentityProviderStatusArguments(Guid identityProviderId, bool enabled) { + var companyId = _identityService.IdentityData.CompanyId; var result = await _portalRepositories.GetInstance().GetOwnCompanyIdentityProviderUpdateDataUntrackedAsync(identityProviderId, companyId, true).ConfigureAwait(false); if (result == default) { @@ -323,7 +323,7 @@ private async ValueTask ValidateOtherActiveIdentityProvider(string? alias, public async ValueTask DeleteCompanyIdentityProviderAsync(Guid identityProviderId) { var companyId = _identityService.IdentityData.CompanyId; - var (alias, typeId) = await ValidateDeleteOwnCompanyIdentityProviderArguments(identityProviderId, companyId).ConfigureAwait(false); + var (alias, typeId) = await ValidateDeleteOwnCompanyIdentityProviderArguments(identityProviderId).ConfigureAwait(false); _portalRepositories.Remove(new CompanyIdentityProvider(companyId, identityProviderId)); @@ -341,8 +341,9 @@ public async ValueTask DeleteCompanyIdentityProviderAsync(Guid identityProviderI await _portalRepositories.SaveAsync().ConfigureAwait(false); } - private async ValueTask<(string? Alias, IdentityProviderTypeId TypeId)> ValidateDeleteOwnCompanyIdentityProviderArguments(Guid identityProviderId, Guid companyId) + private async ValueTask<(string? Alias, IdentityProviderTypeId TypeId)> ValidateDeleteOwnCompanyIdentityProviderArguments(Guid identityProviderId) { + var companyId = _identityService.IdentityData.CompanyId; var result = await _portalRepositories.GetInstance().GetOwnCompanyIdentityProviderUpdateDataUntrackedAsync(identityProviderId, companyId, true).ConfigureAwait(false); if (result == default) { @@ -470,8 +471,9 @@ private async ValueTask GetIdentityProviderDetailsSaml( }; } - public async ValueTask CreateOwnCompanyUserIdentityProviderLinkDataAsync(Guid companyUserId, UserIdentityProviderLinkData identityProviderLinkData, Guid companyId) + public async ValueTask CreateOwnCompanyUserIdentityProviderLinkDataAsync(Guid companyUserId, UserIdentityProviderLinkData identityProviderLinkData) { + var companyId = _identityService.IdentityData.CompanyId; var (userEntityId, alias) = await GetUserAliasDataAsync(companyUserId, identityProviderLinkData.identityProviderId, companyId).ConfigureAwait(false); try @@ -495,8 +497,9 @@ await _provisioningManager.AddProviderUserLinkToCentralUserAsync( identityProviderLinkData.userName); } - public async ValueTask CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync(Guid companyUserId, Guid identityProviderId, UserLinkData userLinkData, Guid companyId) + public async ValueTask CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync(Guid companyUserId, Guid identityProviderId, UserLinkData userLinkData) { + var companyId = _identityService.IdentityData.CompanyId; var (userEntityId, alias) = await GetUserAliasDataAsync(companyUserId, identityProviderId, companyId).ConfigureAwait(false); try @@ -521,8 +524,9 @@ await _provisioningManager.AddProviderUserLinkToCentralUserAsync( userLinkData.userName); } - public async ValueTask GetOwnCompanyUserIdentityProviderLinkDataAsync(Guid companyUserId, Guid identityProviderId, Guid companyId) + public async ValueTask GetOwnCompanyUserIdentityProviderLinkDataAsync(Guid companyUserId, Guid identityProviderId) { + var companyId = _identityService.IdentityData.CompanyId; var (userEntityId, alias) = await GetUserAliasDataAsync(companyUserId, identityProviderId, companyId).ConfigureAwait(false); var result = await _provisioningManager.GetProviderUserLinkDataForCentralUserIdAsync(userEntityId).FirstOrDefaultAsync(identityProviderLink => identityProviderLink.Alias == alias).ConfigureAwait(false); @@ -537,8 +541,9 @@ public async ValueTask GetOwnCompanyUserIdentityPr result.UserName); } - public async ValueTask DeleteOwnCompanyUserIdentityProviderDataAsync(Guid companyUserId, Guid identityProviderId, Guid companyId) + public async ValueTask DeleteOwnCompanyUserIdentityProviderDataAsync(Guid companyUserId, Guid identityProviderId) { + var companyId = _identityService.IdentityData.CompanyId; var (userEntityId, alias) = await GetUserAliasDataAsync(companyUserId, identityProviderId, companyId).ConfigureAwait(false); try { @@ -550,8 +555,39 @@ public async ValueTask DeleteOwnCompanyUserIdentityProviderDataAsync(Guid compan } } - public async IAsyncEnumerable GetOwnCompanyUsersIdentityProviderDataAsync(IEnumerable identityProviderIds, Guid companyId, bool unlinkedUsersOnly) + public async ValueTask GetOwnIdentityProviderWithConnectedCompanies(Guid identityProviderId) + { + var companyId = _identityService.IdentityData.CompanyId; + + var (alias, category, isOwnerCompany, typeId, connectedCompanies) = await _portalRepositories.GetInstance().GetOwnIdentityProviderWithConnectedCompanies(identityProviderId, companyId).ConfigureAwait(false); + if (!isOwnerCompany) + { + throw new ConflictException($"identityProvider {identityProviderId} is not associated with company {companyId}"); + } + + if (alias == null) + { + throw new NotFoundException($"identityProvider {identityProviderId} does not exist"); + } + + if (category == IdentityProviderCategoryId.KEYCLOAK_SAML && typeId is IdentityProviderTypeId.SHARED) + { + throw new ConflictException("Shared Idps must not use SAML"); + } + + var details = category switch + { + IdentityProviderCategoryId.KEYCLOAK_OIDC => await GetIdentityProviderDetailsOidc(identityProviderId, alias, category, typeId).ConfigureAwait(false), + IdentityProviderCategoryId.KEYCLOAK_SAML => await GetIdentityProviderDetailsSaml(identityProviderId, alias, typeId).ConfigureAwait(false), + _ => throw new UnexpectedConditionException($"unexpected value for category '{category}' of identityProvider '{identityProviderId}'") + }; + + return new(details.identityProviderId, details.alias, details.identityProviderCategoryId, details.IdentityProviderTypeId, details.displayName, details.redirectUrl, details.enabled, connectedCompanies); + } + + public async IAsyncEnumerable GetOwnCompanyUsersIdentityProviderDataAsync(IEnumerable identityProviderIds, bool unlinkedUsersOnly) { + var companyId = _identityService.IdentityData.CompanyId; var identityProviderAliasDatas = await GetOwnCompanyUsersIdentityProviderAliasDataInternalAsync(identityProviderIds, companyId).ConfigureAwait(false); var idPerAlias = identityProviderAliasDatas.ToDictionary(item => item.Alias, item => item.IdentityProviderId); var aliase = identityProviderAliasDatas.Select(item => item.Alias).ToList(); @@ -577,24 +613,26 @@ public async IAsyncEnumerable GetOwnCompanyUsersIdenti } } - public (Stream FileStream, string ContentType, string FileName, Encoding Encoding) GetOwnCompanyUsersIdentityProviderLinkDataStream(IEnumerable identityProviderIds, Guid companyId, bool unlinkedUsersOnly) + public (Stream FileStream, string ContentType, string FileName, Encoding Encoding) GetOwnCompanyUsersIdentityProviderLinkDataStream(IEnumerable identityProviderIds, bool unlinkedUsersOnly) { + var companyId = _identityService.IdentityData.CompanyId; var csvSettings = _settings.CsvSettings; return (new AsyncEnumerableStringStream(GetOwnCompanyUsersIdentityProviderDataLines(identityProviderIds, unlinkedUsersOnly, companyId), csvSettings.Encoding), csvSettings.ContentType, csvSettings.FileName, csvSettings.Encoding); } - public ValueTask UploadOwnCompanyUsersIdentityProviderLinkDataAsync(IFormFile document, Guid companyId, CancellationToken cancellationToken) + public ValueTask UploadOwnCompanyUsersIdentityProviderLinkDataAsync(IFormFile document, CancellationToken cancellationToken) { if (!document.ContentType.Equals(_settings.CsvSettings.ContentType, StringComparison.OrdinalIgnoreCase)) { throw new UnsupportedMediaTypeException($"Only contentType {_settings.CsvSettings.ContentType} files are allowed."); } - return UploadOwnCompanyUsersIdentityProviderLinkDataInternalAsync(document, companyId, cancellationToken); + return UploadOwnCompanyUsersIdentityProviderLinkDataInternalAsync(document, cancellationToken); } - private async ValueTask UploadOwnCompanyUsersIdentityProviderLinkDataInternalAsync(IFormFile document, Guid companyId, CancellationToken cancellationToken) + private async ValueTask UploadOwnCompanyUsersIdentityProviderLinkDataInternalAsync(IFormFile document, CancellationToken cancellationToken) { var userRepository = _portalRepositories.GetInstance(); + var companyId = _identityService.IdentityData.CompanyId; var (sharedIdpAlias, existingAliase) = await GetCompanyAliasDataAsync(companyId).ConfigureAwait(false); using var stream = document.OpenReadStream(); diff --git a/src/administration/Administration.Service/BusinessLogic/NetworkBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/NetworkBusinessLogic.cs index 84e8f3c8cd..6aa306ea19 100644 --- a/src/administration/Administration.Service/BusinessLogic/NetworkBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/NetworkBusinessLogic.cs @@ -1,5 +1,4 @@ /******************************************************************************** - * Copyright (c) 2021, 2023 BMW Group AG * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional @@ -24,7 +23,6 @@ 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.Mailing.SendMail; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; @@ -33,7 +31,6 @@ using Org.Eclipse.TractusX.Portal.Backend.Processes.NetworkRegistration.Library; 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; @@ -48,16 +45,14 @@ public class NetworkBusinessLogic : INetworkBusinessLogic private readonly IIdentityService _identityService; private readonly IUserProvisioningService _userProvisioningService; private readonly INetworkRegistrationProcessHelper _processHelper; - private readonly IMailingService _mailingService; private readonly PartnerRegistrationSettings _settings; - public NetworkBusinessLogic(IPortalRepositories portalRepositories, IIdentityService identityService, IUserProvisioningService userProvisioningService, INetworkRegistrationProcessHelper processHelper, IMailingService mailingService, IOptions options) + public NetworkBusinessLogic(IPortalRepositories portalRepositories, IIdentityService identityService, IUserProvisioningService userProvisioningService, INetworkRegistrationProcessHelper processHelper, IOptions options) { _portalRepositories = portalRepositories; _identityService = identityService; _userProvisioningService = userProvisioningService; _processHelper = processHelper; - _mailingService = mailingService; _settings = options.Value; } @@ -71,8 +66,6 @@ public async Task HandlePartnerRegistration(PartnerRegistrationData data) var (roleData, identityProviderIdAliase, singleIdentityProviderIdAlias, allIdentityProviderIds) = await ValidatePartnerRegistrationData(data, networkRepository, identityProviderRepository, ownerCompanyId).ConfigureAwait(false); - var (_, companyName) = await companyRepository.GetCompanyNameUntrackedAsync(ownerCompanyId).ConfigureAwait(false); - var companyId = CreatePartnerCompany(companyRepository, data); var applicationId = _portalRepositories.GetInstance().CreateCompanyApplication(companyId, CompanyApplicationStatusId.CREATED, CompanyApplicationTypeId.EXTERNAL, @@ -98,13 +91,27 @@ string GetIdpAlias(Guid? identityProviderId) => ? singleIdentityProviderIdAlias?.Alias ?? throw new UnexpectedConditionException("singleIdentityProviderIdAlias should never be null here") : identityProviderIdAliase?[identityProviderId.Value] ?? throw new UnexpectedConditionException("identityProviderIdAliase should never be null here and should always contain an entry for identityProviderId"); - async IAsyncEnumerable<(Guid CompanyUserId, string UserName, string? Password, Exception? Error)> CreateUsers() + async IAsyncEnumerable<(Guid CompanyUserId, Exception? Error)> CreateUsers() { - foreach (var user in GetUserCreationData(companyId, GetIdpId, GetIdpAlias, data, roleData)) + var userRepository = _portalRepositories.GetInstance(); + await foreach (var (aliasData, creationInfos) in GetUserCreationData(companyId, GetIdpId, GetIdpAlias, data, roleData).ToAsyncEnumerable()) { - await foreach (var result in _userProvisioningService.CreateOwnCompanyIdpUsersAsync(user.AliasData, user.CreationInfos.ToAsyncEnumerable())) + foreach (var creationInfo in creationInfos) { - yield return result; + var identityId = Guid.Empty; + Exception? error = null; + try + { + var (_, companyUserId) = await _userProvisioningService.GetOrCreateCompanyUser(userRepository, aliasData.IdpAlias, + creationInfo, companyId, aliasData.IdpId, data.Bpn).ConfigureAwait(false); + identityId = companyUserId; + } + catch (Exception ex) + { + error = ex; + } + + yield return (identityId, error); } } } @@ -113,7 +120,6 @@ string GetIdpAlias(Guid? identityProviderId) => userCreationErrors.IfAny(errors => throw new ServiceException($"Errors occured while saving the users: ${string.Join("", errors.Select(x => x.Message))}", errors.First())); await _portalRepositories.SaveAsync().ConfigureAwait(false); - await SendMails(data.UserDetails.Select(x => new ValueTuple(x.Email, x.FirstName, x.LastName)), companyName).ConfigureAwait(false); } private Guid CreatePartnerCompany(ICompanyRepository companyRepository, PartnerRegistrationData data) @@ -169,35 +175,22 @@ private Guid CreatePartnerCompany(ICompanyRepository companyRepository, PartnerR return (AliasData: companyNameIdpAliasData, CreationInfos: userCreationInfos); }); - private async Task SendMails(IEnumerable<(string Email, string? FirstName, string? LastName)> companyUserWithRoleIdForCompany, string ospName) - { - foreach (var (receiver, firstName, lastName) in companyUserWithRoleIdForCompany) - { - var userName = string.Join(" ", firstName, lastName); - var mailParameters = new Dictionary - { - { "userName", !string.IsNullOrWhiteSpace(userName) ? userName : receiver }, - { "hostname", _settings.BasePortalAddress }, - { "osp", ospName }, - { "url", _settings.BasePortalAddress } - }; - await _mailingService.SendMails(receiver, mailParameters, Enumerable.Repeat("OspWelcomeMail", 1)).ConfigureAwait(false); - } - } - public Task RetriggerProcessStep(Guid externalId, ProcessStepTypeId processStepTypeId) => _processHelper.TriggerProcessStep(externalId, processStepTypeId); private async Task<(IEnumerable RoleData, IDictionary? IdentityProviderIdAliase, (Guid IdentityProviderId, string Alias)? SingleIdentityProviderIdAlias, IEnumerable AllIdentityProviderIds)> ValidatePartnerRegistrationData(PartnerRegistrationData data, INetworkRepository networkRepository, IIdentityProviderRepository identityProviderRepository, Guid ownerCompanyId) { - if (string.IsNullOrWhiteSpace(data.Bpn) || !BpnRegex.IsMatch(data.Bpn)) + if (data.Bpn != null) { - throw new ControllerArgumentException("BPN must contain exactly 16 characters and must be prefixed with BPNL", nameof(data.Bpn)); - } + if (!BpnRegex.IsMatch(data.Bpn)) + { + throw new ControllerArgumentException("BPN must contain exactly 16 characters and must be prefixed with BPNL", nameof(data.Bpn)); + } - if (await _portalRepositories.GetInstance().CheckBpnExists(data.Bpn).ConfigureAwait(false)) - { - throw new ControllerArgumentException($"The Bpn {data.Bpn} already exists", nameof(data.Bpn)); + if (await _portalRepositories.GetInstance().CheckBpnExists(data.Bpn).ConfigureAwait(false)) + { + throw new ControllerArgumentException($"The Bpn {data.Bpn} already exists", nameof(data.Bpn)); + } } if (!data.CompanyRoles.Any()) @@ -307,72 +300,4 @@ private static void ValidateUsers(UserDetailData user) throw new ControllerArgumentException("Lastname does not match expected format"); } } - - public async Task Submit(PartnerSubmitData submitData, CancellationToken cancellationToken) - { - var companyId = _identityService.IdentityData.CompanyId; - var userId = _identityService.IdentityData.UserId; - var userRoleIds = await _portalRepositories.GetInstance() - .GetUserRoleIdsUntrackedAsync(_settings.InitialRoles) - .ToListAsync(cancellationToken) - .ConfigureAwait(false); - var data = await _portalRepositories.GetInstance() - .GetSubmitData(companyId, userId, userRoleIds) - .ConfigureAwait(false); - if (!data.Exists) - { - throw new NotFoundException($"Company {companyId} not found"); - } - - if (!data.IsUserInRole) - { - throw new ForbiddenException($"User must be in role {string.Join(",", _settings.InitialRoles.SelectMany(x => x.UserRoleNames))}"); - } - - if (data.CompanyApplications.Count() != 1) - { - throw new ConflictException($"Company {companyId} has no or more than one application"); - } - - if (data.ProcessId == null) - { - throw new ConflictException("There must be an process"); - } - - var companyApplication = data.CompanyApplications.Single(); - if (companyApplication.CompanyApplicationStatusId != CompanyApplicationStatusId.CREATED) - { - throw new ConflictException($"Application {companyApplication.CompanyApplicationId} is not in state CREATED"); - } - - submitData.Agreements.Where(x => x.ConsentStatusId != ConsentStatusId.ACTIVE).IfAny(inactive => - throw new ControllerArgumentException($"All agreements must be agreed to. Agreements that are not active: {string.Join(",", inactive.Select(x => x.AgreementId))}", nameof(submitData.Agreements))); - - data.CompanyRoleAgreementIds - .ExceptBy(submitData.CompanyRoles, x => x.CompanyRoleId) - .IfAny(missing => - throw new ControllerArgumentException($"CompanyRoles {string.Join(",", missing.Select(x => x.CompanyRoleId))} are missing", nameof(submitData.CompanyRoles))); - - var requiredAgreementIds = data.CompanyRoleAgreementIds - .SelectMany(x => x.AgreementIds) - .Distinct().ToImmutableList(); - - requiredAgreementIds.Except(submitData.Agreements.Where(x => x.ConsentStatusId == ConsentStatusId.ACTIVE).Select(x => x.AgreementId)) - .IfAny(missing => - throw new ControllerArgumentException($"All Agreements for the company roles must be agreed to, missing agreementIds: {string.Join(",", missing)}", nameof(submitData.Agreements))); - - _portalRepositories.GetInstance() - .CreateConsents(requiredAgreementIds.Select(agreementId => (agreementId, companyId, userId, ConsentStatusId.ACTIVE))); - - var processId = _portalRepositories.GetInstance().CreateProcess(ProcessTypeId.APPLICATION_CHECKLIST).Id; - _portalRepositories.GetInstance().AttachAndModifyCompanyApplication(companyApplication.CompanyApplicationId, - ca => - { - ca.ApplicationStatusId = CompanyApplicationStatusId.SUBMITTED; - ca.ChecklistProcessId = processId; - }); - _portalRepositories.GetInstance().CreateProcessStepRange(Enumerable.Repeat(new ValueTuple(ProcessStepTypeId.TRIGGER_CALLBACK_OSP_SUBMITTED, ProcessStepStatusId.TODO, data.ProcessId.Value), 1)); - - await _portalRepositories.SaveAsync().ConfigureAwait(false); - } } diff --git a/src/administration/Administration.Service/BusinessLogic/PartnerNetworkBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/PartnerNetworkBusinessLogic.cs index 84da8945dd..819436a29f 100644 --- a/src/administration/Administration.Service/BusinessLogic/PartnerNetworkBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/PartnerNetworkBusinessLogic.cs @@ -37,6 +37,6 @@ public PartnerNetworkBusinessLogic(IPortalRepositories portalRepositories) } /// - public IAsyncEnumerable GetAllMemberCompaniesBPNAsync() => - _portalRepositories.GetInstance().GetAllMemberCompaniesBPNAsync(); + public IAsyncEnumerable GetAllMemberCompaniesBPNAsync(IEnumerable? bpnIds) => + _portalRepositories.GetInstance().GetAllMemberCompaniesBPNAsync(bpnIds); } diff --git a/src/administration/Administration.Service/BusinessLogic/RegistrationBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/RegistrationBusinessLogic.cs index 361003fa40..8e5a021842 100644 --- a/src/administration/Administration.Service/BusinessLogic/RegistrationBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/RegistrationBusinessLogic.cs @@ -48,6 +48,7 @@ public sealed class RegistrationBusinessLogic : IRegistrationBusinessLogic private readonly IApplicationChecklistService _checklistService; private readonly IClearinghouseBusinessLogic _clearinghouseBusinessLogic; private readonly ISdFactoryBusinessLogic _sdFactoryBusinessLogic; + private readonly ILogger _logger; public RegistrationBusinessLogic( IPortalRepositories portalRepositories, @@ -55,7 +56,8 @@ public RegistrationBusinessLogic( IMailingService mailingService, IApplicationChecklistService checklistService, IClearinghouseBusinessLogic clearinghouseBusinessLogic, - ISdFactoryBusinessLogic sdFactoryBusinessLogic) + ISdFactoryBusinessLogic sdFactoryBusinessLogic, + ILogger logger) { _portalRepositories = portalRepositories; _settings = configuration.Value; @@ -63,6 +65,7 @@ public RegistrationBusinessLogic( _checklistService = checklistService; _clearinghouseBusinessLogic = clearinghouseBusinessLogic; _sdFactoryBusinessLogic = sdFactoryBusinessLogic; + _logger = logger; } public Task GetCompanyWithAddressAsync(Guid applicationId) @@ -277,6 +280,7 @@ private async Task UpdateCompanyBpnInternal(Guid applicationId, string bpn) /// public async Task ProcessClearinghouseResponseAsync(ClearinghouseResponseData data, CancellationToken cancellationToken) { + _logger.LogInformation("Process SelfDescription called with the following data {Data}", data); var result = await _portalRepositories.GetInstance().GetSubmittedApplicationIdsByBpn(data.BusinessPartnerNumber).ToListAsync(cancellationToken).ConfigureAwait(false); if (!result.Any()) { @@ -359,6 +363,8 @@ private async Task TriggerChecklistInternal(Guid applicationId, ApplicationCheck /// public async Task ProcessClearinghouseSelfDescription(SelfDescriptionResponseData data, CancellationToken cancellationToken) { + _logger.LogInformation("Process SelfDescription called with the following data {Data}", data); + var result = await _portalRepositories.GetInstance() .GetCompanyIdSubmissionStatusForApplication(data.ExternalId) .ConfigureAwait(false); diff --git a/src/administration/Administration.Service/BusinessLogic/ServiceAccountBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/ServiceAccountBusinessLogic.cs index 4004f04cbc..917b3d3da1 100644 --- a/src/administration/Administration.Service/BusinessLogic/ServiceAccountBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/ServiceAccountBusinessLogic.cs @@ -26,6 +26,7 @@ using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Enums; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Models; @@ -38,21 +39,24 @@ public class ServiceAccountBusinessLogic : IServiceAccountBusinessLogic private readonly IProvisioningManager _provisioningManager; private readonly IPortalRepositories _portalRepositories; private readonly IServiceAccountCreation _serviceAccountCreation; + private readonly IIdentityService _identityService; private readonly ServiceAccountSettings _settings; public ServiceAccountBusinessLogic( IProvisioningManager provisioningManager, IPortalRepositories portalRepositories, IOptions options, - IServiceAccountCreation serviceAccountCreation) + IServiceAccountCreation serviceAccountCreation, + IIdentityService identityService) { _provisioningManager = provisioningManager; _portalRepositories = portalRepositories; _serviceAccountCreation = serviceAccountCreation; + _identityService = identityService; _settings = options.Value; } - public async Task CreateOwnCompanyServiceAccountAsync(ServiceAccountCreationInfo serviceAccountCreationInfos, Guid companyId) + public async Task CreateOwnCompanyServiceAccountAsync(ServiceAccountCreationInfo serviceAccountCreationInfos) { if (serviceAccountCreationInfos.IamClientAuthMethod != IamClientAuthMethod.SECRET) { @@ -63,6 +67,7 @@ public async Task CreateOwnCompanyServiceAccountAsync(Ser throw new ControllerArgumentException("name must not be empty", "name"); } + var companyId = _identityService.IdentityData.CompanyId; var result = await _portalRepositories.GetInstance().GetBpnAndTechnicalUserRoleIds(companyId, _settings.ClientId).ConfigureAwait(false); if (result == default) { @@ -94,9 +99,10 @@ public async Task CreateOwnCompanyServiceAccountAsync(Ser serviceAccountData.AuthData.Secret); } - public async Task DeleteOwnCompanyServiceAccountAsync(Guid serviceAccountId, Guid companyId) + public async Task DeleteOwnCompanyServiceAccountAsync(Guid serviceAccountId) { var serviceAccountRepository = _portalRepositories.GetInstance(); + var companyId = _identityService.IdentityData.CompanyId; var result = await serviceAccountRepository.GetOwnCompanyServiceAccountWithIamServiceAccountRolesAsync(serviceAccountId, companyId).ConfigureAwait(false); if (result == default) { @@ -139,8 +145,9 @@ public async Task DeleteOwnCompanyServiceAccountAsync(Guid serviceAccountId return await _portalRepositories.SaveAsync().ConfigureAwait(false); } - public async Task GetOwnCompanyServiceAccountDetailsAsync(Guid serviceAccountId, Guid companyId) + public async Task GetOwnCompanyServiceAccountDetailsAsync(Guid serviceAccountId) { + var companyId = _identityService.IdentityData.CompanyId; var result = await _portalRepositories.GetInstance().GetOwnCompanyServiceAccountDetailedDataUntrackedAsync(serviceAccountId, companyId); if (result == null) { @@ -165,8 +172,9 @@ public async Task GetOwnCompanyServiceAccountD result.SubscriptionId); } - public async Task ResetOwnCompanyServiceAccountSecretAsync(Guid serviceAccountId, Guid companyId) + public async Task ResetOwnCompanyServiceAccountSecretAsync(Guid serviceAccountId) { + var companyId = _identityService.IdentityData.CompanyId; var result = await _portalRepositories.GetInstance().GetOwnCompanyServiceAccountDetailedDataUntrackedAsync(serviceAccountId, companyId); if (result == null) { @@ -189,7 +197,7 @@ public async Task ResetOwnCompanyServiceAccountSecretAsyn result.SubscriptionId); } - public async Task UpdateOwnCompanyServiceAccountDetailsAsync(Guid serviceAccountId, ServiceAccountEditableDetails serviceAccountDetails, Guid companyId) + public async Task UpdateOwnCompanyServiceAccountDetailsAsync(Guid serviceAccountId, ServiceAccountEditableDetails serviceAccountDetails) { if (serviceAccountDetails.IamClientAuthMethod != IamClientAuthMethod.SECRET) { @@ -199,6 +207,8 @@ public async Task UpdateOwnCompanyServiceAccountDetailsAs { throw new ArgumentException($"serviceAccountId {serviceAccountId} from path does not match the one in body {serviceAccountDetails.ServiceAccountId}", nameof(serviceAccountId)); } + + var companyId = _identityService.IdentityData.CompanyId; var serviceAccountRepository = _portalRepositories.GetInstance(); var result = await serviceAccountRepository.GetOwnCompanyServiceAccountWithIamClientIdAsync(serviceAccountId, companyId).ConfigureAwait(false); if (result == null) @@ -254,13 +264,13 @@ await _provisioningManager.UpdateCentralClientAsync( result.OfferSubscriptionId); } - public Task> GetOwnCompanyServiceAccountsDataAsync(int page, int size, Guid companyId, string? clientId, bool? isOwner) => + public Task> GetOwnCompanyServiceAccountsDataAsync(int page, int size, string? clientId, bool? isOwner) => Pagination.CreateResponseAsync( page, size, 15, - _portalRepositories.GetInstance().GetOwnCompanyServiceAccountsUntracked(companyId, clientId, isOwner)); + _portalRepositories.GetInstance().GetOwnCompanyServiceAccountsUntracked(_identityService.IdentityData.CompanyId, clientId, isOwner)); - IAsyncEnumerable IServiceAccountBusinessLogic.GetServiceAccountRolesAsync(Guid companyId, string? languageShortName) => - _portalRepositories.GetInstance().GetServiceAccountRolesAsync(companyId, _settings.ClientId, languageShortName ?? Constants.DefaultLanguage); + public IAsyncEnumerable GetServiceAccountRolesAsync(string? languageShortName) => + _portalRepositories.GetInstance().GetServiceAccountRolesAsync(_identityService.IdentityData.CompanyId, _settings.ClientId, languageShortName ?? Constants.DefaultLanguage); } diff --git a/src/administration/Administration.Service/BusinessLogic/SubscriptionConfigurationBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/SubscriptionConfigurationBusinessLogic.cs index 049e25c8cd..e349e01f19 100644 --- a/src/administration/Administration.Service/BusinessLogic/SubscriptionConfigurationBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/SubscriptionConfigurationBusinessLogic.cs @@ -24,6 +24,7 @@ using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities; using Org.Eclipse.TractusX.Portal.Backend.Processes.OfferSubscription.Library; using Org.Eclipse.TractusX.Portal.Backend.Processes.OfferSubscription.Library.Extensions; @@ -33,16 +34,19 @@ public class SubscriptionConfigurationBusinessLogic : ISubscriptionConfiguration { private readonly IOfferSubscriptionProcessService _offerSubscriptionProcessService; private readonly IPortalRepositories _portalRepositories; + private readonly IIdentityService _identityService; - public SubscriptionConfigurationBusinessLogic(IOfferSubscriptionProcessService offerSubscriptionProcessService, IPortalRepositories portalRepositories) + public SubscriptionConfigurationBusinessLogic(IOfferSubscriptionProcessService offerSubscriptionProcessService, IPortalRepositories portalRepositories, IIdentityService identityService) { _offerSubscriptionProcessService = offerSubscriptionProcessService; _portalRepositories = portalRepositories; + _identityService = identityService; } /// - public async Task GetProviderCompanyDetailsAsync(Guid companyId) + public async Task GetProviderCompanyDetailsAsync() { + var companyId = _identityService.IdentityData.CompanyId; var result = await _portalRepositories.GetInstance() .GetProviderCompanyDetailAsync(CompanyRoleId.SERVICE_PROVIDER, companyId) .ConfigureAwait(false); @@ -59,7 +63,7 @@ public async Task GetProviderCompanyDetailsAsync(Guid } /// - public Task SetProviderCompanyDetailsAsync(ProviderDetailData data, Guid companyId) + public Task SetProviderCompanyDetailsAsync(ProviderDetailData data) { data.Url.EnsureValidHttpsUrl(() => nameof(data.Url)); data.CallbackUrl?.EnsureValidHttpsUrl(() => nameof(data.CallbackUrl)); @@ -70,7 +74,7 @@ public Task SetProviderCompanyDetailsAsync(ProviderDetailData data, Guid company "the maximum allowed length is 100 characters", nameof(data.Url)); } - return SetOfferProviderCompanyDetailsInternalAsync(data, companyId); + return SetOfferProviderCompanyDetailsInternalAsync(data, _identityService.IdentityData.CompanyId); } private async Task SetOfferProviderCompanyDetailsInternalAsync(ProviderDetailData data, Guid companyId) diff --git a/src/administration/Administration.Service/BusinessLogic/UserBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/UserBusinessLogic.cs index bf8ad2fa48..4fe574bad2 100644 --- a/src/administration/Administration.Service/BusinessLogic/UserBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/UserBusinessLogic.cs @@ -28,6 +28,7 @@ using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.DBAccess; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Models; @@ -44,6 +45,7 @@ public class UserBusinessLogic : IUserBusinessLogic private readonly IUserProvisioningService _userProvisioningService; private readonly IProvisioningDBAccess _provisioningDbAccess; private readonly IPortalRepositories _portalRepositories; + private readonly IIdentityService _identityService; private readonly IMailingService _mailingService; private readonly ILogger _logger; private readonly UserSettings _settings; @@ -54,6 +56,7 @@ public class UserBusinessLogic : IUserBusinessLogic /// Provisioning Manager /// User Provisioning Service /// Provisioning DBAccess + /// Access to the identity /// Mailing Service /// logger /// Settings @@ -63,6 +66,7 @@ public UserBusinessLogic( IUserProvisioningService userProvisioningService, IProvisioningDBAccess provisioningDbAccess, IPortalRepositories portalRepositories, + IIdentityService identityService, IMailingService mailingService, ILogger logger, IOptions settings) @@ -71,12 +75,13 @@ public UserBusinessLogic( _userProvisioningService = userProvisioningService; _provisioningDbAccess = provisioningDbAccess; _portalRepositories = portalRepositories; + _identityService = identityService; _mailingService = mailingService; _logger = logger; _settings = settings.Value; } - public IAsyncEnumerable CreateOwnCompanyUsersAsync(IEnumerable userList, (Guid UserId, Guid CompanyId) identity) + public IAsyncEnumerable CreateOwnCompanyUsersAsync(IEnumerable userList) { var noUserNameAndEmail = userList.Where(user => string.IsNullOrEmpty(user.userName) && string.IsNullOrEmpty(user.eMail)); if (noUserNameAndEmail.Any()) @@ -88,16 +93,16 @@ public IAsyncEnumerable CreateOwnCompanyUsersAsync(IEnumerable user.userName ?? user.eMail))}'"); } - return CreateOwnCompanyUsersInternalAsync(userList, identity); + return CreateOwnCompanyUsersInternalAsync(userList); } - private async IAsyncEnumerable CreateOwnCompanyUsersInternalAsync(IEnumerable userList, (Guid UserId, Guid CompanyId) identity) + private async IAsyncEnumerable CreateOwnCompanyUsersInternalAsync(IEnumerable userList) { - var (companyNameIdpAliasData, nameCreatedBy) = await _userProvisioningService.GetCompanyNameSharedIdpAliasData(identity.UserId).ConfigureAwait(false); + var (companyNameIdpAliasData, nameCreatedBy) = await _userProvisioningService.GetCompanyNameSharedIdpAliasData(_identityService.IdentityData.UserId).ConfigureAwait(false); var distinctRoles = userList.SelectMany(user => user.Roles).Distinct().ToList(); - var roleDatas = await GetOwnCompanyUserRoleData(distinctRoles, identity.CompanyId).ConfigureAwait(false); + var roleDatas = await GetOwnCompanyUserRoleData(distinctRoles).ConfigureAwait(false); var userCreationInfoIdps = userList.Select(user => new UserCreationRoleDataIdpInfo( @@ -148,18 +153,19 @@ private async IAsyncEnumerable CreateOwnCompanyUsersInternalAsync(IEnume } } - private Task> GetOwnCompanyUserRoleData(IEnumerable roles, Guid companyId) + private Task> GetOwnCompanyUserRoleData(IEnumerable roles) { if (!roles.Any()) { Task.FromResult(Enumerable.Empty()); } - return _userProvisioningService.GetOwnCompanyPortalRoleDatas(_settings.Portal.KeycloakClientID, roles, companyId); + + return _userProvisioningService.GetOwnCompanyPortalRoleDatas(_settings.Portal.KeycloakClientID, roles, _identityService.IdentityData.CompanyId); } - public async Task CreateOwnCompanyIdpUserAsync(Guid identityProviderId, UserCreationInfoIdp userCreationInfo, (Guid UserId, Guid CompanyId) identity) + public async Task CreateOwnCompanyIdpUserAsync(Guid identityProviderId, UserCreationInfoIdp userCreationInfo) { - var (companyNameIdpAliasData, nameCreatedBy) = await _userProvisioningService.GetCompanyNameIdpAliasData(identityProviderId, identity.UserId).ConfigureAwait(false); + var (companyNameIdpAliasData, nameCreatedBy) = await _userProvisioningService.GetCompanyNameIdpAliasData(identityProviderId, _identityService.IdentityData.UserId).ConfigureAwait(false); var displayName = await _userProvisioningService.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(false); if (!userCreationInfo.Roles.Any()) @@ -167,7 +173,7 @@ public async Task CreateOwnCompanyIdpUserAsync(Guid identityProviderId, Us throw new ControllerArgumentException($"at least one role must be specified", nameof(userCreationInfo.Roles)); } - var roleDatas = await GetOwnCompanyUserRoleData(userCreationInfo.Roles, identity.CompanyId).ConfigureAwait(false); + var roleDatas = await GetOwnCompanyUserRoleData(userCreationInfo.Roles).ConfigureAwait(false); var result = await _userProvisioningService.CreateOwnCompanyIdpUsersAsync( companyNameIdpAliasData, @@ -217,11 +223,10 @@ public async Task CreateOwnCompanyIdpUserAsync(Guid identityProviderId, Us return result.CompanyUserId; } - public Task> GetOwnCompanyUserDatasAsync(Guid companyId, int page, int size, GetOwnCompanyUsersFilter filter) + public Task> GetOwnCompanyUserDatasAsync(int page, int size, GetOwnCompanyUsersFilter filter) { - var companyUsers = _portalRepositories.GetInstance().GetOwnCompanyUserQuery( - companyId, + _identityService.IdentityData.CompanyId, filter.CompanyUserId, filter.UserEntityId, filter.FirstName, @@ -271,8 +276,9 @@ public async IAsyncEnumerable GetClientRolesAsync(Guid appId, strin } } - public async Task GetOwnCompanyUserDetailsAsync(Guid userId, Guid companyId) + public async Task GetOwnCompanyUserDetailsAsync(Guid userId) { + var companyId = _identityService.IdentityData.CompanyId; var details = await _portalRepositories.GetInstance().GetOwnCompanyUserDetailsUntrackedAsync(userId, companyId).ConfigureAwait(false); if (details == null) { @@ -281,12 +287,13 @@ public async Task GetOwnCompanyUserDetailsAsync(Guid userId, return details; } - public async Task AddOwnCompanyUsersBusinessPartnerNumbersAsync(Guid userId, IEnumerable businessPartnerNumbers, Guid companyId) + public async Task AddOwnCompanyUsersBusinessPartnerNumbersAsync(Guid userId, IEnumerable businessPartnerNumbers) { if (businessPartnerNumbers.Any(businessPartnerNumber => businessPartnerNumber.Length > 20)) { throw new ControllerArgumentException("businessPartnerNumbers must not exceed 20 characters", nameof(businessPartnerNumbers)); } + var companyId = _identityService.IdentityData.CompanyId; var user = await _portalRepositories.GetInstance().GetOwnCompanyUserWithAssignedBusinessPartnerNumbersUntrackedAsync(userId, companyId).ConfigureAwait(false); if (user == null || user.UserEntityId == null) { @@ -303,11 +310,12 @@ public async Task AddOwnCompanyUsersBusinessPartnerNumbersAsync(Guid userId return await _portalRepositories.SaveAsync(); } - public Task AddOwnCompanyUsersBusinessPartnerNumberAsync(Guid userId, string businessPartnerNumber, Guid companyId) => - AddOwnCompanyUsersBusinessPartnerNumbersAsync(userId, Enumerable.Repeat(businessPartnerNumber, 1), companyId); + public Task AddOwnCompanyUsersBusinessPartnerNumberAsync(Guid userId, string businessPartnerNumber) => + AddOwnCompanyUsersBusinessPartnerNumbersAsync(userId, Enumerable.Repeat(businessPartnerNumber, 1)); - public async Task GetOwnUserDetails(Guid userId) + public async Task GetOwnUserDetails() { + var userId = _identityService.IdentityData.UserId; var userRoleIds = await _portalRepositories.GetInstance() .GetUserRoleIdsUntrackedAsync(_settings.UserAdminRoles).ToListAsync().ConfigureAwait(false); var details = await _portalRepositories.GetInstance().GetUserDetailsUntrackedAsync(userId, userRoleIds).ConfigureAwait(false); @@ -318,8 +326,9 @@ public async Task GetOwnUserDetails(Guid userId) return details; } - public async Task UpdateOwnUserDetails(Guid companyUserId, OwnCompanyUserEditableDetails ownCompanyUserEditableDetails, Guid userId) + public async Task UpdateOwnUserDetails(Guid companyUserId, OwnCompanyUserEditableDetails ownCompanyUserEditableDetails) { + var userId = _identityService.IdentityData.UserId; if (companyUserId != userId) { throw new ForbiddenException($"invalid userId {companyUserId} for user {userId}"); @@ -376,8 +385,9 @@ await _provisioningManager.UpdateSharedRealmUserAsync( }; } - public async Task DeleteOwnUserAsync(Guid companyUserId, Guid userId) + public async Task DeleteOwnUserAsync(Guid companyUserId) { + var userId = _identityService.IdentityData.UserId; if (companyUserId != userId) { throw new ForbiddenException($"companyUser {companyUserId} is not the id of user {userId}"); @@ -392,8 +402,9 @@ public async Task DeleteOwnUserAsync(Guid companyUserId, Guid userId) return await _portalRepositories.SaveAsync().ConfigureAwait(false); } - public async IAsyncEnumerable DeleteOwnCompanyUsersAsync(IEnumerable userIds, Guid companyId) + public async IAsyncEnumerable DeleteOwnCompanyUsersAsync(IEnumerable userIds) { + var companyId = _identityService.IdentityData.CompanyId; var iamIdpAlias = await _portalRepositories.GetInstance().GetSharedIdentityProviderIamAliasDataUntrackedAsync(companyId); await foreach (var accountData in _portalRepositories.GetInstance().GetCompanyUserAccountDataUntrackedAsync(userIds, companyId).ConfigureAwait(false)) @@ -493,8 +504,9 @@ private async Task CanResetPassword(Guid userId) return false; } - public async Task ExecuteOwnCompanyUserPasswordReset(Guid companyUserId, (Guid UserId, Guid CompanyId) identity) + public async Task ExecuteOwnCompanyUserPasswordReset(Guid companyUserId) { + var identity = _identityService.IdentityData; var idpUserName = await _portalRepositories.GetInstance().GetIdpCategoryIdByUserIdAsync(companyUserId, identity.CompanyId).ConfigureAwait(false); if (idpUserName != null && !string.IsNullOrWhiteSpace(idpUserName.TargetIamUserId) && !string.IsNullOrWhiteSpace(idpUserName.IdpName)) { @@ -508,20 +520,21 @@ public async Task ExecuteOwnCompanyUserPasswordReset(Guid companyUserId, ( throw new NotFoundException($"Cannot identify companyId or shared idp : userId {companyUserId} is not associated with admin users company {identity.CompanyId}"); } - public Task> GetOwnCompanyAppUsersAsync(Guid appId, Guid userId, int page, int size, CompanyUserFilter filter) => + public Task> GetOwnCompanyAppUsersAsync(Guid appId, int page, int size, CompanyUserFilter filter) => Pagination.CreateResponseAsync( page, size, 15, _portalRepositories.GetInstance().GetOwnCompanyAppUsersPaginationSourceAsync( appId, - userId, + _identityService.IdentityData.UserId, new[] { OfferSubscriptionStatusId.ACTIVE }, new[] { UserStatusId.ACTIVE, UserStatusId.INACTIVE }, filter)); - public async Task DeleteOwnUserBusinessPartnerNumbersAsync(Guid userId, string businessPartnerNumber, (Guid UserId, Guid CompanyId) identity) + public async Task DeleteOwnUserBusinessPartnerNumbersAsync(Guid userId, string businessPartnerNumber) { + var identity = _identityService.IdentityData; var userBusinessPartnerRepository = _portalRepositories.GetInstance(); var userWithBpn = await userBusinessPartnerRepository.GetOwnCompanyUserWithAssignedBusinessPartnerNumbersAsync(userId, identity.CompanyId, businessPartnerNumber).ConfigureAwait(false); diff --git a/src/administration/Administration.Service/BusinessLogic/UserRolesBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/UserRolesBusinessLogic.cs index ea4d9e4157..0e24a9b480 100644 --- a/src/administration/Administration.Service/BusinessLogic/UserRolesBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/UserRolesBusinessLogic.cs @@ -28,6 +28,7 @@ using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library; using System.Text.Json; @@ -38,26 +39,29 @@ public class UserRolesBusinessLogic : IUserRolesBusinessLogic private static readonly JsonSerializerOptions _options = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; private readonly IPortalRepositories _portalRepositories; private readonly IProvisioningManager _provisioningManager; + private readonly IIdentityService _identityService; private readonly UserSettings _settings; - public UserRolesBusinessLogic(IPortalRepositories portalRepositories, IProvisioningManager provisioningManager, IOptions options) + public UserRolesBusinessLogic(IPortalRepositories portalRepositories, IProvisioningManager provisioningManager, IIdentityService identityService, IOptions options) { _portalRepositories = portalRepositories; _provisioningManager = provisioningManager; + _identityService = identityService; _settings = options.Value; } - public IAsyncEnumerable GetCoreOfferRoles(Guid companyId, string? languageShortName) => - _portalRepositories.GetInstance().GetCoreOfferRolesAsync(companyId, languageShortName ?? Constants.DefaultLanguage, _settings.Portal.KeycloakClientID) + public IAsyncEnumerable GetCoreOfferRoles(string? languageShortName) => + _portalRepositories.GetInstance().GetCoreOfferRolesAsync(_identityService.IdentityData.CompanyId, languageShortName ?? Constants.DefaultLanguage, _settings.Portal.KeycloakClientID) .PreSortedGroupBy(x => x.OfferId) .Select(x => new OfferRoleInfos(x.Key, x.Select(s => new OfferRoleInfo(s.RoleId, s.RoleText, s.Description)))); - public IAsyncEnumerable GetAppRolesAsync(Guid appId, Guid companyId, string? languageShortName) => + public IAsyncEnumerable GetAppRolesAsync(Guid appId, string? languageShortName) => _portalRepositories.GetInstance() - .GetAppRolesAsync(appId, companyId, languageShortName ?? Constants.DefaultLanguage); + .GetAppRolesAsync(appId, _identityService.IdentityData.CompanyId, languageShortName ?? Constants.DefaultLanguage); - public Task> ModifyCoreOfferUserRolesAsync(Guid offerId, Guid companyUserId, IEnumerable roles, Guid companyId) + public Task> ModifyCoreOfferUserRolesAsync(Guid offerId, Guid companyUserId, IEnumerable roles) { + var companyId = _identityService.IdentityData.CompanyId; return ModifyUserRolesInternal( async () => { @@ -92,13 +96,13 @@ public Task> ModifyCoreOfferUserRolesAsync(Guid offe }); } - public Task> ModifyAppUserRolesAsync(Guid appId, Guid companyUserId, IEnumerable roles, Guid companyId) => + public Task> ModifyAppUserRolesAsync(Guid appId, Guid companyUserId, IEnumerable roles) => ModifyUserRolesInternal( () => _portalRepositories.GetInstance() - .GetAppAssignedIamClientUserDataUntrackedAsync(appId, companyUserId, companyId), + .GetAppAssignedIamClientUserDataUntrackedAsync(appId, companyUserId, _identityService.IdentityData.CompanyId), (Guid companyUserId, IEnumerable roles, Guid offerId) => _portalRepositories.GetInstance() .GetAssignedAndMatchingAppRoles(companyUserId, roles, offerId), - appId, companyUserId, roles, companyId, + appId, companyUserId, roles, _identityService.IdentityData.CompanyId, data => { var userName = $"{data.firstname} {data.lastname}"; @@ -113,13 +117,13 @@ public Task> ModifyAppUserRolesAsync(Guid appId, Gui }); [Obsolete("to be replaced by endpoint UserRolesBusinessLogic.ModifyAppUserRolesAsync. Remove as soon frontend is adjusted")] - public Task> ModifyUserRoleAsync(Guid appId, UserRoleInfo userRoleInfo, Guid companyId) => + public Task> ModifyUserRoleAsync(Guid appId, UserRoleInfo userRoleInfo) => ModifyUserRolesInternal( () => _portalRepositories.GetInstance() - .GetAppAssignedIamClientUserDataUntrackedAsync(appId, userRoleInfo.CompanyUserId, companyId), + .GetAppAssignedIamClientUserDataUntrackedAsync(appId, userRoleInfo.CompanyUserId, _identityService.IdentityData.CompanyId), (Guid companyUserId, IEnumerable roles, Guid offerId) => _portalRepositories.GetInstance() .GetAssignedAndMatchingAppRoles(companyUserId, roles, offerId), - appId, userRoleInfo.CompanyUserId, userRoleInfo.Roles, companyId, null); + appId, userRoleInfo.CompanyUserId, userRoleInfo.Roles, _identityService.IdentityData.CompanyId, null); private async Task> ModifyUserRolesInternal( Func> getIamUserData, diff --git a/src/administration/Administration.Service/BusinessLogic/UserUploadBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/UserUploadBusinessLogic.cs index a688e104c7..ef1ab4dfde 100644 --- a/src/administration/Administration.Service/BusinessLogic/UserUploadBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/UserUploadBusinessLogic.cs @@ -22,9 +22,11 @@ using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models; using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; using Org.Eclipse.TractusX.Portal.Backend.Framework.IO; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Web; using Org.Eclipse.TractusX.Portal.Backend.Mailing.SendMail; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Models; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Service; using System.Runtime.CompilerServices; @@ -36,33 +38,38 @@ public class UserUploadBusinessLogic : IUserUploadBusinessLogic private readonly IUserProvisioningService _userProvisioningService; private readonly IMailingService _mailingService; private readonly UserSettings _settings; + private readonly IIdentityService _identityService; /// /// Constructor. /// /// User Provisioning Service /// Mailing Service + /// Access to the identity Service /// Settings public UserUploadBusinessLogic( IUserProvisioningService userProvisioningService, IMailingService mailingService, + IIdentityService identityService, IOptions settings) { _userProvisioningService = userProvisioningService; _mailingService = mailingService; + _identityService = identityService; _settings = settings.Value; } - public ValueTask UploadOwnCompanyIdpUsersAsync(Guid identityProviderId, IFormFile document, (Guid UserId, Guid CompanyId) identity, CancellationToken cancellationToken) + public ValueTask UploadOwnCompanyIdpUsersAsync(Guid identityProviderId, IFormFile document, CancellationToken cancellationToken) { CsvParser.ValidateContentTypeTextCSV(document.ContentType); - return UploadOwnCompanyIdpUsersInternalAsync(identityProviderId, document, identity, cancellationToken); + return UploadOwnCompanyIdpUsersInternalAsync(identityProviderId, document, cancellationToken); } - private async ValueTask UploadOwnCompanyIdpUsersInternalAsync(Guid identityProviderId, IFormFile document, (Guid UserId, Guid CompanyId) identity, CancellationToken cancellationToken) + private async ValueTask UploadOwnCompanyIdpUsersInternalAsync(Guid identityProviderId, IFormFile document, CancellationToken cancellationToken) { using var stream = document.OpenReadStream(); + var identity = _identityService.IdentityData; var (companyNameIdpAliasData, nameCreatedBy) = await _userProvisioningService.GetCompanyNameIdpAliasData(identityProviderId, identity.UserId).ConfigureAwait(false); var validRoleData = new List(); @@ -182,17 +189,17 @@ private static (string FirstName, string LastName, string Email, string Provider return (firstName, lastName, email, providerUserName, providerUserId, roles); } - public ValueTask UploadOwnCompanySharedIdpUsersAsync(IFormFile document, (Guid UserId, Guid CompanyId) identity, CancellationToken cancellationToken) + public ValueTask UploadOwnCompanySharedIdpUsersAsync(IFormFile document, CancellationToken cancellationToken) { CsvParser.ValidateContentTypeTextCSV(document.ContentType); - return UploadOwnCompanySharedIdpUsersInternalAsync(document, identity, cancellationToken); + return UploadOwnCompanySharedIdpUsersInternalAsync(document, cancellationToken); } - private async ValueTask UploadOwnCompanySharedIdpUsersInternalAsync(IFormFile document, - (Guid UserId, Guid CompanyId) identity, CancellationToken cancellationToken) + private async ValueTask UploadOwnCompanySharedIdpUsersInternalAsync(IFormFile document, CancellationToken cancellationToken) { using var stream = document.OpenReadStream(); + var identity = _identityService.IdentityData; var (companyNameIdpAliasData, _) = await _userProvisioningService.GetCompanyNameSharedIdpAliasData(identity.UserId).ConfigureAwait(false); var validRoleData = new List(); diff --git a/src/administration/Administration.Service/Controllers/DocumentsController.cs b/src/administration/Administration.Service/Controllers/DocumentsController.cs index 9e3c564d90..4cc5c4559b 100644 --- a/src/administration/Administration.Service/Controllers/DocumentsController.cs +++ b/src/administration/Administration.Service/Controllers/DocumentsController.cs @@ -24,7 +24,6 @@ using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Library; using Org.Eclipse.TractusX.Portal.Backend.Framework.Models; using Org.Eclipse.TractusX.Portal.Backend.Framework.PublicInfos; -using Org.Eclipse.TractusX.Portal.Backend.Keycloak.Authentication; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; @@ -70,7 +69,7 @@ public DocumentsController(IDocumentsBusinessLogic documentsBusinessLogic) [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status503ServiceUnavailable)] public async Task GetDocumentContentFileAsync([FromRoute] Guid documentId) { - var (fileName, content, mediaType) = await this.WithCompanyId(companyId => _businessLogic.GetDocumentAsync(documentId, companyId).ConfigureAwait(false)); + var (fileName, content, mediaType) = await _businessLogic.GetDocumentAsync(documentId).ConfigureAwait(false); return File(content, mediaType, fileName); } @@ -115,7 +114,7 @@ public async Task GetSelfDescriptionDocumentsAsync([FromRoute] Gui [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] public Task DeleteDocumentAsync([FromRoute] Guid documentId) => - this.WithUserId(userId => _businessLogic.DeleteDocumentAsync(documentId, userId)); + _businessLogic.DeleteDocumentAsync(documentId); /// /// Gets the json the seed data for a specific document diff --git a/src/administration/Administration.Service/Controllers/IdentityProviderController.cs b/src/administration/Administration.Service/Controllers/IdentityProviderController.cs index 406418efda..f4e254c41a 100644 --- a/src/administration/Administration.Service/Controllers/IdentityProviderController.cs +++ b/src/administration/Administration.Service/Controllers/IdentityProviderController.cs @@ -24,7 +24,6 @@ using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models; using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Library; using Org.Eclipse.TractusX.Portal.Backend.Framework.Models; -using Org.Eclipse.TractusX.Portal.Backend.Keycloak.Authentication; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Enums; @@ -92,6 +91,29 @@ public async ValueTask> CreateOwnCompanyId return (ActionResult)CreatedAtRoute(nameof(GetOwnCompanyIdentityProvider), new { identityProviderId = details.identityProviderId }, details); } + /// + /// Gets a specific identity provider with the connected Companies + /// + /// Id of the identity provider + /// Returns details of the identity provider + /// + /// Example: GET: api/administration/identityprovider/network/identityproviders/managed/{identityProviderId} + /// + /// Return the details of the identityProvider. + /// The user is not associated with the owner company. + /// Unexpected value of protocol. + /// Bad Gateway Service Error. + [HttpGet] + [Authorize(Roles = "view_managed_idp")] + [Authorize(Policy = PolicyTypes.ValidCompany)] + [Route("network/identityproviders/managed/{identityProviderId}")] + [ProducesResponseType(typeof(IdentityProviderDetailsWithConnectedCompanies), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status500InternalServerError)] + [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)] + public ValueTask GetOwnIdentityProviderWithConnectedCompanies([FromRoute] Guid identityProviderId) => + _businessLogic.GetOwnIdentityProviderWithConnectedCompanies(identityProviderId); + /// /// Gets a specific identity provider /// @@ -221,7 +243,7 @@ public async Task DeleteOwnCompanyIdentityProvider([FromRoute] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)] public IAsyncEnumerable GetOwnCompanyUsersIdentityProviderDataAsync([FromQuery] IEnumerable identityProviderIds, [FromQuery] bool unlinkedUsersOnly = false) => - this.WithCompanyId(companyId => _businessLogic.GetOwnCompanyUsersIdentityProviderDataAsync(identityProviderIds, companyId, unlinkedUsersOnly)); + _businessLogic.GetOwnCompanyUsersIdentityProviderDataAsync(identityProviderIds, unlinkedUsersOnly); /// /// Gets the company users for the identity providers as a file @@ -244,7 +266,7 @@ public IAsyncEnumerable GetOwnCompanyUsersIdentityProv [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)] public IActionResult GetOwnCompanyUsersIdentityProviderFileAsync([FromQuery] IEnumerable identityProviderIds, [FromQuery] bool unlinkedUsersOnly = false) { - var (stream, contentType, fileName, encoding) = this.WithCompanyId(companyId => _businessLogic.GetOwnCompanyUsersIdentityProviderLinkDataStream(identityProviderIds, companyId, unlinkedUsersOnly)); + var (stream, contentType, fileName, encoding) = _businessLogic.GetOwnCompanyUsersIdentityProviderLinkDataStream(identityProviderIds, unlinkedUsersOnly); return File(stream, string.Join("; ", contentType, encoding.WebName), fileName); } @@ -273,7 +295,7 @@ public IActionResult GetOwnCompanyUsersIdentityProviderFileAsync([FromQuery] IEn [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status415UnsupportedMediaType)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)] public ValueTask UploadOwnCompanyUsersIdentityProviderFileAsync([FromForm(Name = "document")] IFormFile document, CancellationToken cancellationToken) => - this.WithCompanyId(companyId => _businessLogic.UploadOwnCompanyUsersIdentityProviderLinkDataAsync(document, companyId, cancellationToken)); + _businessLogic.UploadOwnCompanyUsersIdentityProviderLinkDataAsync(document, cancellationToken); /// /// Adds the user to the given identity provider @@ -305,7 +327,7 @@ public ValueTask UploadOwnCompanyUsersIdentityProvi [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)] public async ValueTask> AddOwnCompanyUserIdentityProviderDataAsync([FromRoute] Guid companyUserId, [FromBody] UserIdentityProviderLinkData identityProviderLinkData) { - var linkData = await this.WithCompanyId(companyId => _businessLogic.CreateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderLinkData, companyId)).ConfigureAwait(false); + var linkData = await _businessLogic.CreateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderLinkData).ConfigureAwait(false); return (ActionResult)CreatedAtRoute( nameof(GetOwnCompanyUserIdentityProviderDataAsync), new { companyUserId = companyUserId, identityProviderId = linkData.identityProviderId }, @@ -339,7 +361,7 @@ public async ValueTask> AddOwnCompany [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status500InternalServerError)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)] public ValueTask CreateOrUpdateOwnCompanyUserIdentityProviderDataAsync([FromRoute] Guid companyUserId, [FromRoute] Guid identityProviderId, [FromBody] UserLinkData userLinkData) => - this.WithCompanyId(companyId => _businessLogic.CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId, userLinkData, companyId)); + _businessLogic.CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId, userLinkData); /// /// Gets the given user for the given identity provider @@ -367,7 +389,7 @@ public ValueTask CreateOrUpdateOwnCompanyUserIdent [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status500InternalServerError)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)] public ValueTask GetOwnCompanyUserIdentityProviderDataAsync([FromRoute] Guid companyUserId, [FromRoute] Guid identityProviderId) => - this.WithCompanyId(companyId => _businessLogic.GetOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId, companyId)); + _businessLogic.GetOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId); /// /// Deletes the given user on the given identity provider @@ -396,7 +418,7 @@ public ValueTask GetOwnCompanyUserIdentityProvider [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)] public async ValueTask DeleteOwnCompanyUserIdentityProviderDataAsync([FromRoute] Guid companyUserId, [FromRoute] Guid identityProviderId) { - await this.WithCompanyId(companyId => _businessLogic.DeleteOwnCompanyUserIdentityProviderDataAsync(companyUserId, identityProviderId, companyId)).ConfigureAwait(false); + await _businessLogic.DeleteOwnCompanyUserIdentityProviderDataAsync(companyUserId, identityProviderId).ConfigureAwait(false); return (ActionResult)NoContent(); } } diff --git a/src/administration/Administration.Service/Controllers/NetworkController.cs b/src/administration/Administration.Service/Controllers/NetworkController.cs index 0c9d0fd64d..c0421c6977 100644 --- a/src/administration/Administration.Service/Controllers/NetworkController.cs +++ b/src/administration/Administration.Service/Controllers/NetworkController.cs @@ -1,5 +1,4 @@ /******************************************************************************** - * Copyright (c) 2021, 2023 BMW Group AG * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional @@ -70,7 +69,7 @@ public async Task PartnerRegister([FromBody] PartnerRegistrationData d /// Empty response on success. /// No registration found for the externalId. [HttpPost] - //[Authorize(Roles = "tbd")] + [Authorize(Roles = "approve_new_partner")] [Authorize(Policy = PolicyTypes.CompanyUser)] [Route("{externalId}/retrigger-synchronize-users")] [ProducesResponseType(StatusCodes.Status204NoContent)] @@ -82,28 +81,6 @@ public async Task RetriggerSynchronizeUser([FromRoute] Guid ext return NoContent(); } - /// - /// Submits the application - /// - /// The agreements for the companyRoles - /// Cancellation Token - /// NoContent - /// Example: POST: api/administration/registration/network/partnerRegistration/submit - /// Empty response on success. - /// No registration found for the externalId. - [HttpPost] - [Authorize(Roles = "submit_registration")] - [Authorize(Policy = PolicyTypes.CompanyUser)] - [Route("partnerRegistration/submit")] - [ProducesResponseType(StatusCodes.Status204NoContent)] - [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)] - [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] - public async Task Submit([FromBody] PartnerSubmitData data, CancellationToken cancellationToken) - { - await _logic.Submit(data, cancellationToken).ConfigureAwait(false); - return NoContent(); - } - /// /// Retriggers the last failed step /// @@ -113,7 +90,7 @@ public async Task Submit([FromBody] PartnerSubmitData data, Can /// Empty response on success. /// No registration found for the externalId. [HttpPost] - //[Authorize(Roles = "tbd")] + [Authorize(Roles = "approve_new_partner")] [Authorize(Policy = PolicyTypes.CompanyUser)] [Route("{externalId}/retrigger-callback-osp-approve")] [ProducesResponseType(StatusCodes.Status204NoContent)] @@ -155,7 +132,7 @@ public async Task RetriggerCallbackOspDecline([FromRoute] Guid /// Empty response on success. /// No registration found for the externalId. [HttpPost] - //[Authorize(Roles = "tbd")] + [Authorize(Roles = "approve_new_partner")] [Authorize(Policy = PolicyTypes.CompanyUser)] [Route("{externalId}/retrigger-callback-osp-submitted")] [ProducesResponseType(StatusCodes.Status204NoContent)] diff --git a/src/administration/Administration.Service/Controllers/PartnerNetworkController.cs b/src/administration/Administration.Service/Controllers/PartnerNetworkController.cs index 27b726858f..2b4401abab 100644 --- a/src/administration/Administration.Service/Controllers/PartnerNetworkController.cs +++ b/src/administration/Administration.Service/Controllers/PartnerNetworkController.cs @@ -47,6 +47,7 @@ public PartnerNetworkController(IPartnerNetworkBusinessLogic logic) } /// Get all member companies + /// BPN Id's /// Returns all the active member companies bpn. /// Example: GET: api/administration/partnernetwork/memberCompanies /// Returns all the active member companies bpn. @@ -56,6 +57,6 @@ public PartnerNetworkController(IPartnerNetworkBusinessLogic logic) [Route("memberCompanies")] [ProducesResponseType(StatusCodes.Status200OK)] [PublicUrl(CompanyRoleId.ACTIVE_PARTICIPANT, CompanyRoleId.SERVICE_PROVIDER, CompanyRoleId.APP_PROVIDER)] - public IAsyncEnumerable GetAllMemberCompaniesBPNAsync() => - _logic.GetAllMemberCompaniesBPNAsync(); + public IAsyncEnumerable GetAllMemberCompaniesBPNAsync([FromQuery] IEnumerable? bpnIds = null) => + _logic.GetAllMemberCompaniesBPNAsync(bpnIds); } diff --git a/src/administration/Administration.Service/Controllers/ServiceAccountController.cs b/src/administration/Administration.Service/Controllers/ServiceAccountController.cs index 2ec3e28caa..21944bb1fc 100644 --- a/src/administration/Administration.Service/Controllers/ServiceAccountController.cs +++ b/src/administration/Administration.Service/Controllers/ServiceAccountController.cs @@ -65,7 +65,7 @@ public ServiceAccountController(IServiceAccountBusinessLogic logic) [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] public async Task ExecuteCompanyUserCreation([FromBody] ServiceAccountCreationInfo serviceAccountCreationInfo) { - var serviceAccountDetails = await this.WithCompanyId(companyId => _logic.CreateOwnCompanyServiceAccountAsync(serviceAccountCreationInfo, companyId).ConfigureAwait(false)); + var serviceAccountDetails = await _logic.CreateOwnCompanyServiceAccountAsync(serviceAccountCreationInfo).ConfigureAwait(false); return CreatedAtRoute("GetServiceAccountDetails", new { serviceAccountId = serviceAccountDetails.ServiceAccountId }, serviceAccountDetails); } @@ -86,7 +86,7 @@ public async Task ExecuteCompanyUserCreation([FromBody] Se [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status409Conflict)] public Task DeleteServiceAccount([FromRoute] Guid serviceAccountId) => - this.WithCompanyId(companyId => _logic.DeleteOwnCompanyServiceAccountAsync(serviceAccountId, companyId)); + _logic.DeleteOwnCompanyServiceAccountAsync(serviceAccountId); /// /// Gets the service account details for the given id @@ -105,7 +105,7 @@ public Task DeleteServiceAccount([FromRoute] Guid serviceAccountId) => [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status409Conflict)] public Task GetServiceAccountDetails([FromRoute] Guid serviceAccountId) => - this.WithCompanyId(companyId => _logic.GetOwnCompanyServiceAccountDetailsAsync(serviceAccountId, companyId)); + _logic.GetOwnCompanyServiceAccountDetailsAsync(serviceAccountId); /// /// Updates the service account details with the given id. @@ -132,7 +132,7 @@ public Task GetServiceAccountDetails([FromRout [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status409Conflict)] public Task PutServiceAccountDetails([FromRoute] Guid serviceAccountId, [FromBody] ServiceAccountEditableDetails serviceAccountDetails) => - this.WithCompanyId(companyId => _logic.UpdateOwnCompanyServiceAccountDetailsAsync(serviceAccountId, serviceAccountDetails, companyId)); + _logic.UpdateOwnCompanyServiceAccountDetailsAsync(serviceAccountId, serviceAccountDetails); /// /// Resets the service account credentials for the given service account Id. @@ -154,7 +154,7 @@ public Task PutServiceAccountDetails([FromRoute] Guid ser [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status409Conflict)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)] public Task ResetServiceAccountCredentials([FromRoute] Guid serviceAccountId) => - this.WithCompanyId(companyId => _logic.ResetOwnCompanyServiceAccountSecretAsync(serviceAccountId, companyId)); + _logic.ResetOwnCompanyServiceAccountSecretAsync(serviceAccountId); /// /// Gets the service account data as pagination @@ -172,7 +172,7 @@ public Task ResetServiceAccountCredentials([FromRoute] Gu [Route("owncompany/serviceaccounts")] [ProducesResponseType(typeof(Pagination.Response), StatusCodes.Status200OK)] public Task> GetServiceAccountsData([FromQuery] int page, [FromQuery] int size, [FromQuery] bool? isOwner, [FromQuery] string? clientId) => - this.WithCompanyId(companyId => _logic.GetOwnCompanyServiceAccountsDataAsync(page, size, companyId, clientId, isOwner)); + _logic.GetOwnCompanyServiceAccountsDataAsync(page, size, clientId, isOwner); /// /// Get all service account roles @@ -187,5 +187,5 @@ public Task ResetServiceAccountCredentials([FromRoute] Gu [Route("user/roles")] [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] public IAsyncEnumerable GetServiceAccountRolesAsync(string? languageShortName = null) => - this.WithCompanyId(companyId => _logic.GetServiceAccountRolesAsync(companyId, languageShortName)); + _logic.GetServiceAccountRolesAsync(languageShortName); } diff --git a/src/administration/Administration.Service/Controllers/SubscriptionConfigurationController.cs b/src/administration/Administration.Service/Controllers/SubscriptionConfigurationController.cs index dba22e0a8c..5c1345f50d 100644 --- a/src/administration/Administration.Service/Controllers/SubscriptionConfigurationController.cs +++ b/src/administration/Administration.Service/Controllers/SubscriptionConfigurationController.cs @@ -69,7 +69,7 @@ public SubscriptionConfigurationController(ISubscriptionConfigurationBusinessLog [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status409Conflict)] [PublicUrl(CompanyRoleId.SERVICE_PROVIDER, CompanyRoleId.APP_PROVIDER)] public Task GetServiceProviderCompanyDetail() => - this.WithCompanyId(companyId => _businessLogic.GetProviderCompanyDetailsAsync(companyId)); + _businessLogic.GetProviderCompanyDetailsAsync(); /// /// Sets detail data to the calling users service provider @@ -91,7 +91,7 @@ public Task GetServiceProviderCompanyDetail() => [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] public async Task SetProviderCompanyDetail([FromBody] ProviderDetailData data) { - await this.WithCompanyId(companyId => _businessLogic.SetProviderCompanyDetailsAsync(data, companyId)).ConfigureAwait(false); + await _businessLogic.SetProviderCompanyDetailsAsync(data).ConfigureAwait(false); return NoContent(); } diff --git a/src/administration/Administration.Service/Controllers/UserController.cs b/src/administration/Administration.Service/Controllers/UserController.cs index ab44558c89..d2fa9a5b43 100644 --- a/src/administration/Administration.Service/Controllers/UserController.cs +++ b/src/administration/Administration.Service/Controllers/UserController.cs @@ -69,7 +69,7 @@ public UserController(IUserBusinessLogic logic, IUserUploadBusinessLogic uploadL [ProducesResponseType(typeof(IAsyncEnumerable), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)] public IAsyncEnumerable CreateOwnCompanyUsers([FromBody] IEnumerable usersToCreate) => - this.WithUserIdAndCompanyId(identity => _logic.CreateOwnCompanyUsersAsync(usersToCreate, identity)); + _logic.CreateOwnCompanyUsersAsync(usersToCreate); /// /// Create new users for the companies shared identityprovider by upload of csv-file @@ -96,7 +96,7 @@ public IAsyncEnumerable CreateOwnCompanyUsers([FromBody] IEnumerable UploadOwnCompanySharedIdpUsersFileAsync([FromForm(Name = "document")] IFormFile document, CancellationToken cancellationToken) => - this.WithUserIdAndCompanyId(identity => _uploadLogic.UploadOwnCompanySharedIdpUsersAsync(document, identity, cancellationToken)); + _uploadLogic.UploadOwnCompanySharedIdpUsersAsync(document, cancellationToken); /// /// Create a new user for a specific identityprovider @@ -124,7 +124,7 @@ public ValueTask UploadOwnCompanySharedIdpUsersFileAsync([Fro [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status409Conflict)] public async Task CreateOwnIdpOwnCompanyUser([FromBody] UserCreationInfoIdp userToCreate, [FromRoute] Guid identityProviderId) { - var result = await this.WithUserIdAndCompanyId(identity => _logic.CreateOwnCompanyIdpUserAsync(identityProviderId, userToCreate, identity)).ConfigureAwait(false); + var result = await _logic.CreateOwnCompanyIdpUserAsync(identityProviderId, userToCreate).ConfigureAwait(false); return CreatedAtRoute(nameof(GetOwnCompanyUserDetails), new { companyUserId = result }, result); } @@ -154,7 +154,7 @@ public async Task CreateOwnIdpOwnCompanyUser([FromBody] Us [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status415UnsupportedMediaType)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)] public ValueTask UploadOwnCompanyUsersIdentityProviderFileAsync([FromRoute] Guid identityProviderId, [FromForm(Name = "document")] IFormFile document, CancellationToken cancellationToken) => - this.WithUserIdAndCompanyId(identity => _uploadLogic.UploadOwnCompanyIdpUsersAsync(identityProviderId, document, identity, cancellationToken)); + _uploadLogic.UploadOwnCompanyIdpUsersAsync(identityProviderId, document, cancellationToken); /// /// Get Company User Data @@ -183,11 +183,10 @@ public ValueTask UploadOwnCompanyUsersIdentityProviderFileAsy [FromQuery] string? firstName = null, [FromQuery] string? lastName = null, [FromQuery] string? email = null) => - this.WithCompanyId(companyId => _logic.GetOwnCompanyUserDatasAsync( - companyId, + _logic.GetOwnCompanyUserDatasAsync( page, size, - new(companyUserId, userEntityId, firstName, lastName, email))); + new(companyUserId, userEntityId, firstName, lastName, email)); /// /// Gets the user details for the given user Id @@ -204,7 +203,7 @@ public ValueTask UploadOwnCompanyUsersIdentityProviderFileAsy [ProducesResponseType(typeof(CompanyUserDetails), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] public Task GetOwnCompanyUserDetails([FromRoute] Guid companyUserId) => - this.WithCompanyId(companyId => _logic.GetOwnCompanyUserDetailsAsync(companyUserId, companyId)); + _logic.GetOwnCompanyUserDetailsAsync(companyUserId); /// /// Updates the portal-roles for the user @@ -225,7 +224,7 @@ public Task GetOwnCompanyUserDetails([FromRoute] Guid compan [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] public Task> ModifyCoreUserRolesAsync([FromRoute] Guid companyUserId, [FromRoute] Guid offerId, [FromBody] IEnumerable roles) => - this.WithCompanyId(companyId => _rolesLogic.ModifyCoreOfferUserRolesAsync(offerId, companyUserId, roles, companyId)); + _rolesLogic.ModifyCoreOfferUserRolesAsync(offerId, companyUserId, roles); /// /// Updates the app-roles for the user @@ -246,7 +245,7 @@ public Task> ModifyCoreUserRolesAsync([FromRoute] Gu [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] public Task> ModifyAppUserRolesAsync([FromRoute] Guid companyUserId, [FromRoute] Guid appId, [FromBody] IEnumerable roles) => - this.WithCompanyId(companyId => _rolesLogic.ModifyAppUserRolesAsync(appId, companyUserId, roles, companyId)); + _rolesLogic.ModifyAppUserRolesAsync(appId, companyUserId, roles); /// /// Adds the given business partner numbers to the user for the given id. @@ -266,7 +265,7 @@ public Task> ModifyAppUserRolesAsync([FromRoute] Gui [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] public Task AddOwnCompanyUserBusinessPartnerNumbers(Guid companyUserId, IEnumerable businessPartnerNumbers) => - this.WithCompanyId(companyId => _logic.AddOwnCompanyUsersBusinessPartnerNumbersAsync(companyUserId, businessPartnerNumbers, companyId)); + _logic.AddOwnCompanyUsersBusinessPartnerNumbersAsync(companyUserId, businessPartnerNumbers); /// /// Adds the given business partner number to the user for the given id. @@ -290,7 +289,7 @@ public Task AddOwnCompanyUserBusinessPartnerNumbers(Guid companyUserId, IEn [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status500InternalServerError)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)] public Task AddOwnCompanyUserBusinessPartnerNumber(Guid companyUserId, string businessPartnerNumber) => - this.WithCompanyId(companyId => _logic.AddOwnCompanyUsersBusinessPartnerNumberAsync(companyUserId, businessPartnerNumber, companyId)); + _logic.AddOwnCompanyUsersBusinessPartnerNumberAsync(companyUserId, businessPartnerNumber); /// /// Deletes the users with the given ids. @@ -308,7 +307,7 @@ public Task AddOwnCompanyUserBusinessPartnerNumber(Guid companyUserId, stri [ProducesResponseType(typeof(IAsyncEnumerable), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] public IAsyncEnumerable DeleteOwnCompanyUsers([FromBody] IEnumerable usersToDelete) => - this.WithCompanyId(companyId => _logic.DeleteOwnCompanyUsersAsync(usersToDelete, companyId)); + _logic.DeleteOwnCompanyUsersAsync(usersToDelete); /// /// Resets the password for the given user @@ -330,7 +329,7 @@ public IAsyncEnumerable DeleteOwnCompanyUsers([FromBody] IEnumerable [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status500InternalServerError)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)] public Task ResetOwnCompanyUserPassword([FromRoute] Guid companyUserId) => - this.WithUserIdAndCompanyId(identity => _logic.ExecuteOwnCompanyUserPasswordReset(companyUserId, identity)); + _logic.ExecuteOwnCompanyUserPasswordReset(companyUserId); /// /// Gets the core offer roles @@ -348,7 +347,7 @@ public Task ResetOwnCompanyUserPassword([FromRoute] Guid companyUserId) => [Route("owncompany/roles/coreoffers")] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] public IAsyncEnumerable GetCoreOfferRoles([FromQuery] string? languageShortName = null) => - this.WithCompanyId(companyId => _rolesLogic.GetCoreOfferRoles(companyId, languageShortName)); + _rolesLogic.GetCoreOfferRoles(languageShortName); /// /// Gets the client roles for the given app. @@ -366,7 +365,7 @@ public IAsyncEnumerable GetCoreOfferRoles([FromQuery] string? la [Route("owncompany/roles/apps/{appId}")] [ProducesResponseType(typeof(OfferRoleInfos), StatusCodes.Status200OK)] public IAsyncEnumerable GetAppRolesAsync([FromRoute] Guid appId, [FromQuery] string? languageShortName = null) => - this.WithCompanyId(companyId => _rolesLogic.GetAppRolesAsync(appId, companyId, languageShortName)); + _rolesLogic.GetAppRolesAsync(appId, languageShortName); /// /// Gets the client roles for the given app. @@ -402,7 +401,7 @@ public IAsyncEnumerable GetClientRolesAsync([FromRoute] Guid appId, [ProducesResponseType(typeof(CompanyOwnUserDetails), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] public Task GetOwnUserDetails() => - this.WithUserId(userId => _logic.GetOwnUserDetails(userId)); + _logic.GetOwnUserDetails(); /// /// Updates the user details for the given companyUserId. @@ -421,7 +420,7 @@ public Task GetOwnUserDetails() => [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] public Task UpdateOwnUserDetails([FromRoute] Guid companyUserId, [FromBody] OwnCompanyUserEditableDetails ownCompanyUserEditableDetails) => - this.WithUserId(userId => _logic.UpdateOwnUserDetails(companyUserId, ownCompanyUserEditableDetails, userId)); + _logic.UpdateOwnUserDetails(companyUserId, ownCompanyUserEditableDetails); /// /// Deletes the own user @@ -440,7 +439,7 @@ public Task UpdateOwnUserDetails([FromRoute] Guid companyUse [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status409Conflict)] public Task DeleteOwnUser([FromRoute] Guid companyUserId) => - this.WithUserId(userId => _logic.DeleteOwnUserAsync(companyUserId, userId)); + _logic.DeleteOwnUserAsync(companyUserId); /// /// Get for given app id all the company assigned users @@ -470,9 +469,8 @@ public Task DeleteOwnUser([FromRoute] Guid companyUserId) => [FromQuery] string? email = null, [FromQuery] string? roleName = null, [FromQuery] bool? hasRole = null) => - this.WithUserId(userId => _logic.GetOwnCompanyAppUsersAsync( + _logic.GetOwnCompanyAppUsersAsync( appId, - userId, page, size, new CompanyUserFilter( @@ -480,7 +478,7 @@ public Task DeleteOwnUser([FromRoute] Guid companyUserId) => lastName, email, roleName, - hasRole))); + hasRole)); /// /// Updates the roles for the user @@ -501,7 +499,7 @@ public Task DeleteOwnUser([FromRoute] Guid companyUserId) => [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] public Task> ModifyUserRolesAsync([FromRoute] Guid appId, [FromBody] UserRoleInfo userRoleInfo) => - this.WithCompanyId(companyId => _rolesLogic.ModifyUserRoleAsync(appId, userRoleInfo, companyId)); + _rolesLogic.ModifyUserRoleAsync(appId, userRoleInfo); /// /// Delete BPN assigned to user from DB and Keycloack. @@ -523,5 +521,5 @@ public Task> ModifyUserRolesAsync([FromRoute] Guid a [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status409Conflict)] public Task DeleteOwnCompanyUserBusinessPartnerNumber([FromRoute] Guid companyUserId, [FromRoute] string businessPartnerNumber) => - this.WithUserIdAndCompanyId(identity => _logic.DeleteOwnUserBusinessPartnerNumbersAsync(companyUserId, businessPartnerNumber, identity)); + _logic.DeleteOwnUserBusinessPartnerNumbersAsync(companyUserId, businessPartnerNumber); } diff --git a/src/administration/Administration.Service/Models/IdentityProviderDetailsWithConnectedCompanies.cs b/src/administration/Administration.Service/Models/IdentityProviderDetailsWithConnectedCompanies.cs new file mode 100644 index 0000000000..2bafac36de --- /dev/null +++ b/src/administration/Administration.Service/Models/IdentityProviderDetailsWithConnectedCompanies.cs @@ -0,0 +1,35 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 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.PortalBackend.DBAccess.Models; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; + +namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models; + +public record IdentityProviderDetailsWithConnectedCompanies +( + Guid IdentityProviderId, + string? Alias, + IdentityProviderCategoryId IdentityProviderCategoryId, + IdentityProviderTypeId IdentityProviderTypeId, + string? DisplayName, + string? RedirectUrl, + bool? Enabled, + IEnumerable ConnectedCompanies +); diff --git a/src/administration/Administration.Service/Models/PartnerSubmitData.cs b/src/administration/Administration.Service/Models/PartnerSubmitData.cs deleted file mode 100644 index 6c91c94cb3..0000000000 --- a/src/administration/Administration.Service/Models/PartnerSubmitData.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; - -namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models; - -public record PartnerSubmitData -( - IEnumerable CompanyRoles, - IEnumerable Agreements -); diff --git a/src/administration/Administration.Service/appsettings.json b/src/administration/Administration.Service/appsettings.json index 75fc7b1791..b445e1186b 100644 --- a/src/administration/Administration.Service/appsettings.json +++ b/src/administration/Administration.Service/appsettings.json @@ -354,13 +354,6 @@ "EmailTemplateType": "PortalRegistrationDecline" } }, - { - "Name": "OspWelcomeMail", - "Setting": { - "Subject": "Welcome to Catena-X - Your user account has been created.", - "EmailTemplateType": "OspWelcomeMail" - } - }, { "Name": "CredentialApproval", "Setting": { diff --git a/src/externalsystems/Bpdm.Library/BusinessLogic/BpdmBusinessLogic.cs b/src/externalsystems/Bpdm.Library/BusinessLogic/BpdmBusinessLogic.cs index a197ddf291..e0ce7487c1 100644 --- a/src/externalsystems/Bpdm.Library/BusinessLogic/BpdmBusinessLogic.cs +++ b/src/externalsystems/Bpdm.Library/BusinessLogic/BpdmBusinessLogic.cs @@ -108,6 +108,11 @@ public BpdmBusinessLogic(IPortalRepositories portalRepositories, IBpdmService bp } var sharingState = await _bpdmService.GetSharingState(context.ApplicationId, cancellationToken).ConfigureAwait(false); + if (sharingState.SharingProcessStarted == null) + { + return new IApplicationChecklistService.WorkerChecklistProcessStepExecutionResult(ProcessStepStatusId.TODO, null, null, null, false, "SharingProcessStarted was not set"); + } + return sharingState.SharingStateType switch { BpdmSharingStateType.Success => diff --git a/src/externalsystems/Bpdm.Library/Models/BpdmSharingState.cs b/src/externalsystems/Bpdm.Library/Models/BpdmSharingState.cs index dc6086a8a8..0f2ecba27e 100644 --- a/src/externalsystems/Bpdm.Library/Models/BpdmSharingState.cs +++ b/src/externalsystems/Bpdm.Library/Models/BpdmSharingState.cs @@ -24,13 +24,13 @@ public record BpdmPaginationSharingStateOutput( ); public record BpdmSharingState( - BpdmSharingStateBusinessPartnerType BusinessPartnerType, + BpdmSharingStateBusinessPartnerType? BusinessPartnerType, Guid ExternalId, - BpdmSharingStateType SharingStateType, + BpdmSharingStateType? SharingStateType, string? SharingErrorCode, string? SharingErrorMessage, string? Bpn, - DateTimeOffset SharingProcessStarted + DateTimeOffset? SharingProcessStarted ); public enum BpdmSharingStateType diff --git a/src/externalsystems/OfferProvider.Library/BusinessLogic/OfferProviderBusinessLogic.cs b/src/externalsystems/OfferProvider.Library/BusinessLogic/OfferProviderBusinessLogic.cs index 8f8a365362..87d9f3ed28 100644 --- a/src/externalsystems/OfferProvider.Library/BusinessLogic/OfferProviderBusinessLogic.cs +++ b/src/externalsystems/OfferProvider.Library/BusinessLogic/OfferProviderBusinessLogic.cs @@ -18,15 +18,12 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -using Microsoft.Extensions.Options; using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; -using Org.Eclipse.TractusX.Portal.Backend.OfferProvider.Library.DependencyInjection; using Org.Eclipse.TractusX.Portal.Backend.OfferProvider.Library.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library; -using System.Text.Json; namespace Org.Eclipse.TractusX.Portal.Backend.OfferProvider.Library.BusinessLogic; @@ -35,7 +32,6 @@ public class OfferProviderBusinessLogic : IOfferProviderBusinessLogic private readonly IPortalRepositories _portalRepositories; private readonly IOfferProviderService _offerProviderService; private readonly IProvisioningManager _provisioningManager; - private readonly OfferProviderSettings _settings; /// /// Constructor. @@ -47,13 +43,11 @@ public class OfferProviderBusinessLogic : IOfferProviderBusinessLogic public OfferProviderBusinessLogic( IPortalRepositories portalRepositories, IOfferProviderService offerProviderService, - IProvisioningManager provisioningManager, - IOptions options) + IProvisioningManager provisioningManager) { _portalRepositories = portalRepositories; _offerProviderService = offerProviderService; _provisioningManager = provisioningManager; - _settings = options.Value; } /// @@ -77,7 +71,7 @@ public OfferProviderBusinessLogic( new OfferThirdPartyAutoSetupCustomerData( data.CompanyInformationData.OrganizationName, data.CompanyInformationData.Country, - data.UserEmail), + data.CompanyInformationData.CompanyUserEmail), new OfferThirdPartyAutoSetupPropertyData( data.CompanyInformationData.BusinessPartnerNumber, offerSubscriptionId, @@ -88,15 +82,6 @@ await _offerProviderService .ConfigureAwait(false); } - var content = JsonSerializer.Serialize(new - { - AppName = data.OfferName, - data.OfferId, - RequestorCompanyName = data.CompanyInformationData.OrganizationName, - data.UserEmail, - AutoSetupExecuted = triggerProvider - }); - await SendNotifications(data.OfferId, data.OfferTypeId, data.SalesManagerId, data.CompanyUserId, content).ConfigureAwait(false); return ( new[] { data.IsSingleInstance ? @@ -107,56 +92,6 @@ await _offerProviderService null); } - private async Task SendNotifications( - Guid offerId, - OfferTypeId offerTypeId, - Guid? salesManagerId, - Guid companyUserId, - string notificationContent) - { - var serviceManagerRoles = _settings.ServiceManagerRoles; - var notificationRepository = _portalRepositories.GetInstance(); - - var notificationTypeId = offerTypeId == OfferTypeId.SERVICE ? NotificationTypeId.SERVICE_REQUEST : NotificationTypeId.APP_SUBSCRIPTION_REQUEST; - if (salesManagerId.HasValue) - { - notificationRepository.CreateNotification(salesManagerId.Value, notificationTypeId, false, - notification => - { - notification.CreatorUserId = companyUserId; - notification.Content = notificationContent; - }); - } - - var userRolesRepository = _portalRepositories.GetInstance(); - var roleData = await userRolesRepository - .GetUserRoleIdsUntrackedAsync(serviceManagerRoles) - .ToListAsync() - .ConfigureAwait(false); - if (roleData.Count < serviceManagerRoles.Sum(clientRoles => clientRoles.UserRoleNames.Count())) - { - throw new ConfigurationException($"invalid configuration, at least one of the configured roles does not exist in the database: {string.Join(", ", serviceManagerRoles.Select(clientRoles => $"client: {clientRoles.ClientId}, roles: [{string.Join(", ", clientRoles.UserRoleNames)}]"))}"); - } - - await foreach (var receiver in _portalRepositories.GetInstance().GetServiceProviderCompanyUserWithRoleIdAsync(offerId, roleData)) - { - if (salesManagerId.HasValue && receiver == salesManagerId.Value) - { - continue; - } - - notificationRepository.CreateNotification( - receiver, - notificationTypeId, - false, - notification => - { - notification.CreatorUserId = companyUserId; - notification.Content = notificationContent; - }); - } - } - /// public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> TriggerProviderCallback(Guid offerSubscriptionId, CancellationToken cancellationToken) { diff --git a/src/externalsystems/OnboardingServiceProvider.Library/Models/OnboardingServiceProviderCallbackData.cs b/src/externalsystems/OnboardingServiceProvider.Library/Models/OnboardingServiceProviderCallbackData.cs index 8d4a700c61..4d37ed66cf 100644 --- a/src/externalsystems/OnboardingServiceProvider.Library/Models/OnboardingServiceProviderCallbackData.cs +++ b/src/externalsystems/OnboardingServiceProvider.Library/Models/OnboardingServiceProviderCallbackData.cs @@ -34,7 +34,7 @@ namespace Org.Eclipse.TractusX.Portal.Backend.OnboardingServiceProvider.Library. public record OnboardingServiceProviderCallbackData( [property: JsonPropertyName("externalId")] Guid ExternalId, [property: JsonPropertyName("applicationId")] Guid ApplicationId, - [property: JsonPropertyName("bpn")] string Bpn, + [property: JsonPropertyName("bpn")] string? Bpn, [property: JsonPropertyName("status")] CompanyApplicationStatusId? Status, [property: JsonPropertyName("message")] string? Message ); diff --git a/src/externalsystems/OnboardingServiceProvider.Library/OnboardingServiceProviderBusinessLogic.cs b/src/externalsystems/OnboardingServiceProvider.Library/OnboardingServiceProviderBusinessLogic.cs index edde5baa74..3d02632f05 100644 --- a/src/externalsystems/OnboardingServiceProvider.Library/OnboardingServiceProviderBusinessLogic.cs +++ b/src/externalsystems/OnboardingServiceProvider.Library/OnboardingServiceProviderBusinessLogic.cs @@ -57,11 +57,6 @@ public OnboardingServiceProviderBusinessLogic(IOnboardingServiceProviderService throw new UnexpectedConditionException("No external registration found"); } - if (string.IsNullOrWhiteSpace(data.Bpn)) - { - throw new UnexpectedConditionException("Bpn must be set"); - } - if (processStepTypeId == ProcessStepTypeId.TRIGGER_CALLBACK_OSP_DECLINED && data.Comments.Count() != 1) { throw new UnexpectedConditionException("Message for decline should be set"); diff --git a/src/framework/Framework.Logging/Framework.Logging.csproj b/src/framework/Framework.Logging/Framework.Logging.csproj index ce1dea0d8d..0504174a44 100644 --- a/src/framework/Framework.Logging/Framework.Logging.csproj +++ b/src/framework/Framework.Logging/Framework.Logging.csproj @@ -1,42 +1,43 @@ - - - - - - Org.Eclipse.TractusX.Portal.Backend.Framework.Logging - Org.Eclipse.TractusX.Portal.Backend.Framework.Logging - net7.0 - enable - enable - - - - - - - - - - - - - - + + + + + + Org.Eclipse.TractusX.Portal.Backend.Framework.Logging + Org.Eclipse.TractusX.Portal.Backend.Framework.Logging + net7.0 + enable + enable + + + + + + + + + + + + + + + diff --git a/src/framework/Framework.Logging/LoggingExtensions.cs b/src/framework/Framework.Logging/LoggingExtensions.cs index 060e636493..32da331a69 100644 --- a/src/framework/Framework.Logging/LoggingExtensions.cs +++ b/src/framework/Framework.Logging/LoggingExtensions.cs @@ -20,8 +20,10 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Logging.MaskingOperator; using Serilog; using Serilog.Core; +using Serilog.Enrichers.Sensitive; using Serilog.Events; using Serilog.Formatting.Json; @@ -38,6 +40,12 @@ public static IHostBuilder AddLogging(this IHostBuilder host, Action { configuration + .Enrich.WithSensitiveDataMasking(opt => + { + opt.Mode = MaskingMode.Globally; + opt.MaskValue = "*****"; + opt.MaskingOperators.Add(new SecretOperator()); + }) .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning) .ReadFrom.Configuration(context.Configuration) .WriteTo.Console(new JsonFormatter(renderMessage: true)); @@ -57,6 +65,12 @@ public static void EnsureInitialized() return; Log.Logger = new LoggerConfiguration() + .Enrich.WithSensitiveDataMasking(opt => + { + opt.Mode = MaskingMode.Globally; + opt.MaskValue = "*****"; + opt.MaskingOperators.Add(new SecretOperator()); + }) .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning) .WriteTo.Console(new JsonFormatter(renderMessage: true)) .CreateBootstrapLogger(); diff --git a/src/framework/Framework.Logging/MaskingOperator/SecretOperator.cs b/src/framework/Framework.Logging/MaskingOperator/SecretOperator.cs new file mode 100644 index 0000000000..d763b2065f --- /dev/null +++ b/src/framework/Framework.Logging/MaskingOperator/SecretOperator.cs @@ -0,0 +1,37 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 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 Serilog.Enrichers.Sensitive; +using System.Text.RegularExpressions; + +namespace Org.Eclipse.TractusX.Portal.Backend.Framework.Logging.MaskingOperator; + +public class SecretOperator : RegexMaskingOperator +{ + private const string SecretPattern = "(secret|password)=(.*?)&"; + + public SecretOperator() + : base(SecretPattern, RegexOptions.IgnoreCase | RegexOptions.Compiled) + { + } + + protected override string PreprocessMask(string mask, Match match) => $"{match.Groups[1]}={mask}&"; + + protected override bool ShouldMaskInput(string input) => input.Contains("secret=", StringComparison.InvariantCultureIgnoreCase) || input.Contains("password=", StringComparison.InvariantCultureIgnoreCase); +} diff --git a/src/framework/Framework.Web/IdentityService.cs b/src/framework/Framework.Web/IdentityService.cs index 821a15f567..8e9c6926ec 100644 --- a/src/framework/Framework.Web/IdentityService.cs +++ b/src/framework/Framework.Web/IdentityService.cs @@ -28,6 +28,7 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Framework.Web; public class IdentityService : IIdentityService { private readonly IHttpContextAccessor _httpContextAccessor; + private IdentityData? _identityData; public IdentityService(IHttpContextAccessor httpContextAccessor) { @@ -36,6 +37,6 @@ public IdentityService(IHttpContextAccessor httpContextAccessor) /// public IdentityData IdentityData => - _httpContextAccessor.HttpContext?.User.GetIdentityData() ?? - throw new ConflictException("The identity should be set here"); + _identityData ??= _httpContextAccessor.HttpContext?.User.GetIdentityData() + ?? throw new ConflictException("The identity should be set here"); } diff --git a/src/keycloak/Keycloak.Authentication/ControllerExtensions.cs b/src/keycloak/Keycloak.Authentication/ControllerExtensions.cs index 0b6baabd59..bb08ffe2d7 100644 --- a/src/keycloak/Keycloak.Authentication/ControllerExtensions.cs +++ b/src/keycloak/Keycloak.Authentication/ControllerExtensions.cs @@ -32,24 +32,9 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Keycloak.Authentication; /// public static class ControllerExtensions { - public static T WithIdentityData(this ControllerBase controller, Func consumingFunction) => - consumingFunction(controller.User.GetIdentityData()); - - public static T WithUserId(this ControllerBase controller, Func consumingFunction) => - consumingFunction(controller.User.Claims.GetGuidFromClaim(PortalClaimTypes.IdentityId)); - - public static T WithCompanyId(this ControllerBase controller, Func consumingFunction) => - consumingFunction(controller.User.Claims.GetGuidFromClaim(PortalClaimTypes.CompanyId)); - - public static T WithUserIdAndCompanyId(this ControllerBase controller, Func<(Guid UserId, Guid CompanyId), T> consumingFunction) => - consumingFunction((controller.User.Claims.GetGuidFromClaim(PortalClaimTypes.IdentityId), controller.User.Claims.GetGuidFromClaim(PortalClaimTypes.CompanyId))); - public static T WithBearerToken(this ControllerBase controller, Func tokenConsumingFunction) => tokenConsumingFunction(controller.GetBearerToken()); - public static T WithIdentityIdAndBearerToken(this ControllerBase controller, Func<(Guid UserId, string BearerToken), T> tokenConsumingFunction) => - tokenConsumingFunction((controller.User.Claims.GetGuidFromClaim(PortalClaimTypes.IdentityId), controller.GetBearerToken())); - public static IdentityData GetIdentityData(this ClaimsPrincipal user) { var sub = user.Claims.GetStringFromClaim(PortalClaimTypes.Sub); @@ -82,7 +67,7 @@ private static string GetStringFromClaim(this IEnumerable claims, string var claimValue = claims.SingleOrDefault(x => x.Type == claimType)?.Value; if (string.IsNullOrWhiteSpace(claimValue)) { - throw new ControllerArgumentException($"Claim {claimType} must not be null or empty.", nameof(claims)); + throw new ControllerArgumentException($"Claim {claimType} must not be null or empty", nameof(claims)); } return claimValue; @@ -93,12 +78,12 @@ private static Guid GetGuidFromClaim(this IEnumerable claims, string clai var claimValue = claims.SingleOrDefault(x => x.Type == claimType)?.Value; if (string.IsNullOrWhiteSpace(claimValue)) { - throw new ControllerArgumentException($"Claim '{claimType} must not be null or empty."); + throw new ControllerArgumentException($"Claim {claimType} must not be null or empty", nameof(claims)); } if (!Guid.TryParse(claimValue, out var result) || Guid.Empty == result) { - throw new ControllerArgumentException($"Claim {claimType} must contain a Guid"); + throw new ControllerArgumentException($"Claim {claimType} must contain a Guid", nameof(claims)); } return result; @@ -109,12 +94,12 @@ private static T GetEnumFromClaim(this IEnumerable claims, string clai var claimValue = claims.SingleOrDefault(x => x.Type == claimType)?.Value; if (string.IsNullOrWhiteSpace(claimValue)) { - throw new ControllerArgumentException($"Claim '{claimType} must not be null or empty."); + throw new ControllerArgumentException($"Claim {claimType} must not be null or empty", nameof(claims)); } if (!Enum.TryParse(claimValue, true, out T result)) { - throw new ControllerArgumentException($"Claim {claimType} must contain a {typeof(T)}"); + throw new ControllerArgumentException($"Claim {claimType} must contain a {typeof(T)}", nameof(claims)); } return result; diff --git a/src/keycloak/Keycloak.Factory/IKeycloakFactory.cs b/src/keycloak/Keycloak.Factory/IKeycloakFactory.cs index 30a9df8e9f..8dab46a100 100644 --- a/src/keycloak/Keycloak.Factory/IKeycloakFactory.cs +++ b/src/keycloak/Keycloak.Factory/IKeycloakFactory.cs @@ -26,5 +26,5 @@ public interface IKeycloakFactory { KeycloakClient CreateKeycloakClient(string instance); - KeycloakClient CreateKeycloakClient(string instance, string clientId, string secret, bool useAuthTrail); + KeycloakClient CreateKeycloakClient(string instance, string clientId, string secret); } diff --git a/src/keycloak/Keycloak.Factory/KeycloakFactory.cs b/src/keycloak/Keycloak.Factory/KeycloakFactory.cs index 3b35a33bff..71a2b98062 100644 --- a/src/keycloak/Keycloak.Factory/KeycloakFactory.cs +++ b/src/keycloak/Keycloak.Factory/KeycloakFactory.cs @@ -46,7 +46,7 @@ public KeycloakClient CreateKeycloakClient(string instance) : KeycloakClient.CreateWithClientId(settings.ConnectionString, settings.ClientId, settings.ClientSecret, settings.UseAuthTrail, settings.AuthRealm); } - public KeycloakClient CreateKeycloakClient(string instance, string clientId, string secret, bool useAuthTrail) + public KeycloakClient CreateKeycloakClient(string instance, string clientId, string secret) { if (!_settings.Keys.Contains(instance, StringComparer.InvariantCultureIgnoreCase)) { @@ -54,6 +54,6 @@ public KeycloakClient CreateKeycloakClient(string instance, string clientId, str } var settings = _settings.Single(x => x.Key.Equals(instance, StringComparison.InvariantCultureIgnoreCase)).Value; - return KeycloakClient.CreateWithClientId(settings.ConnectionString, clientId, secret, useAuthTrail, settings.AuthRealm); + return KeycloakClient.CreateWithClientId(settings.ConnectionString, clientId, secret, settings.UseAuthTrail, settings.AuthRealm); } } diff --git a/src/mailing/Mailing.Template/EmailTemplates/osp_welcome_email.html b/src/mailing/Mailing.Template/EmailTemplates/osp_welcome_email.html index b78482a1bc..126d933f99 100644 --- a/src/mailing/Mailing.Template/EmailTemplates/osp_welcome_email.html +++ b/src/mailing/Mailing.Template/EmailTemplates/osp_welcome_email.html @@ -90,9 +90,16 @@ -

- Dear {userName},

your registration at the Catena-X dataspace got based on your request successfully generated by {osp}.

We have created your registration request. Before the registration validation is taking place, a final check from your side confirming your registration data and confirming the terms & conditions is needed.

Please follow the link below to access your registration data and to confirm the company role related terms & conditions.
You may want to update the company roles by selecting additional roles.

+

+ Dear {userName},

your registration at the Catena-X dataspace got based on your request successfully generated by {osp}.

We have created your registration request. Before the registration validation is taking place, a final check from your side confirming your registration data and confirming the terms & conditions is needed.

Please follow the link below to access your registration data and to confirm the company role related terms & conditions.
You may want to update the company roles by selecting additional roles. + +
Please note: you can login with your {osp} account by clicking on the company login path * +

+ {idpalias} +

* and entering your {osp} user credentials. In case the authentication runs on errors, please have a look at the + help + or contact your onboarding service provider {osp} +

@@ -167,11 +174,16 @@ style="Margin:0;padding-top:15px;padding-bottom:15px;padding-left:30px;padding-right:30px;text-align: left;">

- if the request was not triggered by you, you can close the application by clicking here
{hostname}/{closeApplicationUrl}The above link does not work?
Copy/Paste this URL into your + Browser:
{hostname}/registration/external

+

+
+

I need more information and help?
@@ -183,6 +195,26 @@ + + + + + +
+
diff --git a/src/marketplace/Apps.Service/BusinessLogic/AppChangeBusinessLogic.cs b/src/marketplace/Apps.Service/BusinessLogic/AppChangeBusinessLogic.cs index 0196787f57..62d2639a9d 100644 --- a/src/marketplace/Apps.Service/BusinessLogic/AppChangeBusinessLogic.cs +++ b/src/marketplace/Apps.Service/BusinessLogic/AppChangeBusinessLogic.cs @@ -32,6 +32,7 @@ using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library; using System.Text.Json; @@ -48,6 +49,7 @@ public class AppChangeBusinessLogic : IAppChangeBusinessLogic private readonly INotificationService _notificationService; private readonly IProvisioningManager _provisioningManager; private readonly IOfferService _offerService; + private readonly IIdentityService _identityService; /// /// Constructor. @@ -55,26 +57,35 @@ public class AppChangeBusinessLogic : IAppChangeBusinessLogic /// access to the repositories /// the notification service /// The provisioning manager - /// Settings for the app change bl + /// Access to the identityService /// Offer Servicel - public AppChangeBusinessLogic(IPortalRepositories portalRepositories, INotificationService notificationService, IProvisioningManager provisioningManager, IOfferService offerService, IOptions settings) + /// Settings for the app change bl + public AppChangeBusinessLogic( + IPortalRepositories portalRepositories, + INotificationService notificationService, + IProvisioningManager provisioningManager, + IOfferService offerService, + IIdentityService identityService, + IOptions settings) { _portalRepositories = portalRepositories; _notificationService = notificationService; _provisioningManager = provisioningManager; _settings = settings.Value; _offerService = offerService; + _identityService = identityService; } /// - public Task> AddActiveAppUserRoleAsync(Guid appId, IEnumerable appUserRolesDescription, (Guid UserId, Guid CompanyId) identity) + public Task> AddActiveAppUserRoleAsync(Guid appId, IEnumerable appUserRolesDescription) { AppExtensions.ValidateAppUserRole(appId, appUserRolesDescription); - return InsertActiveAppUserRoleAsync(appId, appUserRolesDescription, identity); + return InsertActiveAppUserRoleAsync(appId, appUserRolesDescription); } - private async Task> InsertActiveAppUserRoleAsync(Guid appId, IEnumerable userRoles, (Guid UserId, Guid CompanyId) identity) + private async Task> InsertActiveAppUserRoleAsync(Guid appId, IEnumerable userRoles) { + var identity = _identityService.IdentityData; var result = await _portalRepositories.GetInstance().GetInsertActiveAppUserRoleDataAsync(appId, OfferTypeId.APP).ConfigureAwait(false); if (result == default) { @@ -113,19 +124,19 @@ private async Task> InsertActiveAppUserRoleAsync(Guid a } /// - public async Task> GetAppUpdateDescriptionByIdAsync(Guid appId, Guid companyId) + public async Task> GetAppUpdateDescriptionByIdAsync(Guid appId) { var offerRepository = _portalRepositories.GetInstance(); - return await ValidateAndGetAppDescription(appId, companyId, offerRepository); + return await ValidateAndGetAppDescription(appId, offerRepository); } /// - public async Task CreateOrUpdateAppDescriptionByIdAsync(Guid appId, Guid companyId, IEnumerable offerDescriptionDatas) + public async Task CreateOrUpdateAppDescriptionByIdAsync(Guid appId, IEnumerable offerDescriptionDatas) { var offerRepository = _portalRepositories.GetInstance(); offerRepository.CreateUpdateDeleteOfferDescriptions(appId, - await ValidateAndGetAppDescription(appId, companyId, offerRepository), + await ValidateAndGetAppDescription(appId, offerRepository), offerDescriptionDatas.Select(od => new ValueTuple(od.LanguageCode, od.LongDescription, od.ShortDescription))); offerRepository.AttachAndModifyOffer(appId, offer => @@ -133,8 +144,9 @@ await ValidateAndGetAppDescription(appId, companyId, offerRepository), await _portalRepositories.SaveAsync().ConfigureAwait(false); } - private static async Task> ValidateAndGetAppDescription(Guid appId, Guid companyId, IOfferRepository offerRepository) + private async Task> ValidateAndGetAppDescription(Guid appId, IOfferRepository offerRepository) { + var companyId = _identityService.IdentityData.CompanyId; var result = await offerRepository.GetActiveOfferDescriptionDataByIdAsync(appId, OfferTypeId.APP, companyId).ConfigureAwait(false); if (result == default) { @@ -160,13 +172,14 @@ private static async Task> ValidateAndGetAppDe } /// - public async Task UploadOfferAssignedAppLeadImageDocumentByIdAsync(Guid appId, (Guid UserId, Guid CompanyId) identity, IFormFile document, CancellationToken cancellationToken) + public async Task UploadOfferAssignedAppLeadImageDocumentByIdAsync(Guid appId, IFormFile document, CancellationToken cancellationToken) { var appLeadImageContentTypes = new[] { MediaTypeId.JPEG, MediaTypeId.PNG }; var documentContentType = document.ContentType.ParseMediaTypeId(); documentContentType.CheckDocumentContentType(appLeadImageContentTypes); var offerRepository = _portalRepositories.GetInstance(); + var identity = _identityService.IdentityData; var result = await offerRepository.GetOfferAssignedAppLeadImageDocumentsByIdAsync(appId, identity.CompanyId, OfferTypeId.APP).ConfigureAwait(false); if (result == default) @@ -204,14 +217,15 @@ public Task DeactivateOfferByAppIdAsync(Guid appId) => _offerService.DeactivateOfferIdAsync(appId, OfferTypeId.APP); /// - public Task UpdateTenantUrlAsync(Guid offerId, Guid subscriptionId, UpdateTenantData data, Guid companyId) + public Task UpdateTenantUrlAsync(Guid offerId, Guid subscriptionId, UpdateTenantData data) { data.Url.EnsureValidHttpUrl(() => nameof(data.Url)); - return UpdateTenantUrlAsyncInternal(offerId, subscriptionId, data.Url, companyId); + return UpdateTenantUrlAsyncInternal(offerId, subscriptionId, data.Url); } - private async Task UpdateTenantUrlAsyncInternal(Guid offerId, Guid subscriptionId, string url, Guid companyId) + private async Task UpdateTenantUrlAsyncInternal(Guid offerId, Guid subscriptionId, string url) { + var companyId = _identityService.IdentityData.CompanyId; var offerSubscriptionsRepository = _portalRepositories.GetInstance(); var result = await offerSubscriptionsRepository.GetUpdateUrlDataAsync(offerId, subscriptionId, companyId).ConfigureAwait(false); if (result == null) @@ -283,4 +297,25 @@ private async Task UpdateTenantUrlAsyncInternal(Guid offerId, Guid subscriptionI await _portalRepositories.SaveAsync().ConfigureAwait(false); } + + /// + public async Task GetActiveAppDocumentTypeDataAsync(Guid appId) + { + var appDocTypeData = await _portalRepositories.GetInstance() + .GetActiveOfferDocumentTypeDataOrderedAsync(appId, _identityService.IdentityData.CompanyId, OfferTypeId.APP, _settings.ActiveAppDocumentTypeIds) + .PreSortedGroupBy(result => result.DocumentTypeId) + .ToDictionaryAsync( + group => group.Key, + group => group.Select(result => + new DocumentData( + result.DocumentId, + result.DocumentName))) + .ConfigureAwait(false); + return new ActiveAppDocumentData( + _settings.ActiveAppDocumentTypeIds.ToDictionary( + documentTypeId => documentTypeId, + documentTypeId => appDocTypeData.TryGetValue(documentTypeId, out var data) + ? data + : Enumerable.Empty())); + } } diff --git a/src/marketplace/Apps.Service/BusinessLogic/AppReleaseBusinessLogic.cs b/src/marketplace/Apps.Service/BusinessLogic/AppReleaseBusinessLogic.cs index e1bf94a55d..a52c75a256 100644 --- a/src/marketplace/Apps.Service/BusinessLogic/AppReleaseBusinessLogic.cs +++ b/src/marketplace/Apps.Service/BusinessLogic/AppReleaseBusinessLogic.cs @@ -31,6 +31,7 @@ using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities; namespace Org.Eclipse.TractusX.Portal.Backend.Apps.Service.BusinessLogic; @@ -44,6 +45,7 @@ public class AppReleaseBusinessLogic : IAppReleaseBusinessLogic private readonly IOfferService _offerService; private readonly IOfferDocumentService _offerDocumentService; private readonly IOfferSetupService _offerSetupService; + private readonly IIdentityService _identityService; /// /// Constructor. @@ -53,31 +55,34 @@ public class AppReleaseBusinessLogic : IAppReleaseBusinessLogic /// /// /// - public AppReleaseBusinessLogic(IPortalRepositories portalRepositories, IOptions settings, IOfferService offerService, IOfferDocumentService offerDocumentService, IOfferSetupService offerSetupService) + /// Access to the identityService + public AppReleaseBusinessLogic(IPortalRepositories portalRepositories, IOptions settings, IOfferService offerService, IOfferDocumentService offerDocumentService, IOfferSetupService offerSetupService, IIdentityService identityService) { _portalRepositories = portalRepositories; _settings = settings.Value; _offerService = offerService; _offerDocumentService = offerDocumentService; _offerSetupService = offerSetupService; + _identityService = identityService; } /// - public Task CreateAppDocumentAsync(Guid appId, DocumentTypeId documentTypeId, IFormFile document, (Guid UserId, Guid CompanyId) identity, CancellationToken cancellationToken) => - UploadAppDoc(appId, documentTypeId, document, identity, OfferTypeId.APP, cancellationToken); + public Task CreateAppDocumentAsync(Guid appId, DocumentTypeId documentTypeId, IFormFile document, CancellationToken cancellationToken) => + UploadAppDoc(appId, documentTypeId, document, OfferTypeId.APP, cancellationToken); - private async Task UploadAppDoc(Guid appId, DocumentTypeId documentTypeId, IFormFile document, (Guid UserId, Guid CompanyId) identity, OfferTypeId offerTypeId, CancellationToken cancellationToken) => - await _offerDocumentService.UploadDocumentAsync(appId, documentTypeId, document, identity, offerTypeId, _settings.UploadAppDocumentTypeIds, cancellationToken).ConfigureAwait(false); + private async Task UploadAppDoc(Guid appId, DocumentTypeId documentTypeId, IFormFile document, OfferTypeId offerTypeId, CancellationToken cancellationToken) => + await _offerDocumentService.UploadDocumentAsync(appId, documentTypeId, document, offerTypeId, _settings.UploadAppDocumentTypeIds, cancellationToken).ConfigureAwait(false); /// - public Task> AddAppUserRoleAsync(Guid appId, IEnumerable userRoles, Guid companyId) + public Task> AddAppUserRoleAsync(Guid appId, IEnumerable userRoles) { AppExtensions.ValidateAppUserRole(appId, userRoles); - return InsertAppUserRoleAsync(appId, userRoles, companyId); + return InsertAppUserRoleAsync(appId, userRoles); } - private async Task> InsertAppUserRoleAsync(Guid appId, IEnumerable userRoles, Guid companyId) + private async Task> InsertAppUserRoleAsync(Guid appId, IEnumerable userRoles) { + var companyId = _identityService.IdentityData.CompanyId; var result = await _portalRepositories.GetInstance().IsProviderCompanyUserAsync(appId, companyId, OfferTypeId.APP).ConfigureAwait(false); if (result == default) { @@ -144,8 +149,9 @@ public async Task GetAppDetailsForStatusAsync(Guid appId) } /// - public async Task DeleteAppRoleAsync(Guid appId, Guid roleId, Guid companyId) + public async Task DeleteAppRoleAsync(Guid appId, Guid roleId) { + var companyId = _identityService.IdentityData.CompanyId; var appUserRole = await _portalRepositories.GetInstance().GetAppUserRoleUntrackedAsync(appId, companyId, OfferStatusId.CREATED, roleId).ConfigureAwait(false); if (!appUserRole.IsProviderCompanyUser) { @@ -164,11 +170,11 @@ public async Task DeleteAppRoleAsync(Guid appId, Guid roleId, Guid companyId) } /// - public IAsyncEnumerable GetAppProviderSalesManagersAsync(Guid companyId) => - _portalRepositories.GetInstance().GetUserDataByAssignedRoles(companyId, _settings.SalesManagerRoles); + public IAsyncEnumerable GetAppProviderSalesManagersAsync() => + _portalRepositories.GetInstance().GetUserDataByAssignedRoles(_identityService.IdentityData.CompanyId, _settings.SalesManagerRoles); /// - public Task AddAppAsync(AppRequestModel appRequestModel, Guid companyId) + public Task AddAppAsync(AppRequestModel appRequestModel) { var emptyLanguageCodes = appRequestModel.SupportedLanguageCodes.Where(string.IsNullOrWhiteSpace); if (emptyLanguageCodes.Any()) @@ -182,11 +188,12 @@ public Task AddAppAsync(AppRequestModel appRequestModel, Guid companyId) throw new ControllerArgumentException("Use Case Ids must not be null or empty", nameof(appRequestModel.UseCaseIds)); } - return this.CreateAppAsync(appRequestModel, companyId); + return this.CreateAppAsync(appRequestModel); } - private async Task CreateAppAsync(AppRequestModel appRequestModel, Guid companyId) + private async Task CreateAppAsync(AppRequestModel appRequestModel) { + var companyId = _identityService.IdentityData.CompanyId; if (appRequestModel.SalesManagerId.HasValue) { await _offerService.ValidateSalesManager(appRequestModel.SalesManagerId.Value, _settings.SalesManagerRoles).ConfigureAwait(false); @@ -232,8 +239,9 @@ private async Task CreateAppAsync(AppRequestModel appRequestModel, Guid co } /// - public async Task UpdateAppReleaseAsync(Guid appId, AppRequestModel appRequestModel, Guid companyId) + public async Task UpdateAppReleaseAsync(Guid appId, AppRequestModel appRequestModel) { + var companyId = _identityService.IdentityData.CompanyId; var appData = await _portalRepositories.GetInstance() .GetAppUpdateData( appId, @@ -386,8 +394,9 @@ public Task DeleteAppDocumentsAsync(Guid documentId) => _offerService.DeleteDocumentsAsync(documentId, _settings.DeleteDocumentTypeIds, OfferTypeId.APP); /// - public async Task DeleteAppAsync(Guid appId, Guid companyId) + public async Task DeleteAppAsync(Guid appId) { + var companyId = _identityService.IdentityData.CompanyId; var (isValidApp, isOfferType, isOfferStatus, isProviderCompanyUser, appData) = await _portalRepositories.GetInstance().GetAppDeleteDataAsync(appId, OfferTypeId.APP, companyId, OfferStatusId.CREATED).ConfigureAwait(false); if (!isValidApp) { @@ -422,7 +431,7 @@ public async Task DeleteAppAsync(Guid appId, Guid companyId) } /// - public Task SetInstanceType(Guid appId, AppInstanceSetupData data, Guid companyId) + public Task SetInstanceType(Guid appId, AppInstanceSetupData data) { if (data.IsSingleInstance) { @@ -434,11 +443,12 @@ public Task SetInstanceType(Guid appId, AppInstanceSetupData data, Guid companyI nameof(data.InstanceUrl)); } - return SetInstanceTypeInternal(appId, data, companyId); + return SetInstanceTypeInternal(appId, data); } - private async Task SetInstanceTypeInternal(Guid appId, AppInstanceSetupData data, Guid companyId) + private async Task SetInstanceTypeInternal(Guid appId, AppInstanceSetupData data) { + var companyId = _identityService.IdentityData.CompanyId; var result = await _portalRepositories.GetInstance() .GetOfferWithSetupDataById(appId, companyId, OfferTypeId.APP) .ConfigureAwait(false); diff --git a/src/marketplace/Apps.Service/BusinessLogic/AppsBusinessLogic.cs b/src/marketplace/Apps.Service/BusinessLogic/AppsBusinessLogic.cs index 3f18eb5213..1d2b99203c 100644 --- a/src/marketplace/Apps.Service/BusinessLogic/AppsBusinessLogic.cs +++ b/src/marketplace/Apps.Service/BusinessLogic/AppsBusinessLogic.cs @@ -170,14 +170,15 @@ public async Task AddFavouriteAppForUserAsync(Guid appId) item.OfferId, item.ServiceName, item.CompanySubscriptionStatuses, - item.Image == Guid.Empty ? null : item.Image))); + item.Image == Guid.Empty ? null : item.Image, + item.ProcessStepTypeId == default ? null : item.ProcessStepTypeId))); } return await Pagination.CreateResponseAsync(page, size, _settings.ApplicationsMaxPageSize, GetCompanyProvidedAppSubscriptionStatusData).ConfigureAwait(false); } /// public Task AddOwnCompanyAppSubscriptionAsync(Guid appId, IEnumerable offerAgreementConsentData) => - _offerSubscriptionService.AddOfferSubscriptionAsync(appId, offerAgreementConsentData, OfferTypeId.APP, _settings.BasePortalAddress, _settings.SubscriptionManagerRoles); + _offerSubscriptionService.AddOfferSubscriptionAsync(appId, offerAgreementConsentData, OfferTypeId.APP, _settings.BasePortalAddress, _settings.SubscriptionManagerRoles, _settings.ServiceManagerRoles); /// public Task TriggerActivateOfferSubscription(Guid subscriptionId) => diff --git a/src/marketplace/Apps.Service/BusinessLogic/AppsSettings.cs b/src/marketplace/Apps.Service/BusinessLogic/AppsSettings.cs index 70cd4107f8..491b980ba4 100644 --- a/src/marketplace/Apps.Service/BusinessLogic/AppsSettings.cs +++ b/src/marketplace/Apps.Service/BusinessLogic/AppsSettings.cs @@ -196,6 +196,14 @@ public class AppsSettings /// [Required(AllowEmptyStrings = false)] public string ActivationPortalAddress { get; init; } = null!; + + /// + /// Active Document Types + /// + [Required] + [EnumEnumeration] + [DistinctValues] + public IEnumerable ActiveAppDocumentTypeIds { get; set; } = null!; } /// diff --git a/src/marketplace/Apps.Service/BusinessLogic/IAppChangeBusinessLogic.cs b/src/marketplace/Apps.Service/BusinessLogic/IAppChangeBusinessLogic.cs index 547bbfd418..0545f6f2a1 100644 --- a/src/marketplace/Apps.Service/BusinessLogic/IAppChangeBusinessLogic.cs +++ b/src/marketplace/Apps.Service/BusinessLogic/IAppChangeBusinessLogic.cs @@ -33,33 +33,29 @@ public interface IAppChangeBusinessLogic /// /// /// - /// /// List of the created AppRoles - Task> AddActiveAppUserRoleAsync(Guid appId, IEnumerable appUserRolesDescription, (Guid UserId, Guid CompanyId) identity); + Task> AddActiveAppUserRoleAsync(Guid appId, IEnumerable appUserRolesDescription); /// /// Get OfferDescription by appId /// /// Id of the app - /// - Task> GetAppUpdateDescriptionByIdAsync(Guid appId, Guid companyId); + Task> GetAppUpdateDescriptionByIdAsync(Guid appId); /// /// Create or Update OfferDescription by appId /// /// Id of the app - /// /// OfferDescription Data - Task CreateOrUpdateAppDescriptionByIdAsync(Guid appId, Guid companyId, IEnumerable offerDescriptionDatas); + Task CreateOrUpdateAppDescriptionByIdAsync(Guid appId, IEnumerable offerDescriptionDatas); /// /// Upload OfferAssigned AppLeadImage Document by appId /// /// Id of the app - /// /// Document Data /// cancellationToken - Task UploadOfferAssignedAppLeadImageDocumentByIdAsync(Guid appId, (Guid UserId, Guid CompanyId) identity, IFormFile document, CancellationToken cancellationToken); + Task UploadOfferAssignedAppLeadImageDocumentByIdAsync(Guid appId, IFormFile document, CancellationToken cancellationToken); /// /// Deactivate Offer Status by appId @@ -73,6 +69,11 @@ public interface IAppChangeBusinessLogic /// Id of the offer /// If of the subscription /// the data to update the url - /// - Task UpdateTenantUrlAsync(Guid offerId, Guid subscriptionId, UpdateTenantData data, Guid companyId); + Task UpdateTenantUrlAsync(Guid offerId, Guid subscriptionId, UpdateTenantData data); + + /// + /// Gets the Active App Documents + /// + /// Id of the offer + Task GetActiveAppDocumentTypeDataAsync(Guid appId); } diff --git a/src/marketplace/Apps.Service/BusinessLogic/IAppReleaseBusinessLogic.cs b/src/marketplace/Apps.Service/BusinessLogic/IAppReleaseBusinessLogic.cs index 2331f02c96..acddacae0b 100644 --- a/src/marketplace/Apps.Service/BusinessLogic/IAppReleaseBusinessLogic.cs +++ b/src/marketplace/Apps.Service/BusinessLogic/IAppReleaseBusinessLogic.cs @@ -37,19 +37,17 @@ public interface IAppReleaseBusinessLogic /// /// /// - /// /// /// - Task CreateAppDocumentAsync(Guid appId, DocumentTypeId documentTypeId, IFormFile document, (Guid UserId, Guid CompanyId) identity, CancellationToken cancellationToken); + Task CreateAppDocumentAsync(Guid appId, DocumentTypeId documentTypeId, IFormFile document, CancellationToken cancellationToken); /// /// Add User Role for App /// /// /// - /// /// - Task> AddAppUserRoleAsync(Guid appId, IEnumerable userRoles, Guid companyId); + Task> AddAppUserRoleAsync(Guid appId, IEnumerable userRoles); /// /// Return Agreements for App_Contract Category @@ -84,33 +82,29 @@ public interface IAppReleaseBusinessLogic /// /// /// - /// /// - Task DeleteAppRoleAsync(Guid appId, Guid roleId, Guid companyId); + Task DeleteAppRoleAsync(Guid appId, Guid roleId); /// /// Get Sales Manager Data /// - /// /// - IAsyncEnumerable GetAppProviderSalesManagersAsync(Guid companyId); + IAsyncEnumerable GetAppProviderSalesManagersAsync(); /// /// Creates an application and returns its generated ID. /// /// - /// /// Guid of the created app. - Task AddAppAsync(AppRequestModel appRequestModel, Guid companyId); + Task AddAppAsync(AppRequestModel appRequestModel); /// /// Creates an application and returns its generated ID. /// /// /// - /// /// Guid of the created app. - Task UpdateAppReleaseAsync(Guid appId, AppRequestModel appRequestModel, Guid companyId); + Task UpdateAppReleaseAsync(Guid appId, AppRequestModel appRequestModel); /// /// Retrieves all in review status apps in the marketplace. @@ -161,17 +155,15 @@ public interface IAppReleaseBusinessLogic /// Delete App /// /// - /// /// - Task DeleteAppAsync(Guid appId, Guid companyId); + Task DeleteAppAsync(Guid appId); /// /// Sets the instance type and all related data for the app /// /// Id of the app /// the data for the app instance - /// id of the current user - Task SetInstanceType(Guid appId, AppInstanceSetupData data, Guid companyId); + Task SetInstanceType(Guid appId, AppInstanceSetupData data); /// /// Get technical user profiles for a specific offer diff --git a/src/marketplace/Apps.Service/Controllers/AppChangeController.cs b/src/marketplace/Apps.Service/Controllers/AppChangeController.cs index ec611382b4..ac2939566f 100644 --- a/src/marketplace/Apps.Service/Controllers/AppChangeController.cs +++ b/src/marketplace/Apps.Service/Controllers/AppChangeController.cs @@ -24,7 +24,6 @@ using Org.Eclipse.TractusX.Portal.Backend.Apps.Service.ViewModels; using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Library; using Org.Eclipse.TractusX.Portal.Backend.Framework.Models; -using Org.Eclipse.TractusX.Portal.Backend.Keycloak.Authentication; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; namespace Org.Eclipse.TractusX.Portal.Backend.Apps.Service.Controllers; @@ -70,8 +69,8 @@ public AppChangeController(IAppChangeBusinessLogic businessLogic) [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status409Conflict)] - public async Task> AddActiveAppUserRole([FromRoute] Guid appId, [FromBody] IEnumerable userRoles) => - await this.WithUserIdAndCompanyId(identity => _businessLogic.AddActiveAppUserRoleAsync(appId, userRoles, identity)).ConfigureAwait(false); + public Task> AddActiveAppUserRole([FromRoute] Guid appId, [FromBody] IEnumerable userRoles) => + _businessLogic.AddActiveAppUserRoleAsync(appId, userRoles); /// /// Get description of the app by Id. @@ -88,8 +87,8 @@ public async Task> AddActiveAppUserRole([FromRoute] Gui [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status409Conflict)] - public async Task> GetAppUpdateDescriptionsAsync([FromRoute] Guid appId) => - await this.WithCompanyId(companyId => _businessLogic.GetAppUpdateDescriptionByIdAsync(appId, companyId)).ConfigureAwait(false); + public Task> GetAppUpdateDescriptionsAsync([FromRoute] Guid appId) => + _businessLogic.GetAppUpdateDescriptionByIdAsync(appId); /// /// Create or Update description of the app by Id. @@ -108,7 +107,7 @@ public async Task> GetAppUpdateDescriptionsAsy [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status409Conflict)] public async Task CreateOrUpdateAppDescriptionsByIdAsync([FromRoute] Guid appId, [FromBody] IEnumerable offerDescriptionDatas) { - await this.WithCompanyId(companyId => _businessLogic.CreateOrUpdateAppDescriptionByIdAsync(appId, companyId, offerDescriptionDatas)).ConfigureAwait(false); + await _businessLogic.CreateOrUpdateAppDescriptionByIdAsync(appId, offerDescriptionDatas).ConfigureAwait(false); return NoContent(); } /// @@ -135,7 +134,7 @@ public async Task CreateOrUpdateAppDescriptionsByIdAsync([FromR [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status415UnsupportedMediaType)] public async Task UploadOfferAssignedAppLeadImageDocumentByIdAsync([FromRoute] Guid appId, [FromForm(Name = "document")] IFormFile document, CancellationToken cancellationToken) { - await this.WithUserIdAndCompanyId(identity => _businessLogic.UploadOfferAssignedAppLeadImageDocumentByIdAsync(appId, identity, document, cancellationToken)); + await _businessLogic.UploadOfferAssignedAppLeadImageDocumentByIdAsync(appId, document, cancellationToken); return NoContent(); } @@ -183,7 +182,23 @@ public async Task DeactivateApp([FromRoute] Guid appId) [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status409Conflict)] public async Task UpdateTenantUrl([FromRoute] Guid appId, [FromRoute] Guid subscriptionId, [FromBody] UpdateTenantData data) { - await this.WithCompanyId(companyId => _businessLogic.UpdateTenantUrlAsync(appId, subscriptionId, data, companyId)).ConfigureAwait(false); + await _businessLogic.UpdateTenantUrlAsync(appId, subscriptionId, data).ConfigureAwait(false); return NoContent(); } + + /// + /// Returns the Active App Documents + /// + /// Id of the app. + /// Example: GET /apps/appchange/{appId}/documents + /// Gets the Active Apps documents + /// If App does not exists + [HttpGet] + [Route("{appId}/documents")] + [Authorize(Roles = "edit_apps")] + [Authorize(Policy = PolicyTypes.ValidCompany)] + [ProducesResponseType(typeof(ActiveAppDocumentData), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] + public async Task GetActiveAppDocuments([FromRoute] Guid appId) => + await _businessLogic.GetActiveAppDocumentTypeDataAsync(appId).ConfigureAwait(false); } diff --git a/src/marketplace/Apps.Service/Controllers/AppReleaseProcessController.cs b/src/marketplace/Apps.Service/Controllers/AppReleaseProcessController.cs index 9333999d93..bb40e9cb03 100644 --- a/src/marketplace/Apps.Service/Controllers/AppReleaseProcessController.cs +++ b/src/marketplace/Apps.Service/Controllers/AppReleaseProcessController.cs @@ -79,7 +79,7 @@ public AppReleaseProcessController(IAppReleaseBusinessLogic appReleaseBusinessLo [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status415UnsupportedMediaType)] public async Task UpdateAppDocumentAsync([FromRoute] Guid appId, [FromRoute] DocumentTypeId documentTypeId, [FromForm(Name = "document")] IFormFile document, CancellationToken cancellationToken) { - await this.WithUserIdAndCompanyId(identity => _appReleaseBusinessLogic.CreateAppDocumentAsync(appId, documentTypeId, document, identity, cancellationToken)); + await _appReleaseBusinessLogic.CreateAppDocumentAsync(appId, documentTypeId, document, cancellationToken); return NoContent(); } @@ -101,8 +101,8 @@ public async Task UpdateAppDocumentAsync([FromRoute] Guid appId [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)] - public async Task> AddAppUserRole([FromRoute] Guid appId, [FromBody] IEnumerable userRoles) => - await this.WithCompanyId(companyId => _appReleaseBusinessLogic.AddAppUserRoleAsync(appId, userRoles, companyId)).ConfigureAwait(false); + public Task> AddAppUserRole([FromRoute] Guid appId, [FromBody] IEnumerable userRoles) => + _appReleaseBusinessLogic.AddAppUserRoleAsync(appId, userRoles); /// /// Return Agreement Data for offer_type_id App @@ -193,7 +193,7 @@ public Task GetAppDetailsForStatusAsync([FromRoute] Guid ap [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)] public async Task DeleteAppRoleAsync([FromRoute] Guid appId, [FromRoute] Guid roleId) { - await this.WithCompanyId(companyId => _appReleaseBusinessLogic.DeleteAppRoleAsync(appId, roleId, companyId)); + await _appReleaseBusinessLogic.DeleteAppRoleAsync(appId, roleId); return NoContent(); } @@ -208,7 +208,7 @@ public async Task DeleteAppRoleAsync([FromRoute] Guid appId, [F [Authorize(Policy = PolicyTypes.ValidCompany)] [ProducesResponseType(typeof(IAsyncEnumerable), StatusCodes.Status200OK)] public IAsyncEnumerable GetAppProviderSalesManagerAsync() => - this.WithCompanyId(companyId => _appReleaseBusinessLogic.GetAppProviderSalesManagersAsync(companyId)); + _appReleaseBusinessLogic.GetAppProviderSalesManagersAsync(); /// /// Creates an app according to request model @@ -228,7 +228,7 @@ public IAsyncEnumerable GetAppProviderSalesManagerAsync() = [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)] public async Task ExecuteAppCreation([FromBody] AppRequestModel appRequestModel) { - var appId = await this.WithCompanyId(companyId => _appReleaseBusinessLogic.AddAppAsync(appRequestModel, companyId).ConfigureAwait(false)); + var appId = await _appReleaseBusinessLogic.AddAppAsync(appRequestModel).ConfigureAwait(false); return CreatedAtRoute(nameof(AppsController.GetAppDetailsByIdAsync), new { controller = "Apps", appId = appId }, appId); } @@ -255,7 +255,7 @@ public async Task ExecuteAppCreation([FromBody] AppRequest [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status409Conflict)] public async Task UpdateAppRelease([FromRoute] Guid appId, [FromBody] AppRequestModel appRequestModel) { - await this.WithCompanyId(companyId => _appReleaseBusinessLogic.UpdateAppReleaseAsync(appId, appRequestModel, companyId).ConfigureAwait(false)); + await _appReleaseBusinessLogic.UpdateAppReleaseAsync(appId, appRequestModel).ConfigureAwait(false); return NoContent(); } @@ -426,7 +426,7 @@ public async Task DeleteAppDocumentsAsync([FromRoute] Guid docu [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] public async Task DeleteAppAsync([FromRoute] Guid appId) { - await this.WithCompanyId(companyId => _appReleaseBusinessLogic.DeleteAppAsync(appId, companyId)).ConfigureAwait(false); + await _appReleaseBusinessLogic.DeleteAppAsync(appId).ConfigureAwait(false); return NoContent(); } @@ -450,7 +450,7 @@ public async Task DeleteAppAsync([FromRoute] Guid appId) [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] public async Task SetInstanceType([FromRoute] Guid appId, [FromBody] AppInstanceSetupData data) { - await this.WithCompanyId(companyId => _appReleaseBusinessLogic.SetInstanceType(appId, data, companyId)).ConfigureAwait(false); + await _appReleaseBusinessLogic.SetInstanceType(appId, data).ConfigureAwait(false); return NoContent(); } diff --git a/src/marketplace/Apps.Service/ViewModels/AppData.cs b/src/marketplace/Apps.Service/ViewModels/AppData.cs index 7f03d03e9f..7ced554ff0 100644 --- a/src/marketplace/Apps.Service/ViewModels/AppData.cs +++ b/src/marketplace/Apps.Service/ViewModels/AppData.cs @@ -18,6 +18,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; namespace Org.Eclipse.TractusX.Portal.Backend.Apps.Service.ViewModels; @@ -43,3 +44,9 @@ public record AppData( string Price, Guid LeadPictureId, IEnumerable UseCases); + +/// +/// View model of an Active App Documents +/// +/// Id of the App. +public record ActiveAppDocumentData(IDictionary> Documents); diff --git a/src/marketplace/Offers.Library.Web/IOfferDocumentService.cs b/src/marketplace/Offers.Library.Web/IOfferDocumentService.cs index 25a537108d..e4b76da924 100644 --- a/src/marketplace/Offers.Library.Web/IOfferDocumentService.cs +++ b/src/marketplace/Offers.Library.Web/IOfferDocumentService.cs @@ -35,9 +35,8 @@ public interface IOfferDocumentService /// /// /// - /// /// /// /// - Task UploadDocumentAsync(Guid id, DocumentTypeId documentTypeId, IFormFile document, (Guid UserId, Guid CompanyId) identity, OfferTypeId offerTypeId, IEnumerable uploadDocumentTypeIdSettings, CancellationToken cancellationToken); + Task UploadDocumentAsync(Guid id, DocumentTypeId documentTypeId, IFormFile document, OfferTypeId offerTypeId, IEnumerable uploadDocumentTypeIdSettings, CancellationToken cancellationToken); } diff --git a/src/marketplace/Offers.Library.Web/OfferDocumentService.cs b/src/marketplace/Offers.Library.Web/OfferDocumentService.cs index 519af98cc6..a686b17573 100644 --- a/src/marketplace/Offers.Library.Web/OfferDocumentService.cs +++ b/src/marketplace/Offers.Library.Web/OfferDocumentService.cs @@ -26,23 +26,27 @@ using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Extensions; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities; namespace Org.Eclipse.TractusX.Portal.Backend.Offers.Library.Web; public class OfferDocumentService : IOfferDocumentService { private readonly IPortalRepositories _portalRepositories; + private readonly IIdentityService _identityService; /// /// Constructor. /// /// Factory to access the repositories - public OfferDocumentService(IPortalRepositories portalRepositories) + /// Access to the identity + public OfferDocumentService(IPortalRepositories portalRepositories, IIdentityService identityService) { _portalRepositories = portalRepositories; + _identityService = identityService; } - public async Task UploadDocumentAsync(Guid id, DocumentTypeId documentTypeId, IFormFile document, (Guid UserId, Guid CompanyId) identity, OfferTypeId offerTypeId, IEnumerable uploadDocumentTypeIdSettings, CancellationToken cancellationToken) + public async Task UploadDocumentAsync(Guid id, DocumentTypeId documentTypeId, IFormFile document, OfferTypeId offerTypeId, IEnumerable uploadDocumentTypeIdSettings, CancellationToken cancellationToken) { if (id == Guid.Empty) { @@ -54,6 +58,7 @@ public async Task UploadDocumentAsync(Guid id, DocumentTypeId documentTypeId, IF throw new ControllerArgumentException("File name should not be null"); } + var identity = _identityService.IdentityData; var uploadContentTypeSettings = uploadDocumentTypeIdSettings.FirstOrDefault(x => x.DocumentTypeId == documentTypeId); if (uploadContentTypeSettings == null) { diff --git a/src/marketplace/Offers.Library/Models/OfferCompanySubscriptionStatusResponse.cs b/src/marketplace/Offers.Library/Models/OfferCompanySubscriptionStatusResponse.cs index 1d1b5fe86e..dc1fdeb0d9 100644 --- a/src/marketplace/Offers.Library/Models/OfferCompanySubscriptionStatusResponse.cs +++ b/src/marketplace/Offers.Library/Models/OfferCompanySubscriptionStatusResponse.cs @@ -19,6 +19,7 @@ ********************************************************************************/ using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; namespace Org.Eclipse.TractusX.Portal.Backend.Offers.Library.Models; @@ -34,5 +35,6 @@ public record OfferCompanySubscriptionStatusResponse( Guid OfferId, string? OfferName, IEnumerable CompanySubscriptionStatuses, - Guid? Image + Guid? Image, + ProcessStepTypeId? ProcessStepTypeId ); diff --git a/src/marketplace/Offers.Library/Service/IOfferSubscriptionService.cs b/src/marketplace/Offers.Library/Service/IOfferSubscriptionService.cs index 9261f7214b..a9e6158f77 100644 --- a/src/marketplace/Offers.Library/Service/IOfferSubscriptionService.cs +++ b/src/marketplace/Offers.Library/Service/IOfferSubscriptionService.cs @@ -21,11 +21,10 @@ using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Configuration; using Org.Eclipse.TractusX.Portal.Backend.Offers.Library.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; -using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities; namespace Org.Eclipse.TractusX.Portal.Backend.Offers.Library.Service; public interface IOfferSubscriptionService { - Task AddOfferSubscriptionAsync(Guid offerId, IEnumerable offerAgreementConsentData, OfferTypeId offerTypeId, string basePortalAddress, IEnumerable notificationRecipients); + Task AddOfferSubscriptionAsync(Guid offerId, IEnumerable offerAgreementConsentData, OfferTypeId offerTypeId, string basePortalAddress, IEnumerable notificationRecipients, IEnumerable serviceManagerRoles); } diff --git a/src/marketplace/Offers.Library/Service/OfferSubscriptionService.cs b/src/marketplace/Offers.Library/Service/OfferSubscriptionService.cs index 402f35b540..5c9365090f 100644 --- a/src/marketplace/Offers.Library/Service/OfferSubscriptionService.cs +++ b/src/marketplace/Offers.Library/Service/OfferSubscriptionService.cs @@ -29,6 +29,7 @@ using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities; using System.Collections.Immutable; +using System.Text.Json; namespace Org.Eclipse.TractusX.Portal.Backend.Offers.Library.Service; @@ -43,7 +44,7 @@ public class OfferSubscriptionService : IOfferSubscriptionService /// /// Factory to access the repositories /// Access to the identity of the user - /// Mail service. + /// Mail service. public OfferSubscriptionService( IPortalRepositories portalRepositories, IIdentityService identityService, @@ -55,10 +56,10 @@ public OfferSubscriptionService( } /// - public async Task AddOfferSubscriptionAsync(Guid offerId, IEnumerable offerAgreementConsentData, OfferTypeId offerTypeId, string basePortalAddress, IEnumerable notificationRecipients) + public async Task AddOfferSubscriptionAsync(Guid offerId, IEnumerable offerAgreementConsentData, OfferTypeId offerTypeId, string basePortalAddress, IEnumerable notificationRecipients, IEnumerable serviceManagerRoles) { var identity = _identityService.IdentityData; - var companyInformation = await ValidateCompanyInformationAsync(identity.CompanyId).ConfigureAwait(false); + var companyInformation = await ValidateCompanyInformationAsync(identity.CompanyId, identity.UserId).ConfigureAwait(false); var offerProviderDetails = await ValidateOfferProviderDetailDataAsync(offerId, offerTypeId).ConfigureAwait(false); if (offerProviderDetails.ProviderCompanyId == null) @@ -75,6 +76,16 @@ public async Task AddOfferSubscriptionAsync(Guid offerId, IEnumerable serviceManagerRoles) + { + var notificationRepository = _portalRepositories.GetInstance(); + + var notificationTypeId = offerTypeId == OfferTypeId.SERVICE ? NotificationTypeId.SERVICE_REQUEST : NotificationTypeId.APP_SUBSCRIPTION_REQUEST; + if (salesManagerId.HasValue) + { + notificationRepository.CreateNotification(salesManagerId.Value, notificationTypeId, false, + notification => + { + notification.CreatorUserId = companyUserId; + notification.Content = notificationContent; + }); + } + + var userRolesRepository = _portalRepositories.GetInstance(); + var roleData = await userRolesRepository + .GetUserRoleIdsUntrackedAsync(serviceManagerRoles) + .ToListAsync() + .ConfigureAwait(false); + if (roleData.Count < serviceManagerRoles.Sum(clientRoles => clientRoles.UserRoleNames.Count())) + { + throw new ConfigurationException($"invalid configuration, at least one of the configured roles does not exist in the database: {string.Join(", ", serviceManagerRoles.Select(clientRoles => $"client: {clientRoles.ClientId}, roles: [{string.Join(", ", clientRoles.UserRoleNames)}]"))}"); + } + + await foreach (var receiver in _portalRepositories.GetInstance().GetServiceProviderCompanyUserWithRoleIdAsync(offerId, roleData)) + { + if (salesManagerId.HasValue && receiver == salesManagerId.Value) + { + continue; + } + + notificationRepository.CreateNotification( + receiver, + notificationTypeId, + false, + notification => + { + notification.CreatorUserId = companyUserId; + notification.Content = notificationContent; + }); + } + } + private async Task ValidateOfferProviderDetailDataAsync(Guid offerId, OfferTypeId offerTypeId) { var offerProviderDetails = await _portalRepositories.GetInstance() @@ -133,10 +194,10 @@ private async Task ValidateConsent(IEnumerable offerA } } - private async Task ValidateCompanyInformationAsync(Guid companyId) + private async Task ValidateCompanyInformationAsync(Guid companyId, Guid companyUserId) { var companyInformation = await _portalRepositories.GetInstance() - .GetOwnCompanyInformationAsync(companyId).ConfigureAwait(false); + .GetOwnCompanyInformationAsync(companyId, companyUserId).ConfigureAwait(false); if (companyInformation == null) { throw new ControllerArgumentException($"Company {companyId} does not exist", nameof(companyId)); diff --git a/src/marketplace/Services.Service/BusinessLogic/IServiceReleaseBusinessLogic.cs b/src/marketplace/Services.Service/BusinessLogic/IServiceReleaseBusinessLogic.cs index 5b40ac72c5..d312dfd047 100644 --- a/src/marketplace/Services.Service/BusinessLogic/IServiceReleaseBusinessLogic.cs +++ b/src/marketplace/Services.Service/BusinessLogic/IServiceReleaseBusinessLogic.cs @@ -94,8 +94,7 @@ public interface IServiceReleaseBusinessLogic /// /// Id of the service to update /// Data of the updated entry - /// CompanyId of User - Task UpdateServiceAsync(Guid serviceId, ServiceUpdateRequestData data, Guid companyId); + Task UpdateServiceAsync(Guid serviceId, ServiceUpdateRequestData data); /// /// Update app status and create notification @@ -123,10 +122,9 @@ public interface IServiceReleaseBusinessLogic /// /// /// - /// /// /// - Task CreateServiceDocumentAsync(Guid serviceId, DocumentTypeId documentTypeId, IFormFile document, (Guid UserId, Guid CompanyId) identity, CancellationToken cancellationToken); + Task CreateServiceDocumentAsync(Guid serviceId, DocumentTypeId documentTypeId, IFormFile document, CancellationToken cancellationToken); /// /// Delete the Service Document diff --git a/src/marketplace/Services.Service/BusinessLogic/ServiceBusinessLogic.cs b/src/marketplace/Services.Service/BusinessLogic/ServiceBusinessLogic.cs index f1fe6618a4..89175d40b3 100644 --- a/src/marketplace/Services.Service/BusinessLogic/ServiceBusinessLogic.cs +++ b/src/marketplace/Services.Service/BusinessLogic/ServiceBusinessLogic.cs @@ -79,7 +79,7 @@ public ServiceBusinessLogic( /// public Task AddServiceSubscription(Guid serviceId, IEnumerable offerAgreementConsentData) => - _offerSubscriptionService.AddOfferSubscriptionAsync(serviceId, offerAgreementConsentData, OfferTypeId.SERVICE, _settings.BasePortalAddress, _settings.SubscriptionManagerRoles); + _offerSubscriptionService.AddOfferSubscriptionAsync(serviceId, offerAgreementConsentData, OfferTypeId.SERVICE, _settings.BasePortalAddress, _settings.SubscriptionManagerRoles, _settings.ServiceManagerRoles); /// public async Task GetServiceDetailsAsync(Guid serviceId, string lang) @@ -147,7 +147,8 @@ public Task AutoSetupServiceAsync(OfferAutoSetupData item.OfferId, item.ServiceName, item.CompanySubscriptionStatuses, - item.Image == Guid.Empty ? null : item.Image))); + item.Image == Guid.Empty ? null : item.Image, + item.ProcessStepTypeId == default ? null : item.ProcessStepTypeId))); } return await Pagination.CreateResponseAsync(page, size, _settings.ApplicationsMaxPageSize, GetCompanyProvidedAppSubscriptionStatusData).ConfigureAwait(false); } diff --git a/src/marketplace/Services.Service/BusinessLogic/ServiceReleaseBusinessLogic.cs b/src/marketplace/Services.Service/BusinessLogic/ServiceReleaseBusinessLogic.cs index 96fa2c752c..d427ff037f 100644 --- a/src/marketplace/Services.Service/BusinessLogic/ServiceReleaseBusinessLogic.cs +++ b/src/marketplace/Services.Service/BusinessLogic/ServiceReleaseBusinessLogic.cs @@ -28,6 +28,7 @@ using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities; using Org.Eclipse.TractusX.Portal.Backend.Services.Service.ViewModels; namespace Org.Eclipse.TractusX.Portal.Backend.Services.Service.BusinessLogic; @@ -40,6 +41,7 @@ public class ServiceReleaseBusinessLogic : IServiceReleaseBusinessLogic private readonly IPortalRepositories _portalRepositories; private readonly IOfferService _offerService; private readonly IOfferDocumentService _offerDocumentService; + private readonly IIdentityService _identityService; private readonly ServiceSettings _settings; /// @@ -48,16 +50,19 @@ public class ServiceReleaseBusinessLogic : IServiceReleaseBusinessLogic /// Factory to access the repositories /// Access to the offer service /// Access to the offer document service + /// Access to identity /// Access to the settings public ServiceReleaseBusinessLogic( IPortalRepositories portalRepositories, IOfferService offerService, IOfferDocumentService offerDocumentService, + IIdentityService identityService, IOptions settings) { _portalRepositories = portalRepositories; _offerService = offerService; _offerDocumentService = offerDocumentService; + _identityService = identityService; _settings = settings.Value; } @@ -160,8 +165,9 @@ public Task CreateServiceOfferingAsync(ServiceOfferingData data) => _offerService.CreateServiceOfferingAsync(data, OfferTypeId.SERVICE); /// - public async Task UpdateServiceAsync(Guid serviceId, ServiceUpdateRequestData data, Guid companyId) + public async Task UpdateServiceAsync(Guid serviceId, ServiceUpdateRequestData data) { + var companyId = _identityService.IdentityData.CompanyId; var serviceData = await _portalRepositories .GetInstance() .GetServiceUpdateData(serviceId, data.ServiceTypeIds, companyId) @@ -242,8 +248,8 @@ public Task DeclineServiceRequestAsync(Guid serviceId, OfferDeclineRequest data) _offerService.DeclineOfferAsync(serviceId, data, OfferTypeId.SERVICE, NotificationTypeId.SERVICE_RELEASE_REJECTION, _settings.ServiceManagerRoles, _settings.ServiceMarketplaceAddress, _settings.SubmitServiceNotificationTypeIds, _settings.CatenaAdminRoles); /// - public Task CreateServiceDocumentAsync(Guid serviceId, DocumentTypeId documentTypeId, IFormFile document, (Guid UserId, Guid CompanyId) identity, CancellationToken cancellationToken) => - _offerDocumentService.UploadDocumentAsync(serviceId, documentTypeId, document, identity, OfferTypeId.SERVICE, _settings.UploadServiceDocumentTypeIds, cancellationToken); + public Task CreateServiceDocumentAsync(Guid serviceId, DocumentTypeId documentTypeId, IFormFile document, CancellationToken cancellationToken) => + _offerDocumentService.UploadDocumentAsync(serviceId, documentTypeId, document, OfferTypeId.SERVICE, _settings.UploadServiceDocumentTypeIds, cancellationToken); /// public Task DeleteServiceDocumentsAsync(Guid documentId) => diff --git a/src/marketplace/Services.Service/Controllers/ServiceReleaseController.cs b/src/marketplace/Services.Service/Controllers/ServiceReleaseController.cs index cd0078ed6d..8871f12aa2 100644 --- a/src/marketplace/Services.Service/Controllers/ServiceReleaseController.cs +++ b/src/marketplace/Services.Service/Controllers/ServiceReleaseController.cs @@ -237,7 +237,7 @@ public async Task CreateServiceOffering([FromBody] Service [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status409Conflict)] public async Task UpdateService([FromRoute] Guid serviceId, [FromBody] ServiceUpdateRequestData data) { - await this.WithCompanyId(companyId => _serviceReleaseBusinessLogic.UpdateServiceAsync(serviceId, data, companyId)); + await _serviceReleaseBusinessLogic.UpdateServiceAsync(serviceId, data); return NoContent(); } @@ -342,7 +342,7 @@ public async Task DeclineServiceRequest([FromRoute] Guid servic [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status415UnsupportedMediaType)] public async Task UpdateServiceDocumentAsync([FromRoute] Guid serviceId, [FromRoute] DocumentTypeId documentTypeId, [FromForm(Name = "document")] IFormFile document, CancellationToken cancellationToken) { - await this.WithUserIdAndCompanyId(identity => _serviceReleaseBusinessLogic.CreateServiceDocumentAsync(serviceId, documentTypeId, document, identity, cancellationToken)); + await _serviceReleaseBusinessLogic.CreateServiceDocumentAsync(serviceId, documentTypeId, document, cancellationToken); return NoContent(); } diff --git a/src/marketplace/Services.Service/Controllers/ServicesController.cs b/src/marketplace/Services.Service/Controllers/ServicesController.cs index a36a582dd9..8d7a73434d 100644 --- a/src/marketplace/Services.Service/Controllers/ServicesController.cs +++ b/src/marketplace/Services.Service/Controllers/ServicesController.cs @@ -313,7 +313,7 @@ public Task GetSubscriptionDetailForSubscriber /// Service does not exist. [HttpPut] [Route("{subscriptionId}/unsubscribe")] - [Authorize(Roles = "unsubscribe_apps")] + [Authorize(Roles = "unsubscribe_services")] [Authorize(Policy = PolicyTypes.ValidCompany)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)] diff --git a/src/notifications/Notifications.Service/BusinessLogic/INotificationBusinessLogic.cs b/src/notifications/Notifications.Service/BusinessLogic/INotificationBusinessLogic.cs index 239cc764b0..0a174b04fa 100644 --- a/src/notifications/Notifications.Service/BusinessLogic/INotificationBusinessLogic.cs +++ b/src/notifications/Notifications.Service/BusinessLogic/INotificationBusinessLogic.cs @@ -34,46 +34,40 @@ public interface INotificationBusinessLogic /// /// the requested page /// the requested size - /// The id of the current user /// additional filters to query notifications /// Returns a collection of the users notification - Task> GetNotificationsAsync(int page, int size, Guid receiverUserId, NotificationFilters filters); + Task> GetNotificationsAsync(int page, int size, NotificationFilters filters); /// /// Gets a specific notification for the given user. /// - /// The id of the current user /// The id of the notification /// Returns a notification - Task GetNotificationDetailDataAsync(Guid userId, Guid notificationId); + Task GetNotificationDetailDataAsync(Guid notificationId); /// /// Gets the notification account for the given user /// - /// Id of the current identity /// OPTIONAL: filter for read or unread notifications /// Returns the count of the notifications - Task GetNotificationCountAsync(Guid userId, bool? isRead); + Task GetNotificationCountAsync(bool? isRead); /// /// Gets the count details of the notifications for the given user /// - /// Id of the current identity /// Returns the count details of the notifications - Task GetNotificationCountDetailsAsync(Guid userId); + Task GetNotificationCountDetailsAsync(); /// /// Sets the status of the notification with the given id to read /// - /// Id of the notification receiver /// Id of the notification /// Read or unread - Task SetNotificationStatusAsync(Guid userId, Guid notificationId, bool isRead); + Task SetNotificationStatusAsync(Guid notificationId, bool isRead); /// /// Deletes the given notification /// - /// Id of the notification receiver /// Id of the notification that should be deleted - Task DeleteNotificationAsync(Guid userId, Guid notificationId); + Task DeleteNotificationAsync(Guid notificationId); } diff --git a/src/notifications/Notifications.Service/BusinessLogic/NotificationBusinessLogic.cs b/src/notifications/Notifications.Service/BusinessLogic/NotificationBusinessLogic.cs index c47458862a..17ea3936af 100644 --- a/src/notifications/Notifications.Service/BusinessLogic/NotificationBusinessLogic.cs +++ b/src/notifications/Notifications.Service/BusinessLogic/NotificationBusinessLogic.cs @@ -26,6 +26,7 @@ using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities; namespace Org.Eclipse.TractusX.Portal.Backend.Notifications.Service.BusinessLogic; @@ -33,28 +34,31 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Notifications.Service.BusinessLogi public class NotificationBusinessLogic : INotificationBusinessLogic { private readonly IPortalRepositories _portalRepositories; + private readonly IIdentityService _identityService; private readonly NotificationSettings _settings; /// /// Creates a new instance of /// /// Access to the repository factory. + /// Access to the identity /// Access to the notifications options - public NotificationBusinessLogic(IPortalRepositories portalRepositories, IOptions settings) + public NotificationBusinessLogic(IPortalRepositories portalRepositories, IIdentityService identityService, IOptions settings) { _portalRepositories = portalRepositories; + _identityService = identityService; _settings = settings.Value; } /// - public Task> GetNotificationsAsync(int page, int size, Guid receiverUserId, NotificationFilters filters) => + public Task> GetNotificationsAsync(int page, int size, NotificationFilters filters) => Pagination.CreateResponseAsync(page, size, _settings.MaxPageSize, _portalRepositories.GetInstance() - .GetAllNotificationDetailsByReceiver(receiverUserId, filters.IsRead, filters.TypeId, filters.TopicId, filters.OnlyDueDate, filters.Sorting ?? NotificationSorting.DateDesc, filters.DoneState, filters.SearchTypeIds, filters.SearchQuery)); + .GetAllNotificationDetailsByReceiver(_identityService.IdentityData.UserId, filters.IsRead, filters.TypeId, filters.TopicId, filters.OnlyDueDate, filters.Sorting ?? NotificationSorting.DateDesc, filters.DoneState, filters.SearchTypeIds, filters.SearchQuery)); /// - public async Task GetNotificationDetailDataAsync(Guid userId, Guid notificationId) + public async Task GetNotificationDetailDataAsync(Guid notificationId) { - var result = await _portalRepositories.GetInstance().GetNotificationByIdAndValidateReceiverAsync(notificationId, userId).ConfigureAwait(false); + var result = await _portalRepositories.GetInstance().GetNotificationByIdAndValidateReceiverAsync(notificationId, _identityService.IdentityData.UserId).ConfigureAwait(false); if (result == default) { throw new NotFoundException($"Notification {notificationId} does not exist."); @@ -67,13 +71,13 @@ public async Task GetNotificationDetailDataAsync(Guid us } /// - public Task GetNotificationCountAsync(Guid userId, bool? isRead) => - _portalRepositories.GetInstance().GetNotificationCountForUserAsync(userId, isRead); + public Task GetNotificationCountAsync(bool? isRead) => + _portalRepositories.GetInstance().GetNotificationCountForUserAsync(_identityService.IdentityData.UserId, isRead); /// - public async Task GetNotificationCountDetailsAsync(Guid userId) + public async Task GetNotificationCountDetailsAsync() { - var details = await _portalRepositories.GetInstance().GetCountDetailsForUserAsync(userId).ToListAsync().ConfigureAwait(false); + var details = await _portalRepositories.GetInstance().GetCountDetailsForUserAsync(_identityService.IdentityData.UserId).ToListAsync().ConfigureAwait(false); var unreadNotifications = details.Where(x => !x.IsRead); return new NotificationCountDetails( details.Where(x => x.IsRead).Sum(x => x.Count), @@ -85,9 +89,9 @@ public async Task GetNotificationCountDetailsAsync(Gui } /// - public async Task SetNotificationStatusAsync(Guid userId, Guid notificationId, bool isRead) + public async Task SetNotificationStatusAsync(Guid notificationId, bool isRead) { - var isReadFlag = await CheckNotificationExistsAndValidateReceiver(notificationId, userId).ConfigureAwait(false); + var isReadFlag = await CheckNotificationExistsAndValidateReceiver(notificationId).ConfigureAwait(false); _portalRepositories.GetInstance().AttachAndModifyNotification(notificationId, notification => { @@ -102,17 +106,17 @@ public async Task SetNotificationStatusAsync(Guid userId, Guid notificationId, b } /// - public async Task DeleteNotificationAsync(Guid userId, Guid notificationId) + public async Task DeleteNotificationAsync(Guid notificationId) { - await CheckNotificationExistsAndValidateReceiver(notificationId, userId).ConfigureAwait(false); + await CheckNotificationExistsAndValidateReceiver(notificationId).ConfigureAwait(false); _portalRepositories.GetInstance().DeleteNotification(notificationId); await _portalRepositories.SaveAsync().ConfigureAwait(false); } - private async Task CheckNotificationExistsAndValidateReceiver(Guid notificationId, Guid userId) + private async Task CheckNotificationExistsAndValidateReceiver(Guid notificationId) { - var result = await _portalRepositories.GetInstance().CheckNotificationExistsByIdAndValidateReceiverAsync(notificationId, userId).ConfigureAwait(false); + var result = await _portalRepositories.GetInstance().CheckNotificationExistsByIdAndValidateReceiverAsync(notificationId, _identityService.IdentityData.UserId).ConfigureAwait(false); if (result == default || !result.IsNotificationExisting) { throw new NotFoundException($"Notification {notificationId} does not exist."); diff --git a/src/notifications/Notifications.Service/Controllers/NotificationController.cs b/src/notifications/Notifications.Service/Controllers/NotificationController.cs index 4a96fa2c2b..173784213e 100644 --- a/src/notifications/Notifications.Service/Controllers/NotificationController.cs +++ b/src/notifications/Notifications.Service/Controllers/NotificationController.cs @@ -84,7 +84,7 @@ public NotificationController(INotificationBusinessLogic logic) [FromQuery] bool? doneState = null, [FromQuery] string? searchQuery = null ) => - this.WithUserId(userId => _logic.GetNotificationsAsync(page, size, userId, new NotificationFilters(isRead, notificationTypeId, notificationTopicId, onlyDueDate, sorting, doneState, searchTypeIds, searchQuery))); + _logic.GetNotificationsAsync(page, size, new NotificationFilters(isRead, notificationTypeId, notificationTopicId, onlyDueDate, sorting, doneState, searchTypeIds, searchQuery)); /// /// Gets a notification for the logged in user @@ -102,7 +102,7 @@ public NotificationController(INotificationBusinessLogic logic) [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)] public Task GetNotification([FromRoute] Guid notificationId) => - this.WithUserId(userId => _logic.GetNotificationDetailDataAsync(userId, notificationId)); + _logic.GetNotificationDetailDataAsync(notificationId); /// /// Gets the notification count for the current logged in user @@ -122,7 +122,7 @@ public Task GetNotification([FromRoute] Guid notificatio [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)] public Task NotificationCount([FromQuery] bool? isRead) => - this.WithUserId(userId => _logic.GetNotificationCountAsync(userId, isRead)); + _logic.GetNotificationCountAsync(isRead); /// /// Gets the notification count for the current logged in user @@ -136,7 +136,7 @@ public Task NotificationCount([FromQuery] bool? isRead) => [Authorize(Policy = PolicyTypes.ValidIdentity)] [ProducesResponseType(typeof(NotificationCountDetails), StatusCodes.Status200OK)] public Task NotificationCountDetails() => - this.WithUserId(userId => _logic.GetNotificationCountDetailsAsync(userId)); + _logic.GetNotificationCountDetailsAsync(); /// /// Changes the read status of a notification @@ -158,7 +158,7 @@ public Task NotificationCountDetails() => [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)] public async Task SetNotificationToRead([FromRoute] Guid notificationId, [FromQuery] bool isRead = true) { - await this.WithUserId(userId => _logic.SetNotificationStatusAsync(userId, notificationId, isRead)).ConfigureAwait(false); + await _logic.SetNotificationStatusAsync(notificationId, isRead).ConfigureAwait(false); return NoContent(); } @@ -180,7 +180,7 @@ public async Task SetNotificationToRead([FromRoute] Guid notificat [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)] public async Task DeleteNotification([FromRoute] Guid notificationId) { - await this.WithUserId(userId => _logic.DeleteNotificationAsync(userId, notificationId)).ConfigureAwait(false); + await _logic.DeleteNotificationAsync(notificationId).ConfigureAwait(false); return NoContent(); } } diff --git a/src/portalbackend/PortalBackend.DBAccess/Models/CompanyInformationData.cs b/src/portalbackend/PortalBackend.DBAccess/Models/CompanyInformationData.cs index 32dbca0a4a..3fcd394a13 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Models/CompanyInformationData.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Models/CompanyInformationData.cs @@ -24,4 +24,5 @@ public record CompanyInformationData( Guid CompanyId, string OrganizationName, string? Country, - string? BusinessPartnerNumber); + string? BusinessPartnerNumber, + string? CompanyUserEmail); diff --git a/src/portalbackend/PortalBackend.DBAccess/Models/ConnectedCompanyData.cs b/src/portalbackend/PortalBackend.DBAccess/Models/ConnectedCompanyData.cs new file mode 100644 index 0000000000..2e34e3e387 --- /dev/null +++ b/src/portalbackend/PortalBackend.DBAccess/Models/ConnectedCompanyData.cs @@ -0,0 +1,26 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 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.PortalBackend.DBAccess.Models; + +public record ConnectedCompanyData +( + Guid CompanyId, + string CompanyName +); diff --git a/src/portalbackend/PortalBackend.DBAccess/Models/OfferCompanySubscriptionStatusData.cs b/src/portalbackend/PortalBackend.DBAccess/Models/OfferCompanySubscriptionStatusData.cs index 2451610794..b46ecd623c 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Models/OfferCompanySubscriptionStatusData.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Models/OfferCompanySubscriptionStatusData.cs @@ -18,6 +18,8 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; + namespace Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; /// @@ -53,4 +55,10 @@ public OfferCompanySubscriptionStatusData() /// /// public Guid Image { get; set; } + + /// + /// Id of the ProcessStep Type + /// + /// + public ProcessStepTypeId ProcessStepTypeId { get; set; } } diff --git a/src/portalbackend/PortalBackend.DBAccess/Models/OfferSubscriptionDetailData.cs b/src/portalbackend/PortalBackend.DBAccess/Models/OfferSubscriptionDetailData.cs index 4407e3c5e6..dbae3a5460 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Models/OfferSubscriptionDetailData.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Models/OfferSubscriptionDetailData.cs @@ -70,7 +70,8 @@ public record AppProviderSubscriptionDetailData( IEnumerable Contact, IEnumerable TechnicalUserData, string? TenantUrl, - string AppInstanceId + string AppInstanceId, + ProcessStepTypeId? ProcessStepTypeId ); /// diff --git a/src/portalbackend/PortalBackend.DBAccess/Models/TriggerProviderInformation.cs b/src/portalbackend/PortalBackend.DBAccess/Models/TriggerProviderInformation.cs index 1d46e0248c..96b1e35bc7 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Models/TriggerProviderInformation.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Models/TriggerProviderInformation.cs @@ -27,7 +27,6 @@ public record TriggerProviderInformation( string? OfferName, string? AutoSetupUrl, CompanyInformationData CompanyInformationData, - string? UserEmail, OfferTypeId OfferTypeId, Guid? SalesManagerId, Guid CompanyUserId, diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/ApplicationRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/ApplicationRepository.cs index 62a7fd2aa6..6fcfc1d716 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/ApplicationRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/ApplicationRepository.cs @@ -54,6 +54,19 @@ public void AttachAndModifyCompanyApplication(Guid companyApplicationId, Action< setOptionalParameters.Invoke(companyApplication); } + public void AttachAndModifyCompanyApplications(IEnumerable<(Guid companyApplicationId, Action? Initialize, Action Modify)> applicationData) + { + var initial = applicationData.Select(x => + { + var companyApplication = new CompanyApplication(x.companyApplicationId, Guid.Empty, default, default, default); + x.Initialize?.Invoke(companyApplication); + return (CompanyApplication: companyApplication, x.Modify); + } + ).ToList(); + _dbContext.AttachRange(initial.Select(x => x.CompanyApplication)); + initial.ForEach(x => x.Modify(x.CompanyApplication)); + } + public Invitation CreateInvitation(Guid applicationId, Guid companyUserId) => _dbContext.Invitations.Add( new Invitation( diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/CompanyRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/CompanyRepository.cs index 76da595d14..959618628d 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/CompanyRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/CompanyRepository.cs @@ -108,10 +108,12 @@ public void CreateUpdateDeleteIdentifiers(Guid companyId, IEnumerable<(UniqueIde company!.CompanyAssignedRoles.SelectMany(car => car.CompanyRole!.CompanyRoleAssignedRoleCollection!.UserRoleCollection!.UserRoles.Where(ur => ur.Offer!.AppInstances.Any(ai => ai.IamClient!.ClientClientId == technicalUserClientId)).Select(ur => ur.Id)).Distinct())) .SingleOrDefaultAsync(); - public IAsyncEnumerable GetAllMemberCompaniesBPNAsync() => + public IAsyncEnumerable GetAllMemberCompaniesBPNAsync(IEnumerable? bpnIds) => _context.Companies .AsNoTracking() - .Where(company => company.CompanyStatusId == CompanyStatusId.ACTIVE) + .Where(company => company.CompanyStatusId == CompanyStatusId.ACTIVE && + (bpnIds == null || bpnIds.Contains(company.BusinessPartnerNumber) && + company.BusinessPartnerNumber != null)) .Select(company => company.BusinessPartnerNumber) .AsAsyncEnumerable(); @@ -281,15 +283,16 @@ public IAsyncEnumerable GetCompanyRoleAndConsentAgreemen true )).SingleOrDefaultAsync(); - public Task GetOwnCompanyInformationAsync(Guid companyId) => + public Task GetOwnCompanyInformationAsync(Guid companyId, Guid companyUserId) => _context.Companies .AsNoTracking() .Where(c => c.Id == companyId) - .Select(user => new CompanyInformationData( - user.Id, - user.Name, - user.Address!.CountryAlpha2Code, - user.BusinessPartnerNumber + .Select(company => new CompanyInformationData( + company.Id, + company.Name, + company.Address!.CountryAlpha2Code, + company.BusinessPartnerNumber, + company.Identities.Where(x => x.Id == companyUserId && x.IdentityTypeId == IdentityTypeId.COMPANY_USER).Select(x => x.CompanyUser!.Email).SingleOrDefault() )) .SingleOrDefaultAsync(); diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/DocumentRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/DocumentRepository.cs index e95038485b..e1dcc472ee 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/DocumentRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/DocumentRepository.cs @@ -23,6 +23,7 @@ using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; +using System.Security.Cryptography.X509Certificates; namespace Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; @@ -129,7 +130,7 @@ public void RemoveDocument(Guid documentId) => this._dbContext.Documents.SingleOrDefaultAsync(x => x.Id == documentId); /// - public Task<(Guid DocumentId, DocumentStatusId DocumentStatusId, bool IsSameApplicationUser, DocumentTypeId documentTypeId, bool IsQueriedApplicationStatus)> GetDocumentDetailsForApplicationUntrackedAsync(Guid documentId, Guid userCompanyId, IEnumerable applicationStatusIds) => + public Task<(Guid DocumentId, DocumentStatusId DocumentStatusId, bool IsSameApplicationUser, DocumentTypeId documentTypeId, bool IsQueriedApplicationStatus, IEnumerable applicationId)> GetDocumentDetailsForApplicationUntrackedAsync(Guid documentId, Guid userCompanyId, IEnumerable applicationStatusIds) => _dbContext.Documents .AsNoTracking() .Where(x => x.Id == documentId) @@ -138,12 +139,13 @@ public void RemoveDocument(Guid documentId) => Document = document, Applications = document.CompanyUser!.Identity!.Company!.CompanyApplications }) - .Select(x => new ValueTuple( + .Select(x => new ValueTuple>( x.Document.Id, x.Document.DocumentStatusId, x.Applications.Any(companyApplication => companyApplication.CompanyId == userCompanyId), x.Document.DocumentTypeId, - x.Applications.Any(companyApplication => applicationStatusIds.Contains(companyApplication.ApplicationStatusId)))) + x.Applications.Any(companyApplication => applicationStatusIds.Contains(companyApplication.ApplicationStatusId)), + x.Applications.Select(x => x.Id))) .SingleOrDefaultAsync(); /// diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/IApplicationRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/IApplicationRepository.cs index 21252ff9f1..6e2d755512 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/IApplicationRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/IApplicationRepository.cs @@ -28,6 +28,7 @@ public interface IApplicationRepository { CompanyApplication CreateCompanyApplication(Guid companyId, CompanyApplicationStatusId companyApplicationStatusId, CompanyApplicationTypeId applicationTypeId, Action? setOptionalFields = null); void AttachAndModifyCompanyApplication(Guid companyApplicationId, Action setOptionalParameters); + void AttachAndModifyCompanyApplications(IEnumerable<(Guid companyApplicationId, Action? Initialize, Action Modify)> applicationData); Invitation CreateInvitation(Guid applicationId, Guid companyUserId); void DeleteInvitations(IEnumerable invitationIds); Task<(bool Exists, CompanyApplicationStatusId StatusId)> GetOwnCompanyApplicationUserDataAsync(Guid applicationId, Guid userCompanyId); diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/ICompanyRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/ICompanyRepository.cs index 53609f9668..38a7d1fb38 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/ICompanyRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/ICompanyRepository.cs @@ -52,8 +52,9 @@ public interface ICompanyRepository /// /// Get all member companies bpn /// + /// Id of the users company /// Business partner numbers of all active companies - IAsyncEnumerable GetAllMemberCompaniesBPNAsync(); + IAsyncEnumerable GetAllMemberCompaniesBPNAsync(IEnumerable? bpnIds); Task GetCompanyDetailsAsync(Guid companyId); /// @@ -157,7 +158,7 @@ public interface ICompanyRepository /// Returns the CompanyStatus Data Task<(bool IsActive, bool IsValid)> GetCompanyStatusDataAsync(Guid companyId); - Task GetOwnCompanyInformationAsync(Guid companyId); + Task GetOwnCompanyInformationAsync(Guid companyId, Guid companyUserId); IAsyncEnumerable GetOwnCompanyRolesAsync(Guid companyId); /// diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/IDocumentRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/IDocumentRepository.cs index a625b7310d..3c40b9bbb1 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/IDocumentRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/IDocumentRepository.cs @@ -95,7 +95,8 @@ public interface IDocumentRepository /// /// /// - Task<(Guid DocumentId, DocumentStatusId DocumentStatusId, bool IsSameApplicationUser, DocumentTypeId documentTypeId, bool IsQueriedApplicationStatus)> GetDocumentDetailsForApplicationUntrackedAsync(Guid documentId, Guid userCompanyId, IEnumerable applicationStatusIds); + /// + Task<(Guid DocumentId, DocumentStatusId DocumentStatusId, bool IsSameApplicationUser, DocumentTypeId documentTypeId, bool IsQueriedApplicationStatus, IEnumerable applicationId)> GetDocumentDetailsForApplicationUntrackedAsync(Guid documentId, Guid userCompanyId, IEnumerable applicationStatusIds); /// /// Attaches the document and sets the optional parameters diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/IIdentityProviderRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/IIdentityProviderRepository.cs index 534db19d70..aa40fb0601 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/IIdentityProviderRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/IIdentityProviderRepository.cs @@ -35,6 +35,7 @@ public interface IIdentityProviderRepository Task GetSharedIdentityProviderIamAliasDataUntrackedAsync(Guid companyId); Task GetIdpCategoryIdByUserIdAsync(Guid companyUserId, Guid userCompanyId); Task<(string? Alias, IdentityProviderCategoryId IamIdentityProviderCategory, bool IsOwnOrOwnerCompany, IdentityProviderTypeId TypeId)> GetOwnCompanyIdentityProviderAliasUntrackedAsync(Guid identityProviderId, Guid companyId); + Task<(string? Alias, IdentityProviderCategoryId IamIdentityProviderCategory, bool IsOwnerCompany, IdentityProviderTypeId TypeId, IEnumerable ConnectedCompanies)> GetOwnIdentityProviderWithConnectedCompanies(Guid identityProviderId, Guid companyId); Task<(bool IsOwner, string? Alias, IdentityProviderCategoryId IdentityProviderCategory, IdentityProviderTypeId IdentityProviderTypeId, IEnumerable<(Guid CompanyId, IEnumerable Aliase)>? CompanyIdAliase)> GetOwnCompanyIdentityProviderUpdateDataUntrackedAsync(Guid identityProviderId, Guid companyId, bool queryAliase); IAsyncEnumerable<(Guid IdentityProviderId, IdentityProviderCategoryId CategoryId, string? Alias, IdentityProviderTypeId TypeId)> GetCompanyIdentityProviderCategoryDataUntracked(Guid companyId); IAsyncEnumerable<(Guid IdentityProviderId, string Alias)> GetOwnCompanyIdentityProviderAliasDataUntracked(Guid companyId, IEnumerable identityProviderIds); diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/INetworkRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/INetworkRepository.cs index 12c03b8306..46e4991a9d 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/INetworkRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/INetworkRepository.cs @@ -30,6 +30,7 @@ public interface INetworkRepository Task CheckExternalIdExists(Guid externalId, Guid onboardingServiceProviderId); Task GetNetworkRegistrationDataForProcessIdAsync(Guid processId); Task<(bool RegistrationIdExists, VerifyProcessData processData)> IsValidRegistration(Guid externalId, IEnumerable processStepTypeIds); - Task<(bool Exists, IEnumerable<(Guid CompanyApplicationId, CompanyApplicationStatusId CompanyApplicationStatusId, string? CallbackUrl)> CompanyApplications, bool IsUserInRole, IEnumerable<(CompanyRoleId CompanyRoleId, IEnumerable AgreementIds)> CompanyRoleAgreementIds, Guid? ProcessId)> GetSubmitData(Guid companyId, Guid userId, IEnumerable roleIds); + Task<(bool Exists, IEnumerable<(Guid CompanyApplicationId, CompanyApplicationStatusId CompanyApplicationStatusId, string? CallbackUrl)> CompanyApplications, IEnumerable<(CompanyRoleId CompanyRoleId, IEnumerable AgreementIds)> CompanyRoleAgreementIds, Guid? ProcessId)> GetSubmitData(Guid companyId); Task<(OspDetails? OspDetails, Guid? ExternalId, string? Bpn, Guid ApplicationId, IEnumerable Comments)> GetCallbackData(Guid networkRegistrationId, ProcessStepTypeId processStepTypeId); + Task GetOspCompanyName(Guid networkRegistrationId); } diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/IOfferRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/IOfferRepository.cs index 0ebf3efd4f..581f984dbb 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/IOfferRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/IOfferRepository.cs @@ -487,4 +487,13 @@ public interface IOfferRepository /// /// Task<(bool IsSingleInstance, IEnumerable> ServiceAccountProfiles, string? OfferName)> GetServiceAccountProfileDataForSubscription(Guid subscriptionId); + + /// + /// Gets the Active Offer DocumentType Data + /// + /// + /// + /// + /// + IAsyncEnumerable GetActiveOfferDocumentTypeDataOrderedAsync(Guid offerId, Guid userCompanyId, OfferTypeId offerTypeId, IEnumerable documentTypeIds); } diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/IUserRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/IUserRepository.cs index 7ba7096318..72840bf836 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/IUserRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/IUserRepository.cs @@ -33,7 +33,7 @@ public interface IUserRepository { IAsyncEnumerable GetApplicationsWithStatusUntrackedAsync(Guid companyId); CompanyUser CreateCompanyUser(Guid identityId, string? firstName, string? lastName, string email); - Identity CreateIdentity(Guid companyId, UserStatusId userStatusId, IdentityTypeId identityTypeId); + Identity CreateIdentity(Guid companyId, UserStatusId userStatusId, IdentityTypeId identityTypeId, Action? setOptionalFields); void AttachAndModifyCompanyUser(Guid companyUserId, Action? initialize, Action setOptionalParameters); IQueryable GetOwnCompanyUserQuery(Guid companyId, Guid? companyUserId = null, string? userEntityId = null, string? firstName = null, string? lastName = null, string? email = null, IEnumerable? statusIds = null); Task<(string UserEntityId, string? FirstName, string? LastName, string? Email)> GetUserEntityDataAsync(Guid companyUserId, Guid companyId); @@ -125,4 +125,5 @@ public interface IUserRepository Identity AttachAndModifyIdentity(Guid identityId, Action? initialize, Action modify); CompanyUserAssignedIdentityProvider AddCompanyUserAssignedIdentityProvider(Guid companyUserId, Guid identityProviderId, string providerId, string userName); IAsyncEnumerable GetUserAssignedIdentityProviderForNetworkRegistration(Guid networkRegistrationId); + IAsyncEnumerable<(Guid ServiceAccountId, string ClientClientId)> GetNextServiceAccountsWithoutUserEntityId(); } diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/IdentityProviderRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/IdentityProviderRepository.cs index a2320ad015..f6ec7db2a8 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/IdentityProviderRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/IdentityProviderRepository.cs @@ -108,6 +108,19 @@ public IamIdentityProvider CreateIamIdentityProvider(Guid identityProviderId, st identityProvider.IdentityProviderTypeId)) .SingleOrDefaultAsync(); + public Task<(string? Alias, IdentityProviderCategoryId IamIdentityProviderCategory, bool IsOwnerCompany, IdentityProviderTypeId TypeId, IEnumerable ConnectedCompanies)> GetOwnIdentityProviderWithConnectedCompanies(Guid identityProviderId, Guid companyId) => + _context.IdentityProviders + .Where(identityProvider => identityProvider.Id == identityProviderId) + .Select(identityProvider => + new ValueTuple>( + identityProvider.IamIdentityProvider!.IamIdpAlias, + identityProvider.IdentityProviderCategoryId, + identityProvider.OwnerId == companyId, + identityProvider.IdentityProviderTypeId, + identityProvider.Companies.Select(c => new ConnectedCompanyData(c.Id, c.Name)) + )) + .SingleOrDefaultAsync(); + public Task<(bool IsOwner, string? Alias, IdentityProviderCategoryId IdentityProviderCategory, IdentityProviderTypeId IdentityProviderTypeId, IEnumerable<(Guid CompanyId, IEnumerable Aliase)>? CompanyIdAliase)> GetOwnCompanyIdentityProviderUpdateDataUntrackedAsync(Guid identityProviderId, Guid companyId, bool queryAliase) => _context.IdentityProviders .Where(identityProvider => identityProvider.Id == identityProviderId) diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/NetworkRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/NetworkRepository.cs index 5ab7108cdd..7a7b149e59 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/NetworkRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/NetworkRepository.cs @@ -66,11 +66,11 @@ public Task GetNetworkRegistrationDataForProcessIdAsync(Guid processId) => )) .SingleOrDefaultAsync(); - public Task<(bool Exists, IEnumerable<(Guid CompanyApplicationId, CompanyApplicationStatusId CompanyApplicationStatusId, string? CallbackUrl)> CompanyApplications, bool IsUserInRole, IEnumerable<(CompanyRoleId CompanyRoleId, IEnumerable AgreementIds)> CompanyRoleAgreementIds, Guid? ProcessId)> GetSubmitData(Guid companyId, Guid userId, IEnumerable roleIds) => + public Task<(bool Exists, IEnumerable<(Guid CompanyApplicationId, CompanyApplicationStatusId CompanyApplicationStatusId, string? CallbackUrl)> CompanyApplications, IEnumerable<(CompanyRoleId CompanyRoleId, IEnumerable AgreementIds)> CompanyRoleAgreementIds, Guid? ProcessId)> GetSubmitData(Guid companyId) => _context.Companies .AsSplitQuery() .Where(x => x.Id == companyId) - .Select(x => new ValueTuple, bool, IEnumerable<(CompanyRoleId, IEnumerable)>, Guid?>( + .Select(x => new ValueTuple, IEnumerable<(CompanyRoleId, IEnumerable)>, Guid?>( true, x.CompanyApplications .Where(ca => ca.CompanyApplicationTypeId == CompanyApplicationTypeId.EXTERNAL) @@ -78,8 +78,6 @@ public Task GetNetworkRegistrationDataForProcessIdAsync(Guid processId) => ca.Id, ca.ApplicationStatusId, ca.OnboardingServiceProvider!.OnboardingServiceProviderDetail!.CallbackUrl)), - x.Identities - .Any(i => i.Id == userId && i.IdentityAssignedRoles.Any(roles => roleIds.Any(r => r == roles.UserRoleId))), x.CompanyAssignedRoles.Select(assigned => new ValueTuple>( assigned.CompanyRoleId, assigned.CompanyRole!.AgreementAssignedCompanyRoles.Select(a => a.AgreementId))), @@ -110,4 +108,9 @@ public Task GetNetworkRegistrationDataForProcessIdAsync(Guid processId) => .Select(step => step.Message!) : new List())) .SingleOrDefaultAsync(); + + public Task GetOspCompanyName(Guid networkRegistrationId) => + _context.NetworkRegistrations.Where(x => x.Id == networkRegistrationId) + .Select(x => x.OnboardingServiceProvider!.Name) + .SingleOrDefaultAsync(); } diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/OfferRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/OfferRepository.cs index 011207dd3c..16b86b918c 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/OfferRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/OfferRepository.cs @@ -123,6 +123,7 @@ public IAsyncEnumerable GetAllActiveAppsAsync(string? languageSho offer.Tags.Select(t => t.Name), offer.Companies.Where(c => c.Id == userCompanyId) .SelectMany(company => company.OfferSubscriptions.Where(x => x.OfferId == offerId)) + .OrderByDescending(x => x.DateCreated) .Select(x => x.OfferSubscriptionStatusId) .FirstOrDefault(), offer.SupportedLanguages.Select(l => l.ShortName), @@ -822,4 +823,20 @@ public void AttachAndModifyAppInstanceSetup(Guid appInstanceSetupId, Guid offerI o.Offer.Name )) .SingleOrDefaultAsync(); + + /// + public IAsyncEnumerable GetActiveOfferDocumentTypeDataOrderedAsync(Guid offerId, Guid userCompanyId, OfferTypeId offerTypeId, IEnumerable documentTypeIds) => + _context.OfferAssignedDocuments + .Where(oad => oad.OfferId == offerId && + oad.Offer!.OfferStatusId == OfferStatusId.ACTIVE && + oad.Offer.OfferTypeId == offerTypeId && + oad.Offer.ProviderCompanyId == userCompanyId && + oad.Document!.DocumentStatusId != DocumentStatusId.INACTIVE && + documentTypeIds.Contains(oad.Document!.DocumentTypeId)) + .OrderBy(oad => oad.Document!.DocumentTypeId) + .Select(oad => new DocumentTypeData( + oad.Document!.DocumentTypeId, + oad.Document.Id, + oad.Document.DocumentName)) + .ToAsyncEnumerable(); } diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/OfferSubscriptionsRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/OfferSubscriptionsRepository.cs index d8701023b4..efc1f7f788 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/OfferSubscriptionsRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/OfferSubscriptionsRepository.cs @@ -44,7 +44,7 @@ public OfferSubscriptionsRepository(PortalDbContext portalDbContext) /// public OfferSubscription CreateOfferSubscription(Guid offerId, Guid companyId, OfferSubscriptionStatusId offerSubscriptionStatusId, Guid requesterId) => - _context.OfferSubscriptions.Add(new OfferSubscription(Guid.NewGuid(), offerId, companyId, offerSubscriptionStatusId, requesterId)).Entity; + _context.OfferSubscriptions.Add(new OfferSubscription(Guid.NewGuid(), offerId, companyId, offerSubscriptionStatusId, requesterId, DateTimeOffset.UtcNow)).Entity; /// public Func?>> GetOwnCompanyProvidedOfferSubscriptionStatusesUntrackedAsync(Guid userCompanyId, OfferTypeId offerTypeId, SubscriptionStatusSorting? sorting, IEnumerable statusIds, Guid? offerId) => @@ -86,7 +86,12 @@ public OfferSubscription CreateOfferSubscription(Guid offerId, Guid companyId, O Image = g.Documents .Where(document => document.DocumentTypeId == DocumentTypeId.APP_LEADIMAGE && document.DocumentStatusId == DocumentStatusId.LOCKED) .Select(document => document.Id) - .FirstOrDefault() + .FirstOrDefault(), + ProcessStepTypeId = g.OfferSubscriptions + .Where(os => os.ProcessId != null) + .Select(os => os.Process!.ProcessSteps + .OrderByDescending(ps => ps.DateCreated) + .Select(ps => ps.ProcessStepTypeId).FirstOrDefault()).FirstOrDefault() }) .SingleOrDefaultAsync(); @@ -173,7 +178,7 @@ public Task CheckPendingOrActiveSubscriptionExists(Guid offerId, Guid comp /// public OfferSubscription AttachAndModifyOfferSubscription(Guid offerSubscriptionId, Action setOptionalParameters) { - var offerSubscription = _context.Attach(new OfferSubscription(offerSubscriptionId, Guid.Empty, Guid.Empty, default, Guid.Empty)).Entity; + var offerSubscription = _context.Attach(new OfferSubscription(offerSubscriptionId, Guid.Empty, Guid.Empty, default, Guid.Empty, default)).Entity; setOptionalParameters.Invoke(offerSubscription); return offerSubscription; } @@ -244,7 +249,9 @@ public OfferSubscription AttachAndModifyOfferSubscription(Guid offerSubscription x.Company.Identities.Where(i => i.IdentityTypeId == IdentityTypeId.COMPANY_USER).Select(id => id.CompanyUser!).Where(cu => cu.Email != null && cu.Identity!.IdentityAssignedRoles.Select(ur => ur.UserRole!).Any(ur => userRoleIds.Contains(ur.Id))).Select(cu => cu.Email!), x.Subscription.CompanyServiceAccounts.Select(sa => new SubscriptionTechnicalUserData(sa.Id, sa.Name, sa.Identity!.IdentityAssignedRoles.Select(ur => ur.UserRole!).Select(ur => ur.UserRoleText))), x.Subscription.AppSubscriptionDetail!.AppSubscriptionUrl, - x.Subscription.AppSubscriptionDetail!.AppInstance!.IamClient!.ClientClientId) + x.Subscription.AppSubscriptionDetail!.AppInstance!.IamClient!.ClientClientId, + x.Subscription.Process!.ProcessSteps.Any() ? + x.Subscription.Process!.ProcessSteps.OrderByDescending(ps => ps.DateCreated).Select(ps => ps.ProcessStepTypeId).FirstOrDefault() : null) : null)) .SingleOrDefaultAsync(); @@ -362,9 +369,9 @@ public Task GetOfferSubscriptionDataForProcessIdAsync(Guid processId) => x.RequesterCompany!.Id, x.RequesterCompany.Name, x.RequesterCompany.Address!.CountryAlpha2Code, - x.RequesterCompany.BusinessPartnerNumber + x.RequesterCompany.BusinessPartnerNumber, + x.Email ), - x.Email, x.OfferTypeId, x.SalesManagerId, x.CompanyUserId, diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/UserRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/UserRepository.cs index dfe4ca0f85..e0a0e5f4f4 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/UserRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/UserRepository.cs @@ -63,14 +63,17 @@ public CompanyUser CreateCompanyUser(Guid identityId, string? firstName, string? }).Entity; /// - public Identity CreateIdentity(Guid companyId, UserStatusId userStatusId, IdentityTypeId identityTypeId) => - _dbContext.Identities.Add( - new Identity( - Guid.NewGuid(), - DateTimeOffset.UtcNow, - companyId, - userStatusId, - identityTypeId)).Entity; + public Identity CreateIdentity(Guid companyId, UserStatusId userStatusId, IdentityTypeId identityTypeId, Action? setOptionalFields) + { + var identity = new Identity( + Guid.NewGuid(), + DateTimeOffset.UtcNow, + companyId, + userStatusId, + identityTypeId); + setOptionalFields?.Invoke(identity); + return _dbContext.Identities.Add(identity).Entity; + } public void AttachAndModifyCompanyUser(Guid companyUserId, Action? initialize, Action setOptionalParameters) { @@ -463,4 +466,15 @@ public IAsyncEnumerable GetUserAssignedI cu.CompanyUserAssignedIdentityProviders.Select(assigned => new ProviderLinkData(assigned.UserName, assigned.IdentityProvider!.IamIdentityProvider!.IamIdpAlias, assigned.ProviderId)) )) .ToAsyncEnumerable(); + + public IAsyncEnumerable<(Guid ServiceAccountId, string ClientClientId)> GetNextServiceAccountsWithoutUserEntityId() => + _dbContext.Identities + .Where(x => + x.IdentityTypeId == IdentityTypeId.COMPANY_SERVICE_ACCOUNT && + x.UserEntityId == null && + x.CompanyServiceAccount!.ClientClientId != null && + x.UserStatusId == UserStatusId.ACTIVE) + .Select(x => new ValueTuple(x.Id, x.CompanyServiceAccount!.ClientClientId!)) + .Take(2) + .ToAsyncEnumerable(); } diff --git a/src/portalbackend/PortalBackend.Migrations/Migrations/20231024094241_1.7.0-rc1.Designer.cs b/src/portalbackend/PortalBackend.Migrations/Migrations/20231024094241_1.7.0-rc1.Designer.cs new file mode 100644 index 0000000000..6b8a19c948 --- /dev/null +++ b/src/portalbackend/PortalBackend.Migrations/Migrations/20231024094241_1.7.0-rc1.Designer.cs @@ -0,0 +1,7852 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 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 Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities; + +#nullable disable + +namespace Org.Eclipse.TractusX.Portal.Backend.PortalBackend.Migrations.Migrations +{ + [DbContext(typeof(PortalDbContext))] + [Migration("20231024094241_1.7.0-rc1")] + partial class _170rc1 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("portal") + .UseCollation("en_US.utf8") + .HasAnnotation("ProductVersion", "7.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.AuditEntities.AuditAppSubscriptionDetail20221118", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("AppInstanceId") + .HasColumnType("uuid") + .HasColumnName("app_instance_id"); + + b.Property("AppSubscriptionUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("app_subscription_url"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("OfferSubscriptionId") + .HasColumnType("uuid") + .HasColumnName("offer_subscription_id"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_app_subscription_detail20221118"); + + b.ToTable("audit_app_subscription_detail20221118", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.AuditEntities.AuditCompanyApplication20221005", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("ApplicationStatusId") + .HasColumnType("integer") + .HasColumnName("application_status_id"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_company_application20221005"); + + b.ToTable("audit_company_application20221005", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.AuditEntities.AuditCompanyApplication20230214", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("ApplicationStatusId") + .HasColumnType("integer") + .HasColumnName("application_status_id"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("ChecklistProcessId") + .HasColumnType("uuid") + .HasColumnName("checklist_process_id"); + + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_company_application20230214"); + + b.ToTable("audit_company_application20230214", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.AuditEntities.AuditCompanyApplication20230824", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("ApplicationStatusId") + .HasColumnType("integer") + .HasColumnName("application_status_id"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("ChecklistProcessId") + .HasColumnType("uuid") + .HasColumnName("checklist_process_id"); + + b.Property("CompanyApplicationTypeId") + .HasColumnType("integer") + .HasColumnName("company_application_type_id"); + + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("OnboardingServiceProviderId") + .HasColumnType("uuid") + .HasColumnName("onboarding_service_provider_id"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_company_application20230824"); + + b.ToTable("audit_company_application20230824", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.AuditEntities.AuditCompanyAssignedRole2023316", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("CompanyRoleId") + .HasColumnType("integer") + .HasColumnName("company_role_id"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_company_assigned_role2023316"); + + b.ToTable("audit_company_assigned_role2023316", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.AuditEntities.AuditCompanyUser20221005", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("CompanyUserStatusId") + .HasColumnType("integer") + .HasColumnName("company_user_status_id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("Email") + .HasColumnType("text") + .HasColumnName("email"); + + b.Property("Firstname") + .HasColumnType("text") + .HasColumnName("firstname"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("Lastlogin") + .HasColumnType("bytea") + .HasColumnName("lastlogin"); + + b.Property("Lastname") + .HasColumnType("text") + .HasColumnName("lastname"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_company_user20221005"); + + b.ToTable("audit_company_user20221005", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.AuditEntities.AuditCompanyUser20230522", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("Email") + .HasColumnType("text") + .HasColumnName("email"); + + b.Property("Firstname") + .HasColumnType("text") + .HasColumnName("firstname"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("Lastlogin") + .HasColumnType("bytea") + .HasColumnName("lastlogin"); + + b.Property("Lastname") + .HasColumnType("text") + .HasColumnName("lastname"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_company_user20230523"); + + b.ToTable("audit_company_user20230523", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.AuditEntities.AuditCompanyUserAssignedRole20221018", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("CompanyUserId") + .HasColumnType("uuid") + .HasColumnName("company_user_id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("UserRoleId") + .HasColumnType("uuid") + .HasColumnName("user_role_id"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_company_user_assigned_role20221018"); + + b.ToTable("audit_company_user_assigned_role20221018", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.AuditEntities.AuditConnector20230405", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("ConnectorUrl") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("connector_url"); + + b.Property("DapsRegistrationSuccessful") + .HasColumnType("boolean") + .HasColumnName("daps_registration_successful"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("HostId") + .HasColumnType("uuid") + .HasColumnName("host_id"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("LocationId") + .IsRequired() + .HasMaxLength(2) + .HasColumnType("character varying(2)") + .HasColumnName("location_id"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name"); + + b.Property("ProviderId") + .HasColumnType("uuid") + .HasColumnName("provider_id"); + + b.Property("SelfDescriptionDocumentId") + .HasColumnType("uuid") + .HasColumnName("self_description_document_id"); + + b.Property("SelfDescriptionMessage") + .HasColumnType("text") + .HasColumnName("self_description_message"); + + b.Property("StatusId") + .HasColumnType("integer") + .HasColumnName("status_id"); + + b.Property("TypeId") + .HasColumnType("integer") + .HasColumnName("type_id"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_connector20230405"); + + b.ToTable("audit_connector20230405", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.AuditEntities.AuditConnector20230503", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("CompanyServiceAccountId") + .HasColumnType("uuid") + .HasColumnName("company_service_account_id"); + + b.Property("ConnectorUrl") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("connector_url"); + + b.Property("DapsRegistrationSuccessful") + .HasColumnType("boolean") + .HasColumnName("daps_registration_successful"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("HostId") + .HasColumnType("uuid") + .HasColumnName("host_id"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("LocationId") + .IsRequired() + .HasMaxLength(2) + .HasColumnType("character varying(2)") + .HasColumnName("location_id"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name"); + + b.Property("ProviderId") + .HasColumnType("uuid") + .HasColumnName("provider_id"); + + b.Property("SelfDescriptionDocumentId") + .HasColumnType("uuid") + .HasColumnName("self_description_document_id"); + + b.Property("SelfDescriptionMessage") + .HasColumnType("text") + .HasColumnName("self_description_message"); + + b.Property("StatusId") + .HasColumnType("integer") + .HasColumnName("status_id"); + + b.Property("TypeId") + .HasColumnType("integer") + .HasColumnName("type_id"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_connector20230503"); + + b.ToTable("audit_connector20230503", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.AuditEntities.AuditConnector20230803", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("CompanyServiceAccountId") + .HasColumnType("uuid") + .HasColumnName("company_service_account_id"); + + b.Property("ConnectorUrl") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("connector_url"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("HostId") + .HasColumnType("uuid") + .HasColumnName("host_id"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("LocationId") + .IsRequired() + .HasMaxLength(2) + .HasColumnType("character varying(2)") + .HasColumnName("location_id"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name"); + + b.Property("ProviderId") + .HasColumnType("uuid") + .HasColumnName("provider_id"); + + b.Property("SelfDescriptionDocumentId") + .HasColumnType("uuid") + .HasColumnName("self_description_document_id"); + + b.Property("SelfDescriptionMessage") + .HasColumnType("text") + .HasColumnName("self_description_message"); + + b.Property("StatusId") + .HasColumnType("integer") + .HasColumnName("status_id"); + + b.Property("TypeId") + .HasColumnType("integer") + .HasColumnName("type_id"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_connector20230803"); + + b.ToTable("audit_connector20230803", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.AuditEntities.AuditConsent20230412", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("AgreementId") + .HasColumnType("uuid") + .HasColumnName("agreement_id"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("Comment") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("comment"); + + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("CompanyUserId") + .HasColumnType("uuid") + .HasColumnName("company_user_id"); + + b.Property("ConsentStatusId") + .HasColumnType("integer") + .HasColumnName("consent_status_id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DocumentId") + .HasColumnType("uuid") + .HasColumnName("document_id"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("Target") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("target"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_consent20230412"); + + b.ToTable("audit_consent20230412", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.AuditEntities.AuditIdentityAssignedRole20230522", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("IdentityId") + .HasColumnType("uuid") + .HasColumnName("identity_id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("UserRoleId") + .HasColumnType("uuid") + .HasColumnName("user_role_id"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_identity_assigned_role20230522"); + + b.ToTable("audit_identity_assigned_role20230522", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.AuditEntities.AuditOffer20230119", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("ContactEmail") + .HasColumnType("text") + .HasColumnName("contact_email"); + + b.Property("ContactNumber") + .HasColumnType("text") + .HasColumnName("contact_number"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("DateReleased") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_released"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("MarketingUrl") + .HasColumnType("text") + .HasColumnName("marketing_url"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("OfferStatusId") + .HasColumnType("integer") + .HasColumnName("offer_status_id"); + + b.Property("OfferTypeId") + .HasColumnType("integer") + .HasColumnName("offer_type_id"); + + b.Property("Provider") + .IsRequired() + .HasColumnType("text") + .HasColumnName("provider"); + + b.Property("ProviderCompanyId") + .HasColumnType("uuid") + .HasColumnName("provider_company_id"); + + b.Property("SalesManagerId") + .HasColumnType("uuid") + .HasColumnName("sales_manager_id"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_offer20230119"); + + b.ToTable("audit_offer20230119", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.AuditEntities.AuditOffer20230406", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("ContactEmail") + .HasColumnType("text") + .HasColumnName("contact_email"); + + b.Property("ContactNumber") + .HasColumnType("text") + .HasColumnName("contact_number"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("DateReleased") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_released"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("LicenseTypeId") + .HasColumnType("integer") + .HasColumnName("license_type_id"); + + b.Property("MarketingUrl") + .HasColumnType("text") + .HasColumnName("marketing_url"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("OfferStatusId") + .HasColumnType("integer") + .HasColumnName("offer_status_id"); + + b.Property("OfferTypeId") + .HasColumnType("integer") + .HasColumnName("offer_type_id"); + + b.Property("Provider") + .IsRequired() + .HasColumnType("text") + .HasColumnName("provider"); + + b.Property("ProviderCompanyId") + .HasColumnType("uuid") + .HasColumnName("provider_company_id"); + + b.Property("SalesManagerId") + .HasColumnType("uuid") + .HasColumnName("sales_manager_id"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_offer20230406"); + + b.ToTable("audit_offer20230406", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.AuditEntities.AuditOfferSubscription20221005", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("DisplayName") + .HasColumnType("text") + .HasColumnName("display_name"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("OfferId") + .HasColumnType("uuid") + .HasColumnName("offer_id"); + + b.Property("OfferSubscriptionStatusId") + .HasColumnType("integer") + .HasColumnName("offer_subscription_status_id"); + + b.Property("RequesterId") + .HasColumnType("uuid") + .HasColumnName("requester_id"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_offer_subscription20221005"); + + b.ToTable("audit_offer_subscription20221005", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.AuditEntities.AuditOfferSubscription20230317", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("DisplayName") + .HasColumnType("text") + .HasColumnName("display_name"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("OfferId") + .HasColumnType("uuid") + .HasColumnName("offer_id"); + + b.Property("OfferSubscriptionStatusId") + .HasColumnType("integer") + .HasColumnName("offer_subscription_status_id"); + + b.Property("ProcessId") + .HasColumnType("uuid") + .HasColumnName("process_id"); + + b.Property("RequesterId") + .HasColumnType("uuid") + .HasColumnName("requester_id"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_offer_subscription20230317"); + + b.ToTable("audit_offer_subscription20230317", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.AuditEntities.AuditOfferSubscription20231013", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("DisplayName") + .HasColumnType("text") + .HasColumnName("display_name"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("OfferId") + .HasColumnType("uuid") + .HasColumnName("offer_id"); + + b.Property("OfferSubscriptionStatusId") + .HasColumnType("integer") + .HasColumnName("offer_subscription_status_id"); + + b.Property("ProcessId") + .HasColumnType("uuid") + .HasColumnName("process_id"); + + b.Property("RequesterId") + .HasColumnType("uuid") + .HasColumnName("requester_id"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_offer_subscription20231013"); + + b.ToTable("audit_offer_subscription20231013", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.AuditEntities.AuditProviderCompanyDetail20230614", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("AutoSetupCallbackUrl") + .HasColumnType("text") + .HasColumnName("auto_setup_callback_url"); + + b.Property("AutoSetupUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("auto_setup_url"); + + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_provider_company_detail20230614"); + + b.ToTable("audit_provider_company_detail20230614", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.AuditEntities.AuditUserRole20221017", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("OfferId") + .HasColumnType("uuid") + .HasColumnName("offer_id"); + + b.Property("UserRoleText") + .IsRequired() + .HasColumnType("text") + .HasColumnName("user_role"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_user_role20221017"); + + b.ToTable("audit_user_role20221017", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Address", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("City") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("city"); + + b.Property("CountryAlpha2Code") + .IsRequired() + .HasMaxLength(2) + .HasColumnType("character(2)") + .HasColumnName("country_alpha2code") + .HasAnnotation("Relational:JsonPropertyName", "country_alpha2code"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("Region") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("region"); + + b.Property("Streetadditional") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("streetadditional"); + + b.Property("Streetname") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("streetname"); + + b.Property("Streetnumber") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("streetnumber"); + + b.Property("Zipcode") + .HasMaxLength(12) + .HasColumnType("character varying(12)") + .HasColumnName("zipcode"); + + b.HasKey("Id") + .HasName("pk_addresses"); + + b.HasIndex("CountryAlpha2Code") + .HasDatabaseName("ix_addresses_country_alpha2code"); + + b.ToTable("addresses", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Agreement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AgreementCategoryId") + .HasColumnType("integer") + .HasColumnName("agreement_category_id"); + + b.Property("AgreementLink") + .HasColumnType("text") + .HasColumnName("agreement_link"); + + b.Property("AgreementType") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("agreement_type"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("DocumentId") + .HasColumnType("uuid") + .HasColumnName("document_id"); + + b.Property("IssuerCompanyId") + .HasColumnType("uuid") + .HasColumnName("issuer_company_id"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name"); + + b.Property("UseCaseId") + .HasColumnType("uuid") + .HasColumnName("use_case_id"); + + b.HasKey("Id") + .HasName("pk_agreements"); + + b.HasIndex("AgreementCategoryId") + .HasDatabaseName("ix_agreements_agreement_category_id"); + + b.HasIndex("DocumentId") + .HasDatabaseName("ix_agreements_document_id"); + + b.HasIndex("IssuerCompanyId") + .HasDatabaseName("ix_agreements_issuer_company_id"); + + b.HasIndex("UseCaseId") + .HasDatabaseName("ix_agreements_use_case_id"); + + b.ToTable("agreements", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AgreementAssignedCompanyRole", b => + { + b.Property("AgreementId") + .HasColumnType("uuid") + .HasColumnName("agreement_id"); + + b.Property("CompanyRoleId") + .HasColumnType("integer") + .HasColumnName("company_role_id"); + + b.HasKey("AgreementId", "CompanyRoleId") + .HasName("pk_agreement_assigned_company_roles"); + + b.HasIndex("CompanyRoleId") + .HasDatabaseName("ix_agreement_assigned_company_roles_company_role_id"); + + b.ToTable("agreement_assigned_company_roles", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AgreementAssignedOffer", b => + { + b.Property("AgreementId") + .HasColumnType("uuid") + .HasColumnName("agreement_id"); + + b.Property("OfferId") + .HasColumnType("uuid") + .HasColumnName("offer_id"); + + b.HasKey("AgreementId", "OfferId") + .HasName("pk_agreement_assigned_offers"); + + b.HasIndex("OfferId") + .HasDatabaseName("ix_agreement_assigned_offers_offer_id"); + + b.ToTable("agreement_assigned_offers", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AgreementAssignedOfferType", b => + { + b.Property("AgreementId") + .HasColumnType("uuid") + .HasColumnName("agreement_id"); + + b.Property("OfferTypeId") + .HasColumnType("integer") + .HasColumnName("offer_type_id"); + + b.HasKey("AgreementId", "OfferTypeId") + .HasName("pk_agreement_assigned_offer_types"); + + b.HasIndex("OfferTypeId") + .HasDatabaseName("ix_agreement_assigned_offer_types_offer_type_id"); + + b.ToTable("agreement_assigned_offer_types", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AgreementCategory", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_agreement_categories"); + + b.ToTable("agreement_categories", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "CX_FRAME_CONTRACT" + }, + new + { + Id = 2, + Label = "APP_CONTRACT" + }, + new + { + Id = 3, + Label = "DATA_CONTRACT" + }, + new + { + Id = 4, + Label = "SERVICE_CONTRACT" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AppAssignedUseCase", b => + { + b.Property("AppId") + .HasColumnType("uuid") + .HasColumnName("app_id"); + + b.Property("UseCaseId") + .HasColumnType("uuid") + .HasColumnName("use_case_id"); + + b.HasKey("AppId", "UseCaseId") + .HasName("pk_app_assigned_use_cases"); + + b.HasIndex("UseCaseId") + .HasDatabaseName("ix_app_assigned_use_cases_use_case_id"); + + b.ToTable("app_assigned_use_cases", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AppInstance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AppId") + .HasColumnType("uuid") + .HasColumnName("app_id"); + + b.Property("IamClientId") + .HasColumnType("uuid") + .HasColumnName("iam_client_id"); + + b.HasKey("Id") + .HasName("pk_app_instances"); + + b.HasIndex("AppId") + .HasDatabaseName("ix_app_instances_app_id"); + + b.HasIndex("IamClientId") + .HasDatabaseName("ix_app_instances_iam_client_id"); + + b.ToTable("app_instances", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AppInstanceAssignedCompanyServiceAccount", b => + { + b.Property("AppInstanceId") + .HasColumnType("uuid") + .HasColumnName("app_instance_id"); + + b.Property("CompanyServiceAccountId") + .HasColumnType("uuid") + .HasColumnName("company_service_account_id"); + + b.HasKey("AppInstanceId", "CompanyServiceAccountId") + .HasName("pk_app_instance_assigned_service_accounts"); + + b.HasIndex("CompanyServiceAccountId") + .HasDatabaseName("ix_app_instance_assigned_service_accounts_company_service_acco"); + + b.ToTable("app_instance_assigned_service_accounts", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AppInstanceSetup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AppId") + .HasColumnType("uuid") + .HasColumnName("app_id"); + + b.Property("InstanceUrl") + .HasColumnType("text") + .HasColumnName("instance_url"); + + b.Property("IsSingleInstance") + .HasColumnType("boolean") + .HasColumnName("is_single_instance"); + + b.HasKey("Id") + .HasName("pk_app_instance_setups"); + + b.HasIndex("AppId") + .IsUnique() + .HasDatabaseName("ix_app_instance_setups_app_id"); + + b.ToTable("app_instance_setups", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AppLanguage", b => + { + b.Property("AppId") + .HasColumnType("uuid") + .HasColumnName("app_id"); + + b.Property("LanguageShortName") + .HasMaxLength(2) + .HasColumnType("character(2)") + .HasColumnName("language_short_name"); + + b.HasKey("AppId", "LanguageShortName") + .HasName("pk_app_languages"); + + b.HasIndex("LanguageShortName") + .HasDatabaseName("ix_app_languages_language_short_name"); + + b.ToTable("app_languages", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AppSubscriptionDetail", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AppInstanceId") + .HasColumnType("uuid") + .HasColumnName("app_instance_id"); + + b.Property("AppSubscriptionUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("app_subscription_url"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("OfferSubscriptionId") + .HasColumnType("uuid") + .HasColumnName("offer_subscription_id"); + + b.HasKey("Id") + .HasName("pk_app_subscription_details"); + + b.HasIndex("AppInstanceId") + .HasDatabaseName("ix_app_subscription_details_app_instance_id"); + + b.HasIndex("LastEditorId") + .HasDatabaseName("ix_app_subscription_details_last_editor_id"); + + b.HasIndex("OfferSubscriptionId") + .IsUnique() + .HasDatabaseName("ix_app_subscription_details_offer_subscription_id"); + + b.ToTable("app_subscription_details", "portal", t => + { + t.HasTrigger("LC_TRIGGER_AFTER_INSERT_APPSUBSCRIPTIONDETAIL"); + + t.HasTrigger("LC_TRIGGER_AFTER_UPDATE_APPSUBSCRIPTIONDETAIL"); + }); + + b + .HasAnnotation("LC_TRIGGER_AFTER_INSERT_APPSUBSCRIPTIONDETAIL", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_INSERT_APPSUBSCRIPTIONDETAIL\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_APPSUBSCRIPTIONDETAIL$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_app_subscription_detail20221118\" (\"id\", \"offer_subscription_id\", \"app_instance_id\", \"app_subscription_url\", \"last_editor_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"offer_subscription_id\", \r\n NEW.\"app_instance_id\", \r\n NEW.\"app_subscription_url\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_APPSUBSCRIPTIONDETAIL$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_APPSUBSCRIPTIONDETAIL AFTER INSERT\r\nON \"portal\".\"app_subscription_details\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_INSERT_APPSUBSCRIPTIONDETAIL\"();") + .HasAnnotation("LC_TRIGGER_AFTER_UPDATE_APPSUBSCRIPTIONDETAIL", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_UPDATE_APPSUBSCRIPTIONDETAIL\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_APPSUBSCRIPTIONDETAIL$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_app_subscription_detail20221118\" (\"id\", \"offer_subscription_id\", \"app_instance_id\", \"app_subscription_url\", \"last_editor_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"offer_subscription_id\", \r\n NEW.\"app_instance_id\", \r\n NEW.\"app_subscription_url\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_APPSUBSCRIPTIONDETAIL$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_APPSUBSCRIPTIONDETAIL AFTER UPDATE\r\nON \"portal\".\"app_subscription_details\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_UPDATE_APPSUBSCRIPTIONDETAIL\"();"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ApplicationChecklistEntry", b => + { + b.Property("ApplicationId") + .HasColumnType("uuid") + .HasColumnName("application_id"); + + b.Property("ApplicationChecklistEntryTypeId") + .HasColumnType("integer") + .HasColumnName("application_checklist_entry_type_id"); + + b.Property("ApplicationChecklistEntryStatusId") + .HasColumnType("integer") + .HasColumnName("application_checklist_entry_status_id"); + + b.Property("Comment") + .HasColumnType("text") + .HasColumnName("comment"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.HasKey("ApplicationId", "ApplicationChecklistEntryTypeId") + .HasName("pk_application_checklist"); + + b.HasIndex("ApplicationChecklistEntryStatusId") + .HasDatabaseName("ix_application_checklist_application_checklist_entry_status_id"); + + b.HasIndex("ApplicationChecklistEntryTypeId") + .HasDatabaseName("ix_application_checklist_application_checklist_entry_type_id"); + + b.ToTable("application_checklist", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ApplicationChecklistEntryStatus", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_application_checklist_statuses"); + + b.ToTable("application_checklist_statuses", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "TO_DO" + }, + new + { + Id = 2, + Label = "IN_PROGRESS" + }, + new + { + Id = 3, + Label = "DONE" + }, + new + { + Id = 4, + Label = "FAILED" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ApplicationChecklistEntryType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_application_checklist_types"); + + b.ToTable("application_checklist_types", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "REGISTRATION_VERIFICATION" + }, + new + { + Id = 2, + Label = "BUSINESS_PARTNER_NUMBER" + }, + new + { + Id = 3, + Label = "IDENTITY_WALLET" + }, + new + { + Id = 4, + Label = "CLEARING_HOUSE" + }, + new + { + Id = 5, + Label = "SELF_DESCRIPTION_LP" + }, + new + { + Id = 6, + Label = "APPLICATION_ACTIVATION" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AuditCompanySsiDetail20230621", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("CompanySsiDetailStatusId") + .HasColumnType("integer") + .HasColumnName("company_ssi_detail_status_id"); + + b.Property("CreatorUserId") + .HasColumnType("uuid") + .HasColumnName("creator_user_id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("DocumentId") + .HasColumnType("uuid") + .HasColumnName("document_id"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiry_date"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("VerifiedCredentialExternalTypeUseCaseDetailId") + .HasColumnType("uuid") + .HasColumnName("verified_credential_external_type_use_case_detail_id"); + + b.Property("VerifiedCredentialTypeId") + .HasColumnType("integer") + .HasColumnName("verified_credential_type_id"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_company_ssi_detail20230621"); + + b.ToTable("audit_company_ssi_detail20230621", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AuditIdentity20230526", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("IdentityTypeId") + .HasColumnType("integer") + .HasColumnName("identity_type_id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("UserEntityId") + .HasMaxLength(36) + .HasColumnType("character varying(36)") + .HasColumnName("user_entity_id"); + + b.Property("UserStatusId") + .HasColumnType("integer") + .HasColumnName("user_status_id") + .HasAnnotation("Relational:JsonPropertyName", "user_status_id"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_identity20230526"); + + b.ToTable("audit_identity20230526", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AuditOperation", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_audit_operation"); + + b.ToTable("audit_operation", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "INSERT" + }, + new + { + Id = 2, + Label = "UPDATE" + }, + new + { + Id = 3, + Label = "DELETE" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.BpdmIdentifier", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_bpdm_identifiers"); + + b.ToTable("bpdm_identifiers", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "EU_VAT_ID_DE" + }, + new + { + Id = 2, + Label = "CH_UID" + }, + new + { + Id = 3, + Label = "EU_VAT_ID_FR" + }, + new + { + Id = 4, + Label = "FR_SIREN" + }, + new + { + Id = 5, + Label = "EU_VAT_ID_AT" + }, + new + { + Id = 6, + Label = "DE_BNUM" + }, + new + { + Id = 7, + Label = "CZ_ICO" + }, + new + { + Id = 8, + Label = "EU_VAT_ID_CZ" + }, + new + { + Id = 9, + Label = "EU_VAT_ID_PL" + }, + new + { + Id = 10, + Label = "EU_VAT_ID_BE" + }, + new + { + Id = 11, + Label = "EU_VAT_ID_CH" + }, + new + { + Id = 12, + Label = "EU_VAT_ID_DK" + }, + new + { + Id = 13, + Label = "EU_VAT_ID_ES" + }, + new + { + Id = 14, + Label = "EU_VAT_ID_GB" + }, + new + { + Id = 15, + Label = "EU_VAT_ID_NO" + }, + new + { + Id = 16, + Label = "BE_ENT_NO" + }, + new + { + Id = 17, + Label = "CVR_DK" + }, + new + { + Id = 18, + Label = "ID_CRN" + }, + new + { + Id = 19, + Label = "NO_ORGID" + }, + new + { + Id = 20, + Label = "LEI_ID" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Company", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AddressId") + .HasColumnType("uuid") + .HasColumnName("address_id"); + + b.Property("BusinessPartnerNumber") + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasColumnName("business_partner_number"); + + b.Property("CompanyStatusId") + .HasColumnType("integer") + .HasColumnName("company_status_id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name"); + + b.Property("SelfDescriptionDocumentId") + .HasColumnType("uuid") + .HasColumnName("self_description_document_id"); + + b.Property("Shortname") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("shortname"); + + b.HasKey("Id") + .HasName("pk_companies"); + + b.HasIndex("AddressId") + .HasDatabaseName("ix_companies_address_id"); + + b.HasIndex("CompanyStatusId") + .HasDatabaseName("ix_companies_company_status_id"); + + b.HasIndex("SelfDescriptionDocumentId") + .HasDatabaseName("ix_companies_self_description_document_id"); + + b.ToTable("companies", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ApplicationStatusId") + .HasColumnType("integer") + .HasColumnName("application_status_id"); + + b.Property("ChecklistProcessId") + .HasColumnType("uuid") + .HasColumnName("checklist_process_id"); + + b.Property("CompanyApplicationTypeId") + .HasColumnType("integer") + .HasColumnName("company_application_type_id"); + + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("OnboardingServiceProviderId") + .HasColumnType("uuid") + .HasColumnName("onboarding_service_provider_id"); + + b.HasKey("Id") + .HasName("pk_company_applications"); + + b.HasIndex("ApplicationStatusId") + .HasDatabaseName("ix_company_applications_application_status_id"); + + b.HasIndex("ChecklistProcessId") + .IsUnique() + .HasDatabaseName("ix_company_applications_checklist_process_id"); + + b.HasIndex("CompanyApplicationTypeId") + .HasDatabaseName("ix_company_applications_company_application_type_id"); + + b.HasIndex("CompanyId") + .HasDatabaseName("ix_company_applications_company_id"); + + b.HasIndex("LastEditorId") + .HasDatabaseName("ix_company_applications_last_editor_id"); + + b.HasIndex("OnboardingServiceProviderId") + .HasDatabaseName("ix_company_applications_onboarding_service_provider_id"); + + b.ToTable("company_applications", "portal", t => + { + t.HasTrigger("LC_TRIGGER_AFTER_INSERT_COMPANYAPPLICATION"); + + t.HasTrigger("LC_TRIGGER_AFTER_UPDATE_COMPANYAPPLICATION"); + }); + + b + .HasAnnotation("LC_TRIGGER_AFTER_INSERT_COMPANYAPPLICATION", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_INSERT_COMPANYAPPLICATION\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_COMPANYAPPLICATION$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_company_application20230824\" (\"id\", \"date_created\", \"date_last_changed\", \"application_status_id\", \"company_id\", \"checklist_process_id\", \"company_application_type_id\", \"onboarding_service_provider_id\", \"last_editor_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"date_created\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"application_status_id\", \r\n NEW.\"company_id\", \r\n NEW.\"checklist_process_id\", \r\n NEW.\"company_application_type_id\", \r\n NEW.\"onboarding_service_provider_id\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_COMPANYAPPLICATION$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_COMPANYAPPLICATION AFTER INSERT\r\nON \"portal\".\"company_applications\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_INSERT_COMPANYAPPLICATION\"();") + .HasAnnotation("LC_TRIGGER_AFTER_UPDATE_COMPANYAPPLICATION", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_UPDATE_COMPANYAPPLICATION\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_COMPANYAPPLICATION$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_company_application20230824\" (\"id\", \"date_created\", \"date_last_changed\", \"application_status_id\", \"company_id\", \"checklist_process_id\", \"company_application_type_id\", \"onboarding_service_provider_id\", \"last_editor_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"date_created\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"application_status_id\", \r\n NEW.\"company_id\", \r\n NEW.\"checklist_process_id\", \r\n NEW.\"company_application_type_id\", \r\n NEW.\"onboarding_service_provider_id\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_COMPANYAPPLICATION$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_COMPANYAPPLICATION AFTER UPDATE\r\nON \"portal\".\"company_applications\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_UPDATE_COMPANYAPPLICATION\"();"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyApplicationStatus", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_company_application_statuses"); + + b.ToTable("company_application_statuses", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "CREATED" + }, + new + { + Id = 2, + Label = "ADD_COMPANY_DATA" + }, + new + { + Id = 3, + Label = "INVITE_USER" + }, + new + { + Id = 4, + Label = "SELECT_COMPANY_ROLE" + }, + new + { + Id = 5, + Label = "UPLOAD_DOCUMENTS" + }, + new + { + Id = 6, + Label = "VERIFY" + }, + new + { + Id = 7, + Label = "SUBMITTED" + }, + new + { + Id = 8, + Label = "CONFIRMED" + }, + new + { + Id = 9, + Label = "DECLINED" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyApplicationType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_company_application_types"); + + b.ToTable("company_application_types", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "INTERNAL" + }, + new + { + Id = 2, + Label = "EXTERNAL" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyAssignedRole", b => + { + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("CompanyRoleId") + .HasColumnType("integer") + .HasColumnName("company_role_id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.HasKey("CompanyId", "CompanyRoleId") + .HasName("pk_company_assigned_roles"); + + b.HasIndex("CompanyRoleId") + .HasDatabaseName("ix_company_assigned_roles_company_role_id"); + + b.HasIndex("LastEditorId") + .HasDatabaseName("ix_company_assigned_roles_last_editor_id"); + + b.ToTable("company_assigned_roles", "portal", t => + { + t.HasTrigger("LC_TRIGGER_AFTER_INSERT_COMPANYASSIGNEDROLE"); + + t.HasTrigger("LC_TRIGGER_AFTER_UPDATE_COMPANYASSIGNEDROLE"); + }); + + b + .HasAnnotation("LC_TRIGGER_AFTER_INSERT_COMPANYASSIGNEDROLE", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_INSERT_COMPANYASSIGNEDROLE\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_COMPANYASSIGNEDROLE$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_company_assigned_role2023316\" (\"company_id\", \"company_role_id\", \"last_editor_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"company_id\", \r\n NEW.\"company_role_id\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_COMPANYASSIGNEDROLE$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_COMPANYASSIGNEDROLE AFTER INSERT\r\nON \"portal\".\"company_assigned_roles\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_INSERT_COMPANYASSIGNEDROLE\"();") + .HasAnnotation("LC_TRIGGER_AFTER_UPDATE_COMPANYASSIGNEDROLE", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_UPDATE_COMPANYASSIGNEDROLE\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_COMPANYASSIGNEDROLE$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_company_assigned_role2023316\" (\"company_id\", \"company_role_id\", \"last_editor_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"company_id\", \r\n NEW.\"company_role_id\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_COMPANYASSIGNEDROLE$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_COMPANYASSIGNEDROLE AFTER UPDATE\r\nON \"portal\".\"company_assigned_roles\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_UPDATE_COMPANYASSIGNEDROLE\"();"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyAssignedUseCase", b => + { + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("UseCaseId") + .HasColumnType("uuid") + .HasColumnName("use_case_id"); + + b.HasKey("CompanyId", "UseCaseId") + .HasName("pk_company_assigned_use_cases"); + + b.HasIndex("UseCaseId") + .HasDatabaseName("ix_company_assigned_use_cases_use_case_id"); + + b.ToTable("company_assigned_use_cases", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyIdentifier", b => + { + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("UniqueIdentifierId") + .HasColumnType("integer") + .HasColumnName("unique_identifier_id"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text") + .HasColumnName("value"); + + b.HasKey("CompanyId", "UniqueIdentifierId") + .HasName("pk_company_identifiers"); + + b.HasIndex("UniqueIdentifierId") + .HasDatabaseName("ix_company_identifiers_unique_identifier_id"); + + b.ToTable("company_identifiers", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyIdentityProvider", b => + { + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("IdentityProviderId") + .HasColumnType("uuid") + .HasColumnName("identity_provider_id"); + + b.HasKey("CompanyId", "IdentityProviderId") + .HasName("pk_company_identity_providers"); + + b.HasIndex("IdentityProviderId") + .HasDatabaseName("ix_company_identity_providers_identity_provider_id"); + + b.ToTable("company_identity_providers", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyRole", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_company_roles"); + + b.ToTable("company_roles", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "ACTIVE_PARTICIPANT" + }, + new + { + Id = 2, + Label = "APP_PROVIDER" + }, + new + { + Id = 3, + Label = "SERVICE_PROVIDER" + }, + new + { + Id = 4, + Label = "OPERATOR" + }, + new + { + Id = 5, + Label = "ONBOARDING_SERVICE_PROVIDER" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyRoleAssignedRoleCollection", b => + { + b.Property("CompanyRoleId") + .HasColumnType("integer") + .HasColumnName("company_role_id"); + + b.Property("UserRoleCollectionId") + .HasColumnType("uuid") + .HasColumnName("user_role_collection_id"); + + b.HasKey("CompanyRoleId") + .HasName("pk_company_role_assigned_role_collections"); + + b.HasIndex("UserRoleCollectionId") + .IsUnique() + .HasDatabaseName("ix_company_role_assigned_role_collections_user_role_collection"); + + b.ToTable("company_role_assigned_role_collections", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyRoleDescription", b => + { + b.Property("CompanyRoleId") + .HasColumnType("integer") + .HasColumnName("company_role_id"); + + b.Property("LanguageShortName") + .HasMaxLength(2) + .HasColumnType("character(2)") + .HasColumnName("language_short_name"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("description"); + + b.HasKey("CompanyRoleId", "LanguageShortName") + .HasName("pk_company_role_descriptions"); + + b.HasIndex("LanguageShortName") + .HasDatabaseName("ix_company_role_descriptions_language_short_name"); + + b.ToTable("company_role_descriptions", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyRoleRegistrationData", b => + { + b.Property("CompanyRoleId") + .HasColumnType("integer") + .HasColumnName("company_role_id"); + + b.Property("IsRegistrationRole") + .HasColumnType("boolean") + .HasColumnName("is_registration_role"); + + b.HasKey("CompanyRoleId") + .HasName("pk_company_role_registration_data"); + + b.ToTable("company_role_registration_data", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyServiceAccount", b => + { + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ClientClientId") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("client_client_id"); + + b.Property("ClientId") + .HasMaxLength(36) + .HasColumnType("character varying(36)") + .HasColumnName("client_id"); + + b.Property("CompanyServiceAccountTypeId") + .HasColumnType("integer") + .HasColumnName("company_service_account_type_id"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name"); + + b.Property("OfferSubscriptionId") + .HasColumnType("uuid") + .HasColumnName("offer_subscription_id"); + + b.HasKey("Id") + .HasName("pk_company_service_accounts"); + + b.HasIndex("ClientClientId") + .IsUnique() + .HasDatabaseName("ix_company_service_accounts_client_client_id"); + + b.HasIndex("CompanyServiceAccountTypeId") + .HasDatabaseName("ix_company_service_accounts_company_service_account_type_id"); + + b.HasIndex("OfferSubscriptionId") + .HasDatabaseName("ix_company_service_accounts_offer_subscription_id"); + + b.ToTable("company_service_accounts", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyServiceAccountType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_company_service_account_types"); + + b.ToTable("company_service_account_types", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "MANAGED" + }, + new + { + Id = 2, + Label = "OWN" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanySsiDetail", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("CompanySsiDetailStatusId") + .HasColumnType("integer") + .HasColumnName("company_ssi_detail_status_id"); + + b.Property("CreatorUserId") + .HasColumnType("uuid") + .HasColumnName("creator_user_id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("DocumentId") + .HasColumnType("uuid") + .HasColumnName("document_id"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiry_date"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("VerifiedCredentialExternalTypeUseCaseDetailId") + .HasColumnType("uuid") + .HasColumnName("verified_credential_external_type_use_case_detail_id"); + + b.Property("VerifiedCredentialTypeId") + .HasColumnType("integer") + .HasColumnName("verified_credential_type_id"); + + b.HasKey("Id") + .HasName("pk_company_ssi_details"); + + b.HasIndex("CompanyId") + .HasDatabaseName("ix_company_ssi_details_company_id"); + + b.HasIndex("CompanySsiDetailStatusId") + .HasDatabaseName("ix_company_ssi_details_company_ssi_detail_status_id"); + + b.HasIndex("CreatorUserId") + .HasDatabaseName("ix_company_ssi_details_creator_user_id"); + + b.HasIndex("DocumentId") + .IsUnique() + .HasDatabaseName("ix_company_ssi_details_document_id"); + + b.HasIndex("LastEditorId") + .HasDatabaseName("ix_company_ssi_details_last_editor_id"); + + b.HasIndex("VerifiedCredentialExternalTypeUseCaseDetailId") + .HasDatabaseName("ix_company_ssi_details_verified_credential_external_type_use_c"); + + b.HasIndex("VerifiedCredentialTypeId") + .HasDatabaseName("ix_company_ssi_details_verified_credential_type_id"); + + b.ToTable("company_ssi_details", "portal", t => + { + t.HasTrigger("LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL"); + + t.HasTrigger("LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL"); + }); + + b + .HasAnnotation("LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_company_ssi_detail20230621\" (\"id\", \"company_id\", \"verified_credential_type_id\", \"company_ssi_detail_status_id\", \"document_id\", \"date_created\", \"creator_user_id\", \"expiry_date\", \"verified_credential_external_type_use_case_detail_id\", \"date_last_changed\", \"last_editor_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"company_id\", \r\n NEW.\"verified_credential_type_id\", \r\n NEW.\"company_ssi_detail_status_id\", \r\n NEW.\"document_id\", \r\n NEW.\"date_created\", \r\n NEW.\"creator_user_id\", \r\n NEW.\"expiry_date\", \r\n NEW.\"verified_credential_external_type_use_case_detail_id\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL AFTER INSERT\r\nON \"portal\".\"company_ssi_details\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL\"();") + .HasAnnotation("LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_company_ssi_detail20230621\" (\"id\", \"company_id\", \"verified_credential_type_id\", \"company_ssi_detail_status_id\", \"document_id\", \"date_created\", \"creator_user_id\", \"expiry_date\", \"verified_credential_external_type_use_case_detail_id\", \"date_last_changed\", \"last_editor_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"company_id\", \r\n NEW.\"verified_credential_type_id\", \r\n NEW.\"company_ssi_detail_status_id\", \r\n NEW.\"document_id\", \r\n NEW.\"date_created\", \r\n NEW.\"creator_user_id\", \r\n NEW.\"expiry_date\", \r\n NEW.\"verified_credential_external_type_use_case_detail_id\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL AFTER UPDATE\r\nON \"portal\".\"company_ssi_details\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL\"();"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanySsiDetailStatus", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_company_ssi_detail_statuses"); + + b.ToTable("company_ssi_detail_statuses", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "PENDING" + }, + new + { + Id = 2, + Label = "ACTIVE" + }, + new + { + Id = 3, + Label = "INACTIVE" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyStatus", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_company_statuses"); + + b.ToTable("company_statuses", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "PENDING" + }, + new + { + Id = 2, + Label = "ACTIVE" + }, + new + { + Id = 3, + Label = "REJECTED" + }, + new + { + Id = 4, + Label = "INACTIVE" + }, + new + { + Id = 5, + Label = "DELETED" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyUser", b => + { + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("Email") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("email"); + + b.Property("Firstname") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("firstname"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("Lastlogin") + .HasColumnType("bytea") + .HasColumnName("lastlogin"); + + b.Property("Lastname") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("lastname"); + + b.HasKey("Id") + .HasName("pk_company_users"); + + b.HasIndex("LastEditorId") + .HasDatabaseName("ix_company_users_last_editor_id"); + + b.ToTable("company_users", "portal", t => + { + t.HasTrigger("LC_TRIGGER_AFTER_INSERT_COMPANYUSER"); + + t.HasTrigger("LC_TRIGGER_AFTER_UPDATE_COMPANYUSER"); + }); + + b + .HasAnnotation("LC_TRIGGER_AFTER_INSERT_COMPANYUSER", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_INSERT_COMPANYUSER\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_COMPANYUSER$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_company_user20230523\" (\"id\", \"email\", \"firstname\", \"lastlogin\", \"lastname\", \"date_last_changed\", \"last_editor_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"email\", \r\n NEW.\"firstname\", \r\n NEW.\"lastlogin\", \r\n NEW.\"lastname\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_COMPANYUSER$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_COMPANYUSER AFTER INSERT\r\nON \"portal\".\"company_users\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_INSERT_COMPANYUSER\"();") + .HasAnnotation("LC_TRIGGER_AFTER_UPDATE_COMPANYUSER", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_UPDATE_COMPANYUSER\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_COMPANYUSER$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_company_user20230523\" (\"id\", \"email\", \"firstname\", \"lastlogin\", \"lastname\", \"date_last_changed\", \"last_editor_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"email\", \r\n NEW.\"firstname\", \r\n NEW.\"lastlogin\", \r\n NEW.\"lastname\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_COMPANYUSER$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_COMPANYUSER AFTER UPDATE\r\nON \"portal\".\"company_users\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_UPDATE_COMPANYUSER\"();"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyUserAssignedAppFavourite", b => + { + b.Property("CompanyUserId") + .HasColumnType("uuid") + .HasColumnName("company_user_id"); + + b.Property("AppId") + .HasColumnType("uuid") + .HasColumnName("app_id"); + + b.HasKey("CompanyUserId", "AppId") + .HasName("pk_company_user_assigned_app_favourites"); + + b.HasIndex("AppId") + .HasDatabaseName("ix_company_user_assigned_app_favourites_app_id"); + + b.ToTable("company_user_assigned_app_favourites", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyUserAssignedBusinessPartner", b => + { + b.Property("CompanyUserId") + .HasColumnType("uuid") + .HasColumnName("company_user_id"); + + b.Property("BusinessPartnerNumber") + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasColumnName("business_partner_number"); + + b.HasKey("CompanyUserId", "BusinessPartnerNumber") + .HasName("pk_company_user_assigned_business_partners"); + + b.ToTable("company_user_assigned_business_partners", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyUserAssignedIdentityProvider", b => + { + b.Property("CompanyUserId") + .HasColumnType("uuid") + .HasColumnName("company_user_id"); + + b.Property("IdentityProviderId") + .HasColumnType("uuid") + .HasColumnName("identity_provider_id"); + + b.Property("ProviderId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("provider_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("user_name"); + + b.HasKey("CompanyUserId", "IdentityProviderId") + .HasName("pk_company_user_assigned_identity_providers"); + + b.HasIndex("IdentityProviderId") + .HasDatabaseName("ix_company_user_assigned_identity_providers_identity_provider_"); + + b.ToTable("company_user_assigned_identity_providers", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Connector", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CompanyServiceAccountId") + .HasColumnType("uuid") + .HasColumnName("company_service_account_id"); + + b.Property("ConnectorUrl") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("connector_url"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("HostId") + .HasColumnType("uuid") + .HasColumnName("host_id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("LocationId") + .IsRequired() + .HasMaxLength(2) + .HasColumnType("character(2)") + .HasColumnName("location_id"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name"); + + b.Property("ProviderId") + .HasColumnType("uuid") + .HasColumnName("provider_id"); + + b.Property("SelfDescriptionDocumentId") + .HasColumnType("uuid") + .HasColumnName("self_description_document_id"); + + b.Property("SelfDescriptionMessage") + .HasColumnType("text") + .HasColumnName("self_description_message"); + + b.Property("StatusId") + .HasColumnType("integer") + .HasColumnName("status_id"); + + b.Property("TypeId") + .HasColumnType("integer") + .HasColumnName("type_id"); + + b.HasKey("Id") + .HasName("pk_connectors"); + + b.HasIndex("CompanyServiceAccountId") + .IsUnique() + .HasDatabaseName("ix_connectors_company_service_account_id"); + + b.HasIndex("HostId") + .HasDatabaseName("ix_connectors_host_id"); + + b.HasIndex("LastEditorId") + .HasDatabaseName("ix_connectors_last_editor_id"); + + b.HasIndex("LocationId") + .HasDatabaseName("ix_connectors_location_id"); + + b.HasIndex("ProviderId") + .HasDatabaseName("ix_connectors_provider_id"); + + b.HasIndex("SelfDescriptionDocumentId") + .IsUnique() + .HasDatabaseName("ix_connectors_self_description_document_id"); + + b.HasIndex("StatusId") + .HasDatabaseName("ix_connectors_status_id"); + + b.HasIndex("TypeId") + .HasDatabaseName("ix_connectors_type_id"); + + b.ToTable("connectors", "portal", t => + { + t.HasTrigger("LC_TRIGGER_AFTER_INSERT_CONNECTOR"); + + t.HasTrigger("LC_TRIGGER_AFTER_UPDATE_CONNECTOR"); + }); + + b + .HasAnnotation("LC_TRIGGER_AFTER_INSERT_CONNECTOR", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_INSERT_CONNECTOR\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_CONNECTOR$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_connector20230803\" (\"id\", \"name\", \"connector_url\", \"type_id\", \"status_id\", \"provider_id\", \"host_id\", \"self_description_document_id\", \"location_id\", \"self_description_message\", \"date_last_changed\", \"company_service_account_id\", \"last_editor_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"name\", \r\n NEW.\"connector_url\", \r\n NEW.\"type_id\", \r\n NEW.\"status_id\", \r\n NEW.\"provider_id\", \r\n NEW.\"host_id\", \r\n NEW.\"self_description_document_id\", \r\n NEW.\"location_id\", \r\n NEW.\"self_description_message\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"company_service_account_id\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_CONNECTOR$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_CONNECTOR AFTER INSERT\r\nON \"portal\".\"connectors\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_INSERT_CONNECTOR\"();") + .HasAnnotation("LC_TRIGGER_AFTER_UPDATE_CONNECTOR", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_UPDATE_CONNECTOR\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_CONNECTOR$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_connector20230803\" (\"id\", \"name\", \"connector_url\", \"type_id\", \"status_id\", \"provider_id\", \"host_id\", \"self_description_document_id\", \"location_id\", \"self_description_message\", \"date_last_changed\", \"company_service_account_id\", \"last_editor_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"name\", \r\n NEW.\"connector_url\", \r\n NEW.\"type_id\", \r\n NEW.\"status_id\", \r\n NEW.\"provider_id\", \r\n NEW.\"host_id\", \r\n NEW.\"self_description_document_id\", \r\n NEW.\"location_id\", \r\n NEW.\"self_description_message\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"company_service_account_id\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_CONNECTOR$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_CONNECTOR AFTER UPDATE\r\nON \"portal\".\"connectors\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_UPDATE_CONNECTOR\"();"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ConnectorAssignedOfferSubscription", b => + { + b.Property("ConnectorId") + .HasColumnType("uuid") + .HasColumnName("connector_id"); + + b.Property("OfferSubscriptionId") + .HasColumnType("uuid") + .HasColumnName("offer_subscription_id"); + + b.HasKey("ConnectorId", "OfferSubscriptionId") + .HasName("pk_connector_assigned_offer_subscriptions"); + + b.HasIndex("OfferSubscriptionId") + .HasDatabaseName("ix_connector_assigned_offer_subscriptions_offer_subscription_id"); + + b.ToTable("connector_assigned_offer_subscriptions", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ConnectorStatus", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_connector_statuses"); + + b.ToTable("connector_statuses", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "PENDING" + }, + new + { + Id = 2, + Label = "ACTIVE" + }, + new + { + Id = 3, + Label = "INACTIVE" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ConnectorType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_connector_types"); + + b.ToTable("connector_types", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "COMPANY_CONNECTOR" + }, + new + { + Id = 2, + Label = "CONNECTOR_AS_A_SERVICE" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Consent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AgreementId") + .HasColumnType("uuid") + .HasColumnName("agreement_id"); + + b.Property("Comment") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("comment"); + + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("CompanyUserId") + .HasColumnType("uuid") + .HasColumnName("company_user_id"); + + b.Property("ConsentStatusId") + .HasColumnType("integer") + .HasColumnName("consent_status_id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DocumentId") + .HasColumnType("uuid") + .HasColumnName("document_id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("Target") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("target"); + + b.HasKey("Id") + .HasName("pk_consents"); + + b.HasIndex("AgreementId") + .HasDatabaseName("ix_consents_agreement_id"); + + b.HasIndex("CompanyId") + .HasDatabaseName("ix_consents_company_id"); + + b.HasIndex("CompanyUserId") + .HasDatabaseName("ix_consents_company_user_id"); + + b.HasIndex("ConsentStatusId") + .HasDatabaseName("ix_consents_consent_status_id"); + + b.HasIndex("DocumentId") + .HasDatabaseName("ix_consents_document_id"); + + b.HasIndex("LastEditorId") + .HasDatabaseName("ix_consents_last_editor_id"); + + b.ToTable("consents", "portal", t => + { + t.HasTrigger("LC_TRIGGER_AFTER_INSERT_CONSENT"); + + t.HasTrigger("LC_TRIGGER_AFTER_UPDATE_CONSENT"); + }); + + b + .HasAnnotation("LC_TRIGGER_AFTER_INSERT_CONSENT", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_INSERT_CONSENT\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_CONSENT$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_consent20230412\" (\"id\", \"date_created\", \"comment\", \"consent_status_id\", \"target\", \"agreement_id\", \"company_id\", \"document_id\", \"company_user_id\", \"last_editor_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"date_created\", \r\n NEW.\"comment\", \r\n NEW.\"consent_status_id\", \r\n NEW.\"target\", \r\n NEW.\"agreement_id\", \r\n NEW.\"company_id\", \r\n NEW.\"document_id\", \r\n NEW.\"company_user_id\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_CONSENT$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_CONSENT AFTER INSERT\r\nON \"portal\".\"consents\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_INSERT_CONSENT\"();") + .HasAnnotation("LC_TRIGGER_AFTER_UPDATE_CONSENT", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_UPDATE_CONSENT\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_CONSENT$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_consent20230412\" (\"id\", \"date_created\", \"comment\", \"consent_status_id\", \"target\", \"agreement_id\", \"company_id\", \"document_id\", \"company_user_id\", \"last_editor_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"date_created\", \r\n NEW.\"comment\", \r\n NEW.\"consent_status_id\", \r\n NEW.\"target\", \r\n NEW.\"agreement_id\", \r\n NEW.\"company_id\", \r\n NEW.\"document_id\", \r\n NEW.\"company_user_id\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_CONSENT$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_CONSENT AFTER UPDATE\r\nON \"portal\".\"consents\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_UPDATE_CONSENT\"();"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ConsentAssignedOffer", b => + { + b.Property("ConsentId") + .HasColumnType("uuid") + .HasColumnName("consent_id"); + + b.Property("OfferId") + .HasColumnType("uuid") + .HasColumnName("offer_id"); + + b.HasKey("ConsentId", "OfferId") + .HasName("pk_consent_assigned_offers"); + + b.HasIndex("OfferId") + .HasDatabaseName("ix_consent_assigned_offers_offer_id"); + + b.ToTable("consent_assigned_offers", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ConsentAssignedOfferSubscription", b => + { + b.Property("ConsentId") + .HasColumnType("uuid") + .HasColumnName("consent_id"); + + b.Property("OfferSubscriptionId") + .HasColumnType("uuid") + .HasColumnName("offer_subscription_id"); + + b.HasKey("ConsentId", "OfferSubscriptionId") + .HasName("pk_consent_assigned_offer_subscriptions"); + + b.HasIndex("OfferSubscriptionId") + .HasDatabaseName("ix_consent_assigned_offer_subscriptions_offer_subscription_id"); + + b.ToTable("consent_assigned_offer_subscriptions", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ConsentStatus", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_consent_statuses"); + + b.ToTable("consent_statuses", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "ACTIVE" + }, + new + { + Id = 2, + Label = "INACTIVE" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Country", b => + { + b.Property("Alpha2Code") + .HasMaxLength(2) + .HasColumnType("character(2)") + .HasColumnName("alpha2code") + .IsFixedLength() + .HasAnnotation("Relational:JsonPropertyName", "alpha2code"); + + b.Property("Alpha3Code") + .HasMaxLength(3) + .HasColumnType("character(3)") + .HasColumnName("alpha3code") + .IsFixedLength() + .HasAnnotation("Relational:JsonPropertyName", "alpha3code"); + + b.Property("CountryNameDe") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("country_name_de"); + + b.Property("CountryNameEn") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("country_name_en"); + + b.HasKey("Alpha2Code") + .HasName("pk_countries"); + + b.ToTable("countries", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CountryAssignedIdentifier", b => + { + b.Property("CountryAlpha2Code") + .HasMaxLength(2) + .HasColumnType("character(2)") + .HasColumnName("country_alpha2code") + .HasAnnotation("Relational:JsonPropertyName", "country_alpha2code"); + + b.Property("UniqueIdentifierId") + .HasColumnType("integer") + .HasColumnName("unique_identifier_id"); + + b.Property("BpdmIdentifierId") + .HasColumnType("integer") + .HasColumnName("bpdm_identifier_id"); + + b.HasKey("CountryAlpha2Code", "UniqueIdentifierId") + .HasName("pk_country_assigned_identifiers"); + + b.HasIndex("BpdmIdentifierId") + .HasDatabaseName("ix_country_assigned_identifiers_bpdm_identifier_id"); + + b.HasIndex("UniqueIdentifierId") + .HasDatabaseName("ix_country_assigned_identifiers_unique_identifier_id"); + + b.ToTable("country_assigned_identifiers", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Document", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CompanyUserId") + .HasColumnType("uuid") + .HasColumnName("company_user_id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DocumentContent") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("document_content"); + + b.Property("DocumentHash") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("document_hash"); + + b.Property("DocumentName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("document_name"); + + b.Property("DocumentStatusId") + .HasColumnType("integer") + .HasColumnName("document_status_id"); + + b.Property("DocumentTypeId") + .HasColumnType("integer") + .HasColumnName("document_type_id"); + + b.Property("MediaTypeId") + .HasColumnType("integer") + .HasColumnName("media_type_id"); + + b.HasKey("Id") + .HasName("pk_documents"); + + b.HasIndex("CompanyUserId") + .HasDatabaseName("ix_documents_company_user_id"); + + b.HasIndex("DocumentStatusId") + .HasDatabaseName("ix_documents_document_status_id"); + + b.HasIndex("DocumentTypeId") + .HasDatabaseName("ix_documents_document_type_id"); + + b.HasIndex("MediaTypeId") + .HasDatabaseName("ix_documents_media_type_id"); + + b.ToTable("documents", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.DocumentStatus", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_document_status"); + + b.ToTable("document_status", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "PENDING" + }, + new + { + Id = 2, + Label = "LOCKED" + }, + new + { + Id = 3, + Label = "INACTIVE" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.DocumentType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_document_types"); + + b.ToTable("document_types", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "CX_FRAME_CONTRACT" + }, + new + { + Id = 2, + Label = "COMMERCIAL_REGISTER_EXTRACT" + }, + new + { + Id = 3, + Label = "APP_CONTRACT" + }, + new + { + Id = 4, + Label = "CONFORMITY_APPROVAL_REGISTRATION" + }, + new + { + Id = 5, + Label = "ADDITIONAL_DETAILS" + }, + new + { + Id = 6, + Label = "APP_LEADIMAGE" + }, + new + { + Id = 7, + Label = "APP_IMAGE" + }, + new + { + Id = 8, + Label = "SELF_DESCRIPTION" + }, + new + { + Id = 9, + Label = "APP_TECHNICAL_INFORMATION" + }, + new + { + Id = 10, + Label = "CONFORMITY_APPROVAL_CONNECTOR" + }, + new + { + Id = 11, + Label = "CONFORMITY_APPROVAL_BUSINESS_APPS" + }, + new + { + Id = 12, + Label = "CONFORMITY_APPROVAL_SERVICES" + }, + new + { + Id = 13, + Label = "SERVICE_LEADIMAGE" + }, + new + { + Id = 14, + Label = "PRESENTATION" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IamClient", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ClientClientId") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("client_client_id"); + + b.HasKey("Id") + .HasName("pk_iam_clients"); + + b.HasIndex("ClientClientId") + .IsUnique() + .HasDatabaseName("ix_iam_clients_client_client_id"); + + b.ToTable("iam_clients", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IamIdentityProvider", b => + { + b.Property("IamIdpAlias") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("iam_idp_alias"); + + b.Property("IdentityProviderId") + .HasColumnType("uuid") + .HasColumnName("identity_provider_id"); + + b.HasKey("IamIdpAlias") + .HasName("pk_iam_identity_providers"); + + b.HasIndex("IdentityProviderId") + .IsUnique() + .HasDatabaseName("ix_iam_identity_providers_identity_provider_id"); + + b.ToTable("iam_identity_providers", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Identity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("IdentityTypeId") + .HasColumnType("integer") + .HasColumnName("identity_type_id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("UserEntityId") + .HasMaxLength(36) + .HasColumnType("character varying(36)") + .HasColumnName("user_entity_id"); + + b.Property("UserStatusId") + .HasColumnType("integer") + .HasColumnName("user_status_id") + .HasAnnotation("Relational:JsonPropertyName", "user_status_id"); + + b.HasKey("Id") + .HasName("pk_identities"); + + b.HasIndex("CompanyId") + .HasDatabaseName("ix_identities_company_id"); + + b.HasIndex("IdentityTypeId") + .HasDatabaseName("ix_identities_identity_type_id"); + + b.HasIndex("LastEditorId") + .HasDatabaseName("ix_identities_last_editor_id"); + + b.HasIndex("UserEntityId") + .IsUnique() + .HasDatabaseName("ix_identities_user_entity_id"); + + b.HasIndex("UserStatusId") + .HasDatabaseName("ix_identities_user_status_id"); + + b.ToTable("identities", "portal", t => + { + t.HasTrigger("LC_TRIGGER_AFTER_INSERT_IDENTITY"); + + t.HasTrigger("LC_TRIGGER_AFTER_UPDATE_IDENTITY"); + }); + + b + .HasAnnotation("LC_TRIGGER_AFTER_INSERT_IDENTITY", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_INSERT_IDENTITY\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_IDENTITY$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_identity20230526\" (\"id\", \"date_created\", \"company_id\", \"user_status_id\", \"user_entity_id\", \"identity_type_id\", \"date_last_changed\", \"last_editor_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"date_created\", \r\n NEW.\"company_id\", \r\n NEW.\"user_status_id\", \r\n NEW.\"user_entity_id\", \r\n NEW.\"identity_type_id\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_IDENTITY$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_IDENTITY AFTER INSERT\r\nON \"portal\".\"identities\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_INSERT_IDENTITY\"();") + .HasAnnotation("LC_TRIGGER_AFTER_UPDATE_IDENTITY", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_UPDATE_IDENTITY\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_IDENTITY$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_identity20230526\" (\"id\", \"date_created\", \"company_id\", \"user_status_id\", \"user_entity_id\", \"identity_type_id\", \"date_last_changed\", \"last_editor_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"date_created\", \r\n NEW.\"company_id\", \r\n NEW.\"user_status_id\", \r\n NEW.\"user_entity_id\", \r\n NEW.\"identity_type_id\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_IDENTITY$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_IDENTITY AFTER UPDATE\r\nON \"portal\".\"identities\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_UPDATE_IDENTITY\"();"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IdentityAssignedRole", b => + { + b.Property("IdentityId") + .HasColumnType("uuid") + .HasColumnName("identity_id"); + + b.Property("UserRoleId") + .HasColumnType("uuid") + .HasColumnName("user_role_id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.HasKey("IdentityId", "UserRoleId") + .HasName("pk_identity_assigned_roles"); + + b.HasIndex("LastEditorId") + .HasDatabaseName("ix_identity_assigned_roles_last_editor_id"); + + b.HasIndex("UserRoleId") + .HasDatabaseName("ix_identity_assigned_roles_user_role_id"); + + b.ToTable("identity_assigned_roles", "portal", t => + { + t.HasTrigger("LC_TRIGGER_AFTER_INSERT_IDENTITYASSIGNEDROLE"); + + t.HasTrigger("LC_TRIGGER_AFTER_UPDATE_IDENTITYASSIGNEDROLE"); + }); + + b + .HasAnnotation("LC_TRIGGER_AFTER_INSERT_IDENTITYASSIGNEDROLE", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_INSERT_IDENTITYASSIGNEDROLE\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_IDENTITYASSIGNEDROLE$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_identity_assigned_role20230522\" (\"identity_id\", \"user_role_id\", \"last_editor_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"identity_id\", \r\n NEW.\"user_role_id\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_IDENTITYASSIGNEDROLE$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_IDENTITYASSIGNEDROLE AFTER INSERT\r\nON \"portal\".\"identity_assigned_roles\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_INSERT_IDENTITYASSIGNEDROLE\"();") + .HasAnnotation("LC_TRIGGER_AFTER_UPDATE_IDENTITYASSIGNEDROLE", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_UPDATE_IDENTITYASSIGNEDROLE\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_IDENTITYASSIGNEDROLE$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_identity_assigned_role20230522\" (\"identity_id\", \"user_role_id\", \"last_editor_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"identity_id\", \r\n NEW.\"user_role_id\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_IDENTITYASSIGNEDROLE$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_IDENTITYASSIGNEDROLE AFTER UPDATE\r\nON \"portal\".\"identity_assigned_roles\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_UPDATE_IDENTITYASSIGNEDROLE\"();"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IdentityProvider", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("IdentityProviderCategoryId") + .HasColumnType("integer") + .HasColumnName("identity_provider_category_id"); + + b.Property("IdentityProviderTypeId") + .HasColumnType("integer") + .HasColumnName("identity_provider_type_id"); + + b.Property("OwnerId") + .HasColumnType("uuid") + .HasColumnName("owner_id"); + + b.HasKey("Id") + .HasName("pk_identity_providers"); + + b.HasIndex("IdentityProviderCategoryId") + .HasDatabaseName("ix_identity_providers_identity_provider_category_id"); + + b.HasIndex("IdentityProviderTypeId") + .HasDatabaseName("ix_identity_providers_identity_provider_type_id"); + + b.HasIndex("OwnerId") + .HasDatabaseName("ix_identity_providers_owner_id"); + + b.ToTable("identity_providers", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IdentityProviderCategory", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_identity_provider_categories"); + + b.ToTable("identity_provider_categories", "portal"); + + b.HasData( + new + { + Id = 2, + Label = "KEYCLOAK_OIDC" + }, + new + { + Id = 3, + Label = "KEYCLOAK_SAML" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IdentityProviderType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_identity_provider_types"); + + b.ToTable("identity_provider_types", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "OWN" + }, + new + { + Id = 2, + Label = "MANAGED" + }, + new + { + Id = 3, + Label = "SHARED" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IdentityType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_identity_type"); + + b.ToTable("identity_type", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "COMPANY_USER" + }, + new + { + Id = 2, + Label = "COMPANY_SERVICE_ACCOUNT" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IdentityUserStatus", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_identity_user_statuses"); + + b.ToTable("identity_user_statuses", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "ACTIVE" + }, + new + { + Id = 2, + Label = "INACTIVE" + }, + new + { + Id = 3, + Label = "DELETED" + }, + new + { + Id = 4, + Label = "PENDING" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Invitation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CompanyApplicationId") + .HasColumnType("uuid") + .HasColumnName("company_application_id"); + + b.Property("CompanyUserId") + .HasColumnType("uuid") + .HasColumnName("company_user_id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("InvitationStatusId") + .HasColumnType("integer") + .HasColumnName("invitation_status_id"); + + b.HasKey("Id") + .HasName("pk_invitations"); + + b.HasIndex("CompanyApplicationId") + .HasDatabaseName("ix_invitations_company_application_id"); + + b.HasIndex("CompanyUserId") + .HasDatabaseName("ix_invitations_company_user_id"); + + b.HasIndex("InvitationStatusId") + .HasDatabaseName("ix_invitations_invitation_status_id"); + + b.ToTable("invitations", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.InvitationStatus", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_invitation_statuses"); + + b.ToTable("invitation_statuses", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "CREATED" + }, + new + { + Id = 2, + Label = "PENDING" + }, + new + { + Id = 3, + Label = "ACCEPTED" + }, + new + { + Id = 4, + Label = "DECLINED" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Language", b => + { + b.Property("ShortName") + .HasMaxLength(2) + .HasColumnType("character(2)") + .HasColumnName("short_name") + .IsFixedLength(); + + b.HasKey("ShortName") + .HasName("pk_languages"); + + b.ToTable("languages", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.LanguageLongName", b => + { + b.Property("ShortName") + .HasMaxLength(2) + .HasColumnType("character(2)") + .HasColumnName("short_name") + .IsFixedLength(); + + b.Property("LanguageShortName") + .HasMaxLength(2) + .HasColumnType("character(2)") + .HasColumnName("language_short_name") + .IsFixedLength(); + + b.Property("LongName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("long_name"); + + b.HasKey("ShortName", "LanguageShortName") + .HasName("pk_language_long_names"); + + b.HasIndex("LanguageShortName") + .HasDatabaseName("ix_language_long_names_language_short_name"); + + b.ToTable("language_long_names", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.LicenseType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_license_types"); + + b.ToTable("license_types", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "COTS" + }, + new + { + Id = 2, + Label = "FOSS" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.MediaType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_media_types"); + + b.ToTable("media_types", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "JPEG" + }, + new + { + Id = 2, + Label = "GIF" + }, + new + { + Id = 3, + Label = "PNG" + }, + new + { + Id = 4, + Label = "SVG" + }, + new + { + Id = 5, + Label = "TIFF" + }, + new + { + Id = 6, + Label = "PDF" + }, + new + { + Id = 7, + Label = "JSON" + }, + new + { + Id = 8, + Label = "PEM" + }, + new + { + Id = 9, + Label = "CA_CERT" + }, + new + { + Id = 10, + Label = "PKX_CER" + }, + new + { + Id = 11, + Label = "OCTET" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.NetworkRegistration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ApplicationId") + .HasColumnType("uuid") + .HasColumnName("application_id"); + + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("ExternalId") + .HasColumnType("uuid") + .HasColumnName("external_id"); + + b.Property("OnboardingServiceProviderId") + .HasColumnType("uuid") + .HasColumnName("onboarding_service_provider_id"); + + b.Property("ProcessId") + .HasColumnType("uuid") + .HasColumnName("process_id"); + + b.HasKey("Id") + .HasName("pk_network_registrations"); + + b.HasIndex("ApplicationId") + .IsUnique() + .HasDatabaseName("ix_network_registrations_application_id"); + + b.HasIndex("CompanyId") + .IsUnique() + .HasDatabaseName("ix_network_registrations_company_id"); + + b.HasIndex("OnboardingServiceProviderId") + .HasDatabaseName("ix_network_registrations_onboarding_service_provider_id"); + + b.HasIndex("ProcessId") + .IsUnique() + .HasDatabaseName("ix_network_registrations_process_id"); + + b.HasIndex("ExternalId", "OnboardingServiceProviderId") + .IsUnique() + .HasDatabaseName("ix_network_registrations_external_id_onboarding_service_provid"); + + b.ToTable("network_registrations", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Notification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Content") + .HasColumnType("text") + .HasColumnName("content"); + + b.Property("CreatorUserId") + .HasColumnType("uuid") + .HasColumnName("creator_user_id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("Done") + .HasColumnType("boolean") + .HasColumnName("done"); + + b.Property("DueDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("due_date"); + + b.Property("IsRead") + .HasColumnType("boolean") + .HasColumnName("is_read"); + + b.Property("NotificationTypeId") + .HasColumnType("integer") + .HasColumnName("notification_type_id"); + + b.Property("ReceiverUserId") + .HasColumnType("uuid") + .HasColumnName("receiver_user_id"); + + b.HasKey("Id") + .HasName("pk_notifications"); + + b.HasIndex("CreatorUserId") + .HasDatabaseName("ix_notifications_creator_user_id"); + + b.HasIndex("NotificationTypeId") + .HasDatabaseName("ix_notifications_notification_type_id"); + + b.HasIndex("ReceiverUserId") + .HasDatabaseName("ix_notifications_receiver_user_id"); + + b.ToTable("notifications", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.NotificationTopic", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_notification_topic"); + + b.ToTable("notification_topic", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "INFO" + }, + new + { + Id = 2, + Label = "ACTION" + }, + new + { + Id = 3, + Label = "OFFER" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.NotificationType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_notification_type"); + + b.ToTable("notification_type", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "INFO" + }, + new + { + Id = 2, + Label = "ACTION" + }, + new + { + Id = 3, + Label = "WELCOME" + }, + new + { + Id = 4, + Label = "WELCOME_USE_CASES" + }, + new + { + Id = 5, + Label = "WELCOME_SERVICE_PROVIDER" + }, + new + { + Id = 6, + Label = "WELCOME_CONNECTOR_REGISTRATION" + }, + new + { + Id = 7, + Label = "WELCOME_APP_MARKETPLACE" + }, + new + { + Id = 8, + Label = "APP_SUBSCRIPTION_REQUEST" + }, + new + { + Id = 9, + Label = "APP_SUBSCRIPTION_ACTIVATION" + }, + new + { + Id = 10, + Label = "CONNECTOR_REGISTERED" + }, + new + { + Id = 11, + Label = "APP_RELEASE_REQUEST" + }, + new + { + Id = 12, + Label = "TECHNICAL_USER_CREATION" + }, + new + { + Id = 13, + Label = "SERVICE_REQUEST" + }, + new + { + Id = 14, + Label = "SERVICE_ACTIVATION" + }, + new + { + Id = 15, + Label = "APP_ROLE_ADDED" + }, + new + { + Id = 16, + Label = "APP_RELEASE_APPROVAL" + }, + new + { + Id = 17, + Label = "SERVICE_RELEASE_REQUEST" + }, + new + { + Id = 18, + Label = "SERVICE_RELEASE_APPROVAL" + }, + new + { + Id = 19, + Label = "APP_RELEASE_REJECTION" + }, + new + { + Id = 20, + Label = "SERVICE_RELEASE_REJECTION" + }, + new + { + Id = 21, + Label = "ROLE_UPDATE_CORE_OFFER" + }, + new + { + Id = 22, + Label = "ROLE_UPDATE_APP_OFFER" + }, + new + { + Id = 23, + Label = "SUBSCRIPTION_URL_UPDATE" + }, + new + { + Id = 24, + Label = "CREDENTIAL_APPROVAL" + }, + new + { + Id = 25, + Label = "CREDENTIAL_REJECTED" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.NotificationTypeAssignedTopic", b => + { + b.Property("NotificationTypeId") + .HasColumnType("integer") + .HasColumnName("notification_type_id"); + + b.Property("NotificationTopicId") + .HasColumnType("integer") + .HasColumnName("notification_topic_id"); + + b.HasKey("NotificationTypeId", "NotificationTopicId") + .HasName("pk_notification_type_assigned_topics"); + + b.HasIndex("NotificationTopicId") + .HasDatabaseName("ix_notification_type_assigned_topics_notification_topic_id"); + + b.HasIndex("NotificationTypeId") + .IsUnique() + .HasDatabaseName("ix_notification_type_assigned_topics_notification_type_id"); + + b.ToTable("notification_type_assigned_topics", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Offer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ContactEmail") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("contact_email"); + + b.Property("ContactNumber") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("contact_number"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("DateReleased") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_released"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("LicenseTypeId") + .HasColumnType("integer") + .HasColumnName("license_type_id"); + + b.Property("MarketingUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("marketing_url"); + + b.Property("Name") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name"); + + b.Property("OfferStatusId") + .HasColumnType("integer") + .HasColumnName("offer_status_id"); + + b.Property("OfferTypeId") + .HasColumnType("integer") + .HasColumnName("offer_type_id"); + + b.Property("Provider") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("provider"); + + b.Property("ProviderCompanyId") + .HasColumnType("uuid") + .HasColumnName("provider_company_id"); + + b.Property("SalesManagerId") + .HasColumnType("uuid") + .HasColumnName("sales_manager_id"); + + b.HasKey("Id") + .HasName("pk_offers"); + + b.HasIndex("LastEditorId") + .HasDatabaseName("ix_offers_last_editor_id"); + + b.HasIndex("LicenseTypeId") + .HasDatabaseName("ix_offers_license_type_id"); + + b.HasIndex("OfferStatusId") + .HasDatabaseName("ix_offers_offer_status_id"); + + b.HasIndex("OfferTypeId") + .HasDatabaseName("ix_offers_offer_type_id"); + + b.HasIndex("ProviderCompanyId") + .HasDatabaseName("ix_offers_provider_company_id"); + + b.HasIndex("SalesManagerId") + .HasDatabaseName("ix_offers_sales_manager_id"); + + b.ToTable("offers", "portal", t => + { + t.HasTrigger("LC_TRIGGER_AFTER_INSERT_OFFER"); + + t.HasTrigger("LC_TRIGGER_AFTER_UPDATE_OFFER"); + }); + + b + .HasAnnotation("LC_TRIGGER_AFTER_INSERT_OFFER", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_INSERT_OFFER\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_OFFER$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_offer20230406\" (\"id\", \"name\", \"date_created\", \"date_released\", \"marketing_url\", \"contact_email\", \"contact_number\", \"provider\", \"offer_type_id\", \"sales_manager_id\", \"provider_company_id\", \"offer_status_id\", \"license_type_id\", \"date_last_changed\", \"last_editor_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"name\", \r\n NEW.\"date_created\", \r\n NEW.\"date_released\", \r\n NEW.\"marketing_url\", \r\n NEW.\"contact_email\", \r\n NEW.\"contact_number\", \r\n NEW.\"provider\", \r\n NEW.\"offer_type_id\", \r\n NEW.\"sales_manager_id\", \r\n NEW.\"provider_company_id\", \r\n NEW.\"offer_status_id\", \r\n NEW.\"license_type_id\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_OFFER$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_OFFER AFTER INSERT\r\nON \"portal\".\"offers\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_INSERT_OFFER\"();") + .HasAnnotation("LC_TRIGGER_AFTER_UPDATE_OFFER", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_UPDATE_OFFER\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_OFFER$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_offer20230406\" (\"id\", \"name\", \"date_created\", \"date_released\", \"marketing_url\", \"contact_email\", \"contact_number\", \"provider\", \"offer_type_id\", \"sales_manager_id\", \"provider_company_id\", \"offer_status_id\", \"license_type_id\", \"date_last_changed\", \"last_editor_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"name\", \r\n NEW.\"date_created\", \r\n NEW.\"date_released\", \r\n NEW.\"marketing_url\", \r\n NEW.\"contact_email\", \r\n NEW.\"contact_number\", \r\n NEW.\"provider\", \r\n NEW.\"offer_type_id\", \r\n NEW.\"sales_manager_id\", \r\n NEW.\"provider_company_id\", \r\n NEW.\"offer_status_id\", \r\n NEW.\"license_type_id\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_OFFER$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_OFFER AFTER UPDATE\r\nON \"portal\".\"offers\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_UPDATE_OFFER\"();"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferAssignedDocument", b => + { + b.Property("OfferId") + .HasColumnType("uuid") + .HasColumnName("offer_id"); + + b.Property("DocumentId") + .HasColumnType("uuid") + .HasColumnName("document_id"); + + b.HasKey("OfferId", "DocumentId") + .HasName("pk_offer_assigned_documents"); + + b.HasIndex("DocumentId") + .HasDatabaseName("ix_offer_assigned_documents_document_id"); + + b.ToTable("offer_assigned_documents", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferAssignedLicense", b => + { + b.Property("OfferId") + .HasColumnType("uuid") + .HasColumnName("offer_id"); + + b.Property("OfferLicenseId") + .HasColumnType("uuid") + .HasColumnName("offer_license_id"); + + b.HasKey("OfferId", "OfferLicenseId") + .HasName("pk_offer_assigned_licenses"); + + b.HasIndex("OfferLicenseId") + .HasDatabaseName("ix_offer_assigned_licenses_offer_license_id"); + + b.ToTable("offer_assigned_licenses", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferAssignedPrivacyPolicy", b => + { + b.Property("OfferId") + .HasColumnType("uuid") + .HasColumnName("offer_id"); + + b.Property("PrivacyPolicyId") + .HasColumnType("integer") + .HasColumnName("privacy_policy_id"); + + b.HasKey("OfferId", "PrivacyPolicyId") + .HasName("pk_offer_assigned_privacy_policies"); + + b.HasIndex("PrivacyPolicyId") + .HasDatabaseName("ix_offer_assigned_privacy_policies_privacy_policy_id"); + + b.ToTable("offer_assigned_privacy_policies", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferDescription", b => + { + b.Property("OfferId") + .HasColumnType("uuid") + .HasColumnName("offer_id"); + + b.Property("LanguageShortName") + .HasMaxLength(2) + .HasColumnType("character(2)") + .HasColumnName("language_short_name"); + + b.Property("DescriptionLong") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("description_long"); + + b.Property("DescriptionShort") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("description_short"); + + b.HasKey("OfferId", "LanguageShortName") + .HasName("pk_offer_descriptions"); + + b.HasIndex("LanguageShortName") + .HasDatabaseName("ix_offer_descriptions_language_short_name"); + + b.ToTable("offer_descriptions", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferLicense", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Licensetext") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("licensetext"); + + b.HasKey("Id") + .HasName("pk_offer_licenses"); + + b.ToTable("offer_licenses", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferStatus", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_offer_statuses"); + + b.ToTable("offer_statuses", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "CREATED" + }, + new + { + Id = 2, + Label = "IN_REVIEW" + }, + new + { + Id = 3, + Label = "ACTIVE" + }, + new + { + Id = 4, + Label = "INACTIVE" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("Description") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("description"); + + b.Property("DisplayName") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("display_name"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("OfferId") + .HasColumnType("uuid") + .HasColumnName("offer_id"); + + b.Property("OfferSubscriptionStatusId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(1) + .HasColumnName("offer_subscription_status_id"); + + b.Property("ProcessId") + .HasColumnType("uuid") + .HasColumnName("process_id"); + + b.Property("RequesterId") + .HasColumnType("uuid") + .HasColumnName("requester_id"); + + b.HasKey("Id") + .HasName("pk_offer_subscriptions"); + + b.HasIndex("CompanyId") + .HasDatabaseName("ix_offer_subscriptions_company_id"); + + b.HasIndex("LastEditorId") + .HasDatabaseName("ix_offer_subscriptions_last_editor_id"); + + b.HasIndex("OfferId") + .HasDatabaseName("ix_offer_subscriptions_offer_id"); + + b.HasIndex("OfferSubscriptionStatusId") + .HasDatabaseName("ix_offer_subscriptions_offer_subscription_status_id"); + + b.HasIndex("ProcessId") + .IsUnique() + .HasDatabaseName("ix_offer_subscriptions_process_id"); + + b.HasIndex("RequesterId") + .HasDatabaseName("ix_offer_subscriptions_requester_id"); + + b.ToTable("offer_subscriptions", "portal", t => + { + t.HasTrigger("LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION"); + + t.HasTrigger("LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION"); + }); + + b + .HasAnnotation("LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_offer_subscription20231013\" (\"id\", \"company_id\", \"offer_id\", \"offer_subscription_status_id\", \"display_name\", \"description\", \"requester_id\", \"last_editor_id\", \"process_id\", \"date_created\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"company_id\", \r\n NEW.\"offer_id\", \r\n NEW.\"offer_subscription_status_id\", \r\n NEW.\"display_name\", \r\n NEW.\"description\", \r\n NEW.\"requester_id\", \r\n NEW.\"last_editor_id\", \r\n NEW.\"process_id\", \r\n NEW.\"date_created\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION AFTER INSERT\r\nON \"portal\".\"offer_subscriptions\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION\"();") + .HasAnnotation("LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_offer_subscription20231013\" (\"id\", \"company_id\", \"offer_id\", \"offer_subscription_status_id\", \"display_name\", \"description\", \"requester_id\", \"last_editor_id\", \"process_id\", \"date_created\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"company_id\", \r\n NEW.\"offer_id\", \r\n NEW.\"offer_subscription_status_id\", \r\n NEW.\"display_name\", \r\n NEW.\"description\", \r\n NEW.\"requester_id\", \r\n NEW.\"last_editor_id\", \r\n NEW.\"process_id\", \r\n NEW.\"date_created\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION AFTER UPDATE\r\nON \"portal\".\"offer_subscriptions\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION\"();"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferSubscriptionProcessData", b => + { + b.Property("OfferSubscriptionId") + .HasColumnType("uuid") + .HasColumnName("offer_subscription_id"); + + b.Property("OfferUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("offer_url"); + + b.HasKey("OfferSubscriptionId") + .HasName("pk_offer_subscriptions_process_datas"); + + b.ToTable("offer_subscriptions_process_datas", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferSubscriptionStatus", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_offer_subscription_statuses"); + + b.ToTable("offer_subscription_statuses", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "PENDING" + }, + new + { + Id = 2, + Label = "ACTIVE" + }, + new + { + Id = 3, + Label = "INACTIVE" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferTag", b => + { + b.Property("OfferId") + .HasColumnType("uuid") + .HasColumnName("offer_id"); + + b.Property("Name") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("tag_name") + .HasAnnotation("Relational:JsonPropertyName", "tag_name"); + + b.HasKey("OfferId", "Name") + .HasName("pk_offer_tags"); + + b.ToTable("offer_tags", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_offer_types"); + + b.ToTable("offer_types", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "APP" + }, + new + { + Id = 2, + Label = "CORE_COMPONENT" + }, + new + { + Id = 3, + Label = "SERVICE" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OnboardingServiceProviderDetail", b => + { + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("AuthUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("auth_url"); + + b.Property("CallbackUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("callback_url"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("client_id"); + + b.Property("ClientSecret") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("client_secret"); + + b.HasKey("CompanyId") + .HasName("pk_onboarding_service_provider_details"); + + b.ToTable("onboarding_service_provider_details", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.PrivacyPolicy", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_privacy_policies"); + + b.ToTable("privacy_policies", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "COMPANY_DATA" + }, + new + { + Id = 2, + Label = "USER_DATA" + }, + new + { + Id = 3, + Label = "LOCATION" + }, + new + { + Id = 4, + Label = "BROWSER_HISTORY" + }, + new + { + Id = 5, + Label = "NONE" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Process", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("LockExpiryDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("lock_expiry_date"); + + b.Property("ProcessTypeId") + .HasColumnType("integer") + .HasColumnName("process_type_id"); + + b.Property("Version") + .IsConcurrencyToken() + .HasColumnType("uuid") + .HasColumnName("version"); + + b.HasKey("Id") + .HasName("pk_processes"); + + b.HasIndex("ProcessTypeId") + .HasDatabaseName("ix_processes_process_type_id"); + + b.ToTable("processes", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ProcessStep", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("Message") + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("ProcessId") + .HasColumnType("uuid") + .HasColumnName("process_id"); + + b.Property("ProcessStepStatusId") + .HasColumnType("integer") + .HasColumnName("process_step_status_id"); + + b.Property("ProcessStepTypeId") + .HasColumnType("integer") + .HasColumnName("process_step_type_id"); + + b.HasKey("Id") + .HasName("pk_process_steps"); + + b.HasIndex("ProcessId") + .HasDatabaseName("ix_process_steps_process_id"); + + b.HasIndex("ProcessStepStatusId") + .HasDatabaseName("ix_process_steps_process_step_status_id"); + + b.HasIndex("ProcessStepTypeId") + .HasDatabaseName("ix_process_steps_process_step_type_id"); + + b.ToTable("process_steps", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ProcessStepStatus", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_process_step_statuses"); + + b.ToTable("process_step_statuses", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "TODO" + }, + new + { + Id = 2, + Label = "DONE" + }, + new + { + Id = 3, + Label = "SKIPPED" + }, + new + { + Id = 4, + Label = "FAILED" + }, + new + { + Id = 5, + Label = "DUPLICATE" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ProcessStepType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_process_step_types"); + + b.ToTable("process_step_types", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "VERIFY_REGISTRATION" + }, + new + { + Id = 2, + Label = "CREATE_BUSINESS_PARTNER_NUMBER_PUSH" + }, + new + { + Id = 3, + Label = "CREATE_BUSINESS_PARTNER_NUMBER_PULL" + }, + new + { + Id = 4, + Label = "CREATE_BUSINESS_PARTNER_NUMBER_MANUAL" + }, + new + { + Id = 5, + Label = "CREATE_IDENTITY_WALLET" + }, + new + { + Id = 6, + Label = "RETRIGGER_IDENTITY_WALLET" + }, + new + { + Id = 7, + Label = "START_CLEARING_HOUSE" + }, + new + { + Id = 8, + Label = "RETRIGGER_CLEARING_HOUSE" + }, + new + { + Id = 9, + Label = "END_CLEARING_HOUSE" + }, + new + { + Id = 10, + Label = "START_SELF_DESCRIPTION_LP" + }, + new + { + Id = 11, + Label = "RETRIGGER_SELF_DESCRIPTION_LP" + }, + new + { + Id = 12, + Label = "ACTIVATE_APPLICATION" + }, + new + { + Id = 13, + Label = "RETRIGGER_BUSINESS_PARTNER_NUMBER_PUSH" + }, + new + { + Id = 14, + Label = "RETRIGGER_BUSINESS_PARTNER_NUMBER_PULL" + }, + new + { + Id = 15, + Label = "OVERRIDE_BUSINESS_PARTNER_NUMBER" + }, + new + { + Id = 16, + Label = "TRIGGER_OVERRIDE_CLEARING_HOUSE" + }, + new + { + Id = 17, + Label = "START_OVERRIDE_CLEARING_HOUSE" + }, + new + { + Id = 18, + Label = "FINISH_SELF_DESCRIPTION_LP" + }, + new + { + Id = 19, + Label = "DECLINE_APPLICATION" + }, + new + { + Id = 100, + Label = "TRIGGER_PROVIDER" + }, + new + { + Id = 101, + Label = "START_AUTOSETUP" + }, + new + { + Id = 102, + Label = "OFFERSUBSCRIPTION_CLIENT_CREATION" + }, + new + { + Id = 103, + Label = "SINGLE_INSTANCE_SUBSCRIPTION_DETAILS_CREATION" + }, + new + { + Id = 104, + Label = "OFFERSUBSCRIPTION_TECHNICALUSER_CREATION" + }, + new + { + Id = 105, + Label = "ACTIVATE_SUBSCRIPTION" + }, + new + { + Id = 106, + Label = "TRIGGER_PROVIDER_CALLBACK" + }, + new + { + Id = 107, + Label = "RETRIGGER_PROVIDER" + }, + new + { + Id = 108, + Label = "RETRIGGER_OFFERSUBSCRIPTION_CLIENT_CREATION" + }, + new + { + Id = 109, + Label = "RETRIGGER_OFFERSUBSCRIPTION_TECHNICALUSER_CREATION" + }, + new + { + Id = 110, + Label = "RETRIGGER_PROVIDER_CALLBACK" + }, + new + { + Id = 111, + Label = "TRIGGER_ACTIVATE_SUBSCRIPTION" + }, + new + { + Id = 200, + Label = "SYNCHRONIZE_USER" + }, + new + { + Id = 201, + Label = "RETRIGGER_SYNCHRONIZE_USER" + }, + new + { + Id = 202, + Label = "TRIGGER_CALLBACK_OSP_SUBMITTED" + }, + new + { + Id = 203, + Label = "TRIGGER_CALLBACK_OSP_APPROVED" + }, + new + { + Id = 204, + Label = "TRIGGER_CALLBACK_OSP_DECLINED" + }, + new + { + Id = 205, + Label = "RETRIGGER_CALLBACK_OSP_SUBMITTED" + }, + new + { + Id = 206, + Label = "RETRIGGER_CALLBACK_OSP_APPROVED" + }, + new + { + Id = 207, + Label = "RETRIGGER_CALLBACK_OSP_DECLINED" + }, + new + { + Id = 300, + Label = "SYNCHRONIZE_SERVICE_ACCOUNTS" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ProcessType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_process_types"); + + b.ToTable("process_types", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "APPLICATION_CHECKLIST" + }, + new + { + Id = 3, + Label = "OFFER_SUBSCRIPTION" + }, + new + { + Id = 4, + Label = "PARTNER_REGISTRATION" + }, + new + { + Id = 5, + Label = "SERVICE_ACCOUNT_SYNC" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ProviderCompanyDetail", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AutoSetupCallbackUrl") + .HasColumnType("text") + .HasColumnName("auto_setup_callback_url"); + + b.Property("AutoSetupUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("auto_setup_url"); + + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.HasKey("Id") + .HasName("pk_provider_company_details"); + + b.HasIndex("CompanyId") + .IsUnique() + .HasDatabaseName("ix_provider_company_details_company_id"); + + b.HasIndex("LastEditorId") + .HasDatabaseName("ix_provider_company_details_last_editor_id"); + + b.ToTable("provider_company_details", "portal", t => + { + t.HasTrigger("LC_TRIGGER_AFTER_INSERT_PROVIDERCOMPANYDETAIL"); + + t.HasTrigger("LC_TRIGGER_AFTER_UPDATE_PROVIDERCOMPANYDETAIL"); + }); + + b + .HasAnnotation("LC_TRIGGER_AFTER_INSERT_PROVIDERCOMPANYDETAIL", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_INSERT_PROVIDERCOMPANYDETAIL\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_PROVIDERCOMPANYDETAIL$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_provider_company_detail20230614\" (\"id\", \"date_created\", \"auto_setup_url\", \"auto_setup_callback_url\", \"company_id\", \"date_last_changed\", \"last_editor_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"date_created\", \r\n NEW.\"auto_setup_url\", \r\n NEW.\"auto_setup_callback_url\", \r\n NEW.\"company_id\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_PROVIDERCOMPANYDETAIL$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_PROVIDERCOMPANYDETAIL AFTER INSERT\r\nON \"portal\".\"provider_company_details\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_INSERT_PROVIDERCOMPANYDETAIL\"();") + .HasAnnotation("LC_TRIGGER_AFTER_UPDATE_PROVIDERCOMPANYDETAIL", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_UPDATE_PROVIDERCOMPANYDETAIL\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_PROVIDERCOMPANYDETAIL$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_provider_company_detail20230614\" (\"id\", \"date_created\", \"auto_setup_url\", \"auto_setup_callback_url\", \"company_id\", \"date_last_changed\", \"last_editor_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"date_created\", \r\n NEW.\"auto_setup_url\", \r\n NEW.\"auto_setup_callback_url\", \r\n NEW.\"company_id\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_PROVIDERCOMPANYDETAIL$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_PROVIDERCOMPANYDETAIL AFTER UPDATE\r\nON \"portal\".\"provider_company_details\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_UPDATE_PROVIDERCOMPANYDETAIL\"();"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ServiceDetail", b => + { + b.Property("ServiceId") + .HasColumnType("uuid") + .HasColumnName("service_id"); + + b.Property("ServiceTypeId") + .HasColumnType("integer") + .HasColumnName("service_type_id"); + + b.HasKey("ServiceId", "ServiceTypeId") + .HasName("pk_service_details"); + + b.HasIndex("ServiceTypeId") + .HasDatabaseName("ix_service_details_service_type_id"); + + b.ToTable("service_details", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ServiceType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_service_types"); + + b.ToTable("service_types", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "DATASPACE_SERVICE" + }, + new + { + Id = 2, + Label = "CONSULTANCY_SERVICE" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.TechnicalUserProfile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("OfferId") + .HasColumnType("uuid") + .HasColumnName("offer_id"); + + b.HasKey("Id") + .HasName("pk_technical_user_profiles"); + + b.HasIndex("OfferId") + .HasDatabaseName("ix_technical_user_profiles_offer_id"); + + b.ToTable("technical_user_profiles", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.TechnicalUserProfileAssignedUserRole", b => + { + b.Property("TechnicalUserProfileId") + .HasColumnType("uuid") + .HasColumnName("technical_user_profile_id"); + + b.Property("UserRoleId") + .HasColumnType("uuid") + .HasColumnName("user_role_id"); + + b.HasKey("TechnicalUserProfileId", "UserRoleId") + .HasName("pk_technical_user_profile_assigned_user_roles"); + + b.HasIndex("UserRoleId") + .HasDatabaseName("ix_technical_user_profile_assigned_user_roles_user_role_id"); + + b.ToTable("technical_user_profile_assigned_user_roles", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UniqueIdentifier", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_unique_identifiers"); + + b.ToTable("unique_identifiers", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "COMMERCIAL_REG_NUMBER" + }, + new + { + Id = 2, + Label = "VAT_ID" + }, + new + { + Id = 3, + Label = "LEI_CODE" + }, + new + { + Id = 4, + Label = "VIES" + }, + new + { + Id = 5, + Label = "EORI" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UseCase", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name"); + + b.Property("Shortname") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("shortname"); + + b.HasKey("Id") + .HasName("pk_use_cases"); + + b.ToTable("use_cases", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UseCaseDescription", b => + { + b.Property("UseCaseId") + .HasColumnType("uuid") + .HasColumnName("use_case_id"); + + b.Property("LanguageShortName") + .HasMaxLength(2) + .HasColumnType("character(2)") + .HasColumnName("language_short_name"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.HasKey("UseCaseId", "LanguageShortName") + .HasName("pk_use_case_descriptions"); + + b.HasIndex("LanguageShortName") + .HasDatabaseName("ix_use_case_descriptions_language_short_name"); + + b.ToTable("use_case_descriptions", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UserRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("OfferId") + .HasColumnType("uuid") + .HasColumnName("offer_id"); + + b.Property("UserRoleText") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("user_role") + .HasAnnotation("Relational:JsonPropertyName", "user_role"); + + b.HasKey("Id") + .HasName("pk_user_roles"); + + b.HasIndex("LastEditorId") + .HasDatabaseName("ix_user_roles_last_editor_id"); + + b.HasIndex("OfferId") + .HasDatabaseName("ix_user_roles_offer_id"); + + b.ToTable("user_roles", "portal", t => + { + t.HasTrigger("LC_TRIGGER_AFTER_INSERT_USERROLE"); + + t.HasTrigger("LC_TRIGGER_AFTER_UPDATE_USERROLE"); + }); + + b + .HasAnnotation("LC_TRIGGER_AFTER_INSERT_USERROLE", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_INSERT_USERROLE\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_USERROLE$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_user_role20221017\" (\"id\", \"user_role\", \"offer_id\", \"last_editor_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"user_role\", \r\n NEW.\"offer_id\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_USERROLE$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_USERROLE AFTER INSERT\r\nON \"portal\".\"user_roles\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_INSERT_USERROLE\"();") + .HasAnnotation("LC_TRIGGER_AFTER_UPDATE_USERROLE", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_UPDATE_USERROLE\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_USERROLE$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_user_role20221017\" (\"id\", \"user_role\", \"offer_id\", \"last_editor_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"user_role\", \r\n NEW.\"offer_id\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_USERROLE$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_USERROLE AFTER UPDATE\r\nON \"portal\".\"user_roles\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_UPDATE_USERROLE\"();"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UserRoleAssignedCollection", b => + { + b.Property("UserRoleId") + .HasColumnType("uuid") + .HasColumnName("user_role_id"); + + b.Property("UserRoleCollectionId") + .HasColumnType("uuid") + .HasColumnName("user_role_collection_id"); + + b.HasKey("UserRoleId", "UserRoleCollectionId") + .HasName("pk_user_role_assigned_collections"); + + b.HasIndex("UserRoleCollectionId") + .HasDatabaseName("ix_user_role_assigned_collections_user_role_collection_id"); + + b.ToTable("user_role_assigned_collections", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UserRoleCollection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("pk_user_role_collections"); + + b.ToTable("user_role_collections", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UserRoleCollectionDescription", b => + { + b.Property("UserRoleCollectionId") + .HasColumnType("uuid") + .HasColumnName("user_role_collection_id"); + + b.Property("LanguageShortName") + .HasMaxLength(2) + .HasColumnType("character(2)") + .HasColumnName("language_short_name"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("description"); + + b.HasKey("UserRoleCollectionId", "LanguageShortName") + .HasName("pk_user_role_collection_descriptions"); + + b.HasIndex("LanguageShortName") + .HasDatabaseName("ix_user_role_collection_descriptions_language_short_name"); + + b.ToTable("user_role_collection_descriptions", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UserRoleDescription", b => + { + b.Property("UserRoleId") + .HasColumnType("uuid") + .HasColumnName("user_role_id"); + + b.Property("LanguageShortName") + .HasMaxLength(2) + .HasColumnType("character(2)") + .HasColumnName("language_short_name"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("description"); + + b.HasKey("UserRoleId", "LanguageShortName") + .HasName("pk_user_role_descriptions"); + + b.HasIndex("LanguageShortName") + .HasDatabaseName("ix_user_role_descriptions_language_short_name"); + + b.ToTable("user_role_descriptions", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialExternalType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_verified_credential_external_types"); + + b.ToTable("verified_credential_external_types", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "TRACEABILITY_CREDENTIAL" + }, + new + { + Id = 2, + Label = "PCF_CREDENTIAL" + }, + new + { + Id = 3, + Label = "BEHAVIOR_TWIN_CREDENTIAL" + }, + new + { + Id = 4, + Label = "VEHICLE_DISMANTLE" + }, + new + { + Id = 5, + Label = "SUSTAINABILITY_CREDENTIAL" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialExternalTypeUseCaseDetailVersion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Expiry") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiry"); + + b.Property("Template") + .IsRequired() + .HasColumnType("text") + .HasColumnName("template"); + + b.Property("ValidFrom") + .HasColumnType("timestamp with time zone") + .HasColumnName("valid_from"); + + b.Property("VerifiedCredentialExternalTypeId") + .HasColumnType("integer") + .HasColumnName("verified_credential_external_type_id"); + + b.Property("Version") + .IsRequired() + .HasColumnType("text") + .HasColumnName("version"); + + b.HasKey("Id") + .HasName("pk_verified_credential_external_type_use_case_detail_versions"); + + b.HasIndex("VerifiedCredentialExternalTypeId", "Version") + .IsUnique() + .HasDatabaseName("ix_verified_credential_external_type_use_case_detail_versions_"); + + b.ToTable("verified_credential_external_type_use_case_detail_versions", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_verified_credential_types"); + + b.ToTable("verified_credential_types", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "TRACEABILITY_FRAMEWORK" + }, + new + { + Id = 2, + Label = "PCF_FRAMEWORK" + }, + new + { + Id = 3, + Label = "BEHAVIOR_TWIN_FRAMEWORK" + }, + new + { + Id = 4, + Label = "DISMANTLER_CERTIFICATE" + }, + new + { + Id = 5, + Label = "SUSTAINABILITY_FRAMEWORK" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialTypeAssignedExternalType", b => + { + b.Property("VerifiedCredentialTypeId") + .HasColumnType("integer") + .HasColumnName("verified_credential_type_id"); + + b.Property("VerifiedCredentialExternalTypeId") + .HasColumnType("integer") + .HasColumnName("verified_credential_external_type_id"); + + b.HasKey("VerifiedCredentialTypeId", "VerifiedCredentialExternalTypeId") + .HasName("pk_verified_credential_type_assigned_external_types"); + + b.HasIndex("VerifiedCredentialExternalTypeId") + .HasDatabaseName("ix_verified_credential_type_assigned_external_types_verified_c"); + + b.HasIndex("VerifiedCredentialTypeId") + .IsUnique() + .HasDatabaseName("ix_verified_credential_type_assigned_external_types_verified_c1"); + + b.ToTable("verified_credential_type_assigned_external_types", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialTypeAssignedKind", b => + { + b.Property("VerifiedCredentialTypeId") + .HasColumnType("integer") + .HasColumnName("verified_credential_type_id"); + + b.Property("VerifiedCredentialTypeKindId") + .HasColumnType("integer") + .HasColumnName("verified_credential_type_kind_id"); + + b.HasKey("VerifiedCredentialTypeId", "VerifiedCredentialTypeKindId") + .HasName("pk_verified_credential_type_assigned_kinds"); + + b.HasIndex("VerifiedCredentialTypeId") + .HasDatabaseName("ix_verified_credential_type_assigned_kinds_verified_credential"); + + b.HasIndex("VerifiedCredentialTypeKindId") + .HasDatabaseName("ix_verified_credential_type_assigned_kinds_verified_credential1"); + + b.ToTable("verified_credential_type_assigned_kinds", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialTypeAssignedUseCase", b => + { + b.Property("VerifiedCredentialTypeId") + .HasColumnType("integer") + .HasColumnName("verified_credential_type_id"); + + b.Property("UseCaseId") + .HasColumnType("uuid") + .HasColumnName("use_case_id"); + + b.HasKey("VerifiedCredentialTypeId", "UseCaseId") + .HasName("pk_verified_credential_type_assigned_use_cases"); + + b.HasIndex("UseCaseId") + .IsUnique() + .HasDatabaseName("ix_verified_credential_type_assigned_use_cases_use_case_id"); + + b.HasIndex("VerifiedCredentialTypeId") + .IsUnique() + .HasDatabaseName("ix_verified_credential_type_assigned_use_cases_verified_creden"); + + b.ToTable("verified_credential_type_assigned_use_cases", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialTypeKind", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_verified_credential_type_kinds"); + + b.ToTable("verified_credential_type_kinds", "portal"); + + b.HasData( + new + { + Id = 1, + Label = "USE_CASE" + }, + new + { + Id = 2, + Label = "CERTIFICATE" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Views.CompaniesLinkedServiceAccount", b => + { + b.Property("ServiceAccountId") + .HasColumnType("uuid") + .HasColumnName("service_account_id"); + + b.Property("Owners") + .HasColumnType("uuid") + .HasColumnName("owners"); + + b.Property("Provider") + .HasColumnType("uuid") + .HasColumnName("provider"); + + b.HasKey("ServiceAccountId"); + + b.ToTable((string)null); + + b.ToView("company_linked_service_accounts", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Views.OfferSubscriptionView", b => + { + b.Property("AppInstance") + .HasColumnType("uuid") + .HasColumnName("app_instance"); + + b.Property("Connector") + .HasColumnType("uuid") + .HasColumnName("connector"); + + b.Property("OfferTypeId") + .HasColumnType("integer") + .HasColumnName("offer_type_id"); + + b.Property("SubscriptionId") + .HasColumnType("uuid") + .HasColumnName("subscription_id"); + + b.Property("TechnicalUser") + .HasColumnType("uuid") + .HasColumnName("technical_user"); + + b.ToTable((string)null); + + b.ToView("offer_subscription_view", "portal"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Address", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Country", "Country") + .WithMany("Addresses") + .HasForeignKey("CountryAlpha2Code") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_addresses_countries_country_temp_id"); + + b.Navigation("Country"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Agreement", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AgreementCategory", "AgreementCategory") + .WithMany("Agreements") + .HasForeignKey("AgreementCategoryId") + .IsRequired() + .HasConstraintName("fk_agreements_agreement_categories_agreement_category_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Document", "Document") + .WithMany("Agreements") + .HasForeignKey("DocumentId") + .HasConstraintName("fk_agreements_documents_document_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Company", "IssuerCompany") + .WithMany("Agreements") + .HasForeignKey("IssuerCompanyId") + .IsRequired() + .HasConstraintName("fk_agreements_companies_issuer_company_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UseCase", "UseCase") + .WithMany("Agreements") + .HasForeignKey("UseCaseId") + .HasConstraintName("fk_agreements_use_cases_use_case_id"); + + b.Navigation("AgreementCategory"); + + b.Navigation("Document"); + + b.Navigation("IssuerCompany"); + + b.Navigation("UseCase"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AgreementAssignedCompanyRole", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Agreement", "Agreement") + .WithMany("AgreementAssignedCompanyRoles") + .HasForeignKey("AgreementId") + .IsRequired() + .HasConstraintName("fk_agreement_assigned_company_roles_agreements_agreement_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyRole", "CompanyRole") + .WithMany("AgreementAssignedCompanyRoles") + .HasForeignKey("CompanyRoleId") + .IsRequired() + .HasConstraintName("fk_agreement_assigned_company_roles_company_roles_company_role"); + + b.Navigation("Agreement"); + + b.Navigation("CompanyRole"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AgreementAssignedOffer", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Agreement", "Agreement") + .WithMany("AgreementAssignedOffers") + .HasForeignKey("AgreementId") + .IsRequired() + .HasConstraintName("fk_agreement_assigned_offers_agreements_agreement_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Offer", "Offer") + .WithMany("AgreementAssignedOffers") + .HasForeignKey("OfferId") + .IsRequired() + .HasConstraintName("fk_agreement_assigned_offers_offers_offer_id"); + + b.Navigation("Agreement"); + + b.Navigation("Offer"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AgreementAssignedOfferType", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Agreement", "Agreement") + .WithMany("AgreementAssignedOfferTypes") + .HasForeignKey("AgreementId") + .IsRequired() + .HasConstraintName("fk_agreement_assigned_offer_types_agreements_agreement_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferType", "OfferType") + .WithMany("AgreementAssignedOfferTypes") + .HasForeignKey("OfferTypeId") + .IsRequired() + .HasConstraintName("fk_agreement_assigned_offer_types_offer_types_offer_type_id"); + + b.Navigation("Agreement"); + + b.Navigation("OfferType"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AppAssignedUseCase", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Offer", "App") + .WithMany() + .HasForeignKey("AppId") + .IsRequired() + .HasConstraintName("fk_app_assigned_use_cases_offers_app_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UseCase", "UseCase") + .WithMany() + .HasForeignKey("UseCaseId") + .IsRequired() + .HasConstraintName("fk_app_assigned_use_cases_use_cases_use_case_id"); + + b.Navigation("App"); + + b.Navigation("UseCase"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AppInstance", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Offer", "App") + .WithMany("AppInstances") + .HasForeignKey("AppId") + .OnDelete(DeleteBehavior.SetNull) + .IsRequired() + .HasConstraintName("fk_app_instances_offers_app_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IamClient", "IamClient") + .WithMany("AppInstances") + .HasForeignKey("IamClientId") + .OnDelete(DeleteBehavior.SetNull) + .IsRequired() + .HasConstraintName("fk_app_instances_iam_clients_iam_client_id"); + + b.Navigation("App"); + + b.Navigation("IamClient"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AppInstanceAssignedCompanyServiceAccount", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AppInstance", "AppInstance") + .WithMany("ServiceAccounts") + .HasForeignKey("AppInstanceId") + .IsRequired() + .HasConstraintName("fk_app_instance_assigned_service_accounts_app_instances_app_in"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyServiceAccount", "CompanyServiceAccount") + .WithMany("AppInstances") + .HasForeignKey("CompanyServiceAccountId") + .IsRequired() + .HasConstraintName("fk_app_instance_assigned_service_accounts_company_service_acco"); + + b.Navigation("AppInstance"); + + b.Navigation("CompanyServiceAccount"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AppInstanceSetup", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Offer", "App") + .WithOne("AppInstanceSetup") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AppInstanceSetup", "AppId") + .IsRequired() + .HasConstraintName("fk_app_instance_setups_offers_app_id"); + + b.Navigation("App"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AppLanguage", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Offer", "App") + .WithMany() + .HasForeignKey("AppId") + .IsRequired() + .HasConstraintName("fk_app_languages_offers_app_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Language", "Language") + .WithMany() + .HasForeignKey("LanguageShortName") + .IsRequired() + .HasConstraintName("fk_app_languages_languages_language_temp_id"); + + b.Navigation("App"); + + b.Navigation("Language"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AppSubscriptionDetail", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AppInstance", "AppInstance") + .WithMany("AppSubscriptionDetails") + .HasForeignKey("AppInstanceId") + .HasConstraintName("fk_app_subscription_details_app_instances_app_instance_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Identity", "LastEditor") + .WithMany() + .HasForeignKey("LastEditorId") + .HasConstraintName("fk_app_subscription_details_identities_last_editor_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferSubscription", "OfferSubscription") + .WithOne("AppSubscriptionDetail") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AppSubscriptionDetail", "OfferSubscriptionId") + .IsRequired() + .HasConstraintName("fk_app_subscription_details_offer_subscriptions_offer_subscrip"); + + b.Navigation("AppInstance"); + + b.Navigation("LastEditor"); + + b.Navigation("OfferSubscription"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ApplicationChecklistEntry", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ApplicationChecklistEntryStatus", "ApplicationChecklistEntryStatus") + .WithMany("ApplicationChecklistEntries") + .HasForeignKey("ApplicationChecklistEntryStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_application_checklist_application_checklist_statuses_applic"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ApplicationChecklistEntryType", "ApplicationChecklistEntryType") + .WithMany("ApplicationChecklistEntries") + .HasForeignKey("ApplicationChecklistEntryTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_application_checklist_application_checklist_types_applicati"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyApplication", "Application") + .WithMany("ApplicationChecklistEntries") + .HasForeignKey("ApplicationId") + .IsRequired() + .HasConstraintName("fk_application_checklist_company_applications_application_id"); + + b.Navigation("Application"); + + b.Navigation("ApplicationChecklistEntryStatus"); + + b.Navigation("ApplicationChecklistEntryType"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Company", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Address", "Address") + .WithMany("Companies") + .HasForeignKey("AddressId") + .HasConstraintName("fk_companies_addresses_address_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyStatus", "CompanyStatus") + .WithMany("Companies") + .HasForeignKey("CompanyStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_companies_company_statuses_company_status_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Document", "SelfDescriptionDocument") + .WithMany("Companies") + .HasForeignKey("SelfDescriptionDocumentId") + .HasConstraintName("fk_companies_documents_self_description_document_id"); + + b.Navigation("Address"); + + b.Navigation("CompanyStatus"); + + b.Navigation("SelfDescriptionDocument"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyApplication", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyApplicationStatus", "ApplicationStatus") + .WithMany("CompanyApplications") + .HasForeignKey("ApplicationStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_company_applications_company_application_statuses_applicati"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Process", "ChecklistProcess") + .WithOne("CompanyApplication") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyApplication", "ChecklistProcessId") + .HasConstraintName("fk_company_applications_processes_checklist_process_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyApplicationType", "CompanyApplicationType") + .WithMany("CompanyApplications") + .HasForeignKey("CompanyApplicationTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_company_applications_company_application_types_company_appl"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Company", "Company") + .WithMany("CompanyApplications") + .HasForeignKey("CompanyId") + .IsRequired() + .HasConstraintName("fk_company_applications_companies_company_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Identity", "LastEditor") + .WithMany() + .HasForeignKey("LastEditorId") + .HasConstraintName("fk_company_applications_identities_last_editor_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Company", "OnboardingServiceProvider") + .WithMany("ProvidedApplications") + .HasForeignKey("OnboardingServiceProviderId") + .HasConstraintName("fk_company_applications_companies_onboarding_service_provider_"); + + b.Navigation("ApplicationStatus"); + + b.Navigation("ChecklistProcess"); + + b.Navigation("Company"); + + b.Navigation("CompanyApplicationType"); + + b.Navigation("LastEditor"); + + b.Navigation("OnboardingServiceProvider"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyAssignedRole", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Company", "Company") + .WithMany("CompanyAssignedRoles") + .HasForeignKey("CompanyId") + .IsRequired() + .HasConstraintName("fk_company_assigned_roles_companies_company_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyRole", "CompanyRole") + .WithMany("CompanyAssignedRoles") + .HasForeignKey("CompanyRoleId") + .IsRequired() + .HasConstraintName("fk_company_assigned_roles_company_roles_company_role_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Identity", "LastEditor") + .WithMany() + .HasForeignKey("LastEditorId") + .HasConstraintName("fk_company_assigned_roles_identities_last_editor_id"); + + b.Navigation("Company"); + + b.Navigation("CompanyRole"); + + b.Navigation("LastEditor"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyAssignedUseCase", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Company", "Company") + .WithMany("CompanyAssignedUseCase") + .HasForeignKey("CompanyId") + .IsRequired() + .HasConstraintName("fk_company_assigned_use_cases_companies_company_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UseCase", "UseCase") + .WithMany("CompanyAssignedUseCase") + .HasForeignKey("UseCaseId") + .IsRequired() + .HasConstraintName("fk_company_assigned_use_cases_use_cases_use_case_id"); + + b.Navigation("Company"); + + b.Navigation("UseCase"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyIdentifier", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Company", "Company") + .WithMany("CompanyIdentifiers") + .HasForeignKey("CompanyId") + .IsRequired() + .HasConstraintName("fk_company_identifiers_companies_company_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UniqueIdentifier", "UniqueIdentifier") + .WithMany("CompanyIdentifiers") + .HasForeignKey("UniqueIdentifierId") + .IsRequired() + .HasConstraintName("fk_company_identifiers_unique_identifiers_unique_identifier_id"); + + b.Navigation("Company"); + + b.Navigation("UniqueIdentifier"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyIdentityProvider", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Company", "Company") + .WithMany() + .HasForeignKey("CompanyId") + .IsRequired() + .HasConstraintName("fk_company_identity_providers_companies_company_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IdentityProvider", "IdentityProvider") + .WithMany("CompanyIdentityProviders") + .HasForeignKey("IdentityProviderId") + .IsRequired() + .HasConstraintName("fk_company_identity_providers_identity_providers_identity_prov"); + + b.Navigation("Company"); + + b.Navigation("IdentityProvider"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyRoleAssignedRoleCollection", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyRole", "CompanyRole") + .WithOne("CompanyRoleAssignedRoleCollection") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyRoleAssignedRoleCollection", "CompanyRoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_company_role_assigned_role_collections_company_roles_compan"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UserRoleCollection", "UserRoleCollection") + .WithOne("CompanyRoleAssignedRoleCollection") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyRoleAssignedRoleCollection", "UserRoleCollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_company_role_assigned_role_collections_user_role_collection"); + + b.Navigation("CompanyRole"); + + b.Navigation("UserRoleCollection"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyRoleDescription", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyRole", "CompanyRole") + .WithMany("CompanyRoleDescriptions") + .HasForeignKey("CompanyRoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_company_role_descriptions_company_roles_company_role_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Language", "Language") + .WithMany("CompanyRoleDescriptions") + .HasForeignKey("LanguageShortName") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_company_role_descriptions_languages_language_temp_id1"); + + b.Navigation("CompanyRole"); + + b.Navigation("Language"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyRoleRegistrationData", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyRole", "CompanyRole") + .WithOne("CompanyRoleRegistrationData") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyRoleRegistrationData", "CompanyRoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_company_role_registration_data_company_roles_company_role_id"); + + b.Navigation("CompanyRole"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyServiceAccount", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyServiceAccountType", "CompanyServiceAccountType") + .WithMany("CompanyServiceAccounts") + .HasForeignKey("CompanyServiceAccountTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_company_service_accounts_company_service_account_types_comp"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Identity", "Identity") + .WithOne("CompanyServiceAccount") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyServiceAccount", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_company_service_accounts_identities_identity_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferSubscription", "OfferSubscription") + .WithMany("CompanyServiceAccounts") + .HasForeignKey("OfferSubscriptionId") + .HasConstraintName("fk_company_service_accounts_offer_subscriptions_offer_subscrip"); + + b.Navigation("CompanyServiceAccountType"); + + b.Navigation("Identity"); + + b.Navigation("OfferSubscription"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanySsiDetail", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Company", "Company") + .WithMany("CompanySsiDetails") + .HasForeignKey("CompanyId") + .IsRequired() + .HasConstraintName("fk_company_ssi_details_companies_company_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanySsiDetailStatus", "CompanySsiDetailStatus") + .WithMany("CompanySsiDetails") + .HasForeignKey("CompanySsiDetailStatusId") + .IsRequired() + .HasConstraintName("fk_company_ssi_details_company_ssi_detail_statuses_company_ssi"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyUser", "CreatorUser") + .WithMany("CompanySsiDetails") + .HasForeignKey("CreatorUserId") + .IsRequired() + .HasConstraintName("fk_company_ssi_details_company_users_creator_user_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Document", "Document") + .WithOne("CompanySsiDetail") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanySsiDetail", "DocumentId") + .IsRequired() + .HasConstraintName("fk_company_ssi_details_documents_document_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Identity", "LastEditor") + .WithMany() + .HasForeignKey("LastEditorId") + .HasConstraintName("fk_company_ssi_details_identities_last_editor_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialExternalTypeUseCaseDetailVersion", "VerifiedCredentialExternalTypeUseCaseDetailVersion") + .WithMany("CompanySsiDetails") + .HasForeignKey("VerifiedCredentialExternalTypeUseCaseDetailId") + .HasConstraintName("fk_company_ssi_details_verified_credential_external_type_use_c"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialType", "VerifiedCredentialType") + .WithMany("CompanySsiDetails") + .HasForeignKey("VerifiedCredentialTypeId") + .IsRequired() + .HasConstraintName("fk_company_ssi_details_verified_credential_types_verified_cred"); + + b.Navigation("Company"); + + b.Navigation("CompanySsiDetailStatus"); + + b.Navigation("CreatorUser"); + + b.Navigation("Document"); + + b.Navigation("LastEditor"); + + b.Navigation("VerifiedCredentialExternalTypeUseCaseDetailVersion"); + + b.Navigation("VerifiedCredentialType"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyUser", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Identity", "Identity") + .WithOne("CompanyUser") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyUser", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_company_users_identities_identity_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Identity", "LastEditor") + .WithMany() + .HasForeignKey("LastEditorId") + .HasConstraintName("fk_company_users_identities_last_editor_id"); + + b.Navigation("Identity"); + + b.Navigation("LastEditor"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyUserAssignedAppFavourite", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Offer", "App") + .WithMany() + .HasForeignKey("AppId") + .IsRequired() + .HasConstraintName("fk_company_user_assigned_app_favourites_offers_app_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyUser", "CompanyUser") + .WithMany() + .HasForeignKey("CompanyUserId") + .IsRequired() + .HasConstraintName("fk_company_user_assigned_app_favourites_company_users_company_"); + + b.Navigation("App"); + + b.Navigation("CompanyUser"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyUserAssignedBusinessPartner", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyUser", "CompanyUser") + .WithMany("CompanyUserAssignedBusinessPartners") + .HasForeignKey("CompanyUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_company_user_assigned_business_partners_company_users_compa"); + + b.Navigation("CompanyUser"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyUserAssignedIdentityProvider", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyUser", "CompanyUser") + .WithMany("CompanyUserAssignedIdentityProviders") + .HasForeignKey("CompanyUserId") + .IsRequired() + .HasConstraintName("fk_company_user_assigned_identity_providers_company_users_comp"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IdentityProvider", "IdentityProvider") + .WithMany("CompanyUserAssignedIdentityProviders") + .HasForeignKey("IdentityProviderId") + .IsRequired() + .HasConstraintName("fk_company_user_assigned_identity_providers_identity_providers"); + + b.Navigation("CompanyUser"); + + b.Navigation("IdentityProvider"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Connector", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyServiceAccount", "CompanyServiceAccount") + .WithOne("Connector") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Connector", "CompanyServiceAccountId") + .HasConstraintName("fk_connectors_company_service_accounts_company_service_account"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Company", "Host") + .WithMany("HostedConnectors") + .HasForeignKey("HostId") + .HasConstraintName("fk_connectors_companies_host_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Identity", "LastEditor") + .WithMany() + .HasForeignKey("LastEditorId") + .HasConstraintName("fk_connectors_identities_last_editor_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Country", "Location") + .WithMany("Connectors") + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_connectors_countries_location_temp_id1"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Company", "Provider") + .WithMany("ProvidedConnectors") + .HasForeignKey("ProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_connectors_companies_provider_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Document", "SelfDescriptionDocument") + .WithOne("Connector") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Connector", "SelfDescriptionDocumentId") + .HasConstraintName("fk_connectors_documents_self_description_document_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ConnectorStatus", "Status") + .WithMany("Connectors") + .HasForeignKey("StatusId") + .IsRequired() + .HasConstraintName("fk_connectors_connector_statuses_status_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ConnectorType", "Type") + .WithMany("Connectors") + .HasForeignKey("TypeId") + .IsRequired() + .HasConstraintName("fk_connectors_connector_types_type_id"); + + b.Navigation("CompanyServiceAccount"); + + b.Navigation("Host"); + + b.Navigation("LastEditor"); + + b.Navigation("Location"); + + b.Navigation("Provider"); + + b.Navigation("SelfDescriptionDocument"); + + b.Navigation("Status"); + + b.Navigation("Type"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ConnectorAssignedOfferSubscription", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Connector", "Connector") + .WithMany("ConnectorAssignedOfferSubscriptions") + .HasForeignKey("ConnectorId") + .IsRequired() + .HasConstraintName("fk_connector_assigned_offer_subscriptions_connectors_connector"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferSubscription", "OfferSubscription") + .WithMany("ConnectorAssignedOfferSubscriptions") + .HasForeignKey("OfferSubscriptionId") + .IsRequired() + .HasConstraintName("fk_connector_assigned_offer_subscriptions_offer_subscriptions_"); + + b.Navigation("Connector"); + + b.Navigation("OfferSubscription"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Consent", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Agreement", "Agreement") + .WithMany("Consents") + .HasForeignKey("AgreementId") + .IsRequired() + .HasConstraintName("fk_consents_agreements_agreement_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Company", "Company") + .WithMany("Consents") + .HasForeignKey("CompanyId") + .IsRequired() + .HasConstraintName("fk_consents_companies_company_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyUser", "CompanyUser") + .WithMany("Consents") + .HasForeignKey("CompanyUserId") + .IsRequired() + .HasConstraintName("fk_consents_company_users_company_user_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ConsentStatus", "ConsentStatus") + .WithMany("Consents") + .HasForeignKey("ConsentStatusId") + .IsRequired() + .HasConstraintName("fk_consents_consent_statuses_consent_status_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Document", "Document") + .WithMany("Consents") + .HasForeignKey("DocumentId") + .HasConstraintName("fk_consents_documents_document_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Identity", "LastEditor") + .WithMany() + .HasForeignKey("LastEditorId") + .HasConstraintName("fk_consents_identities_last_editor_id"); + + b.Navigation("Agreement"); + + b.Navigation("Company"); + + b.Navigation("CompanyUser"); + + b.Navigation("ConsentStatus"); + + b.Navigation("Document"); + + b.Navigation("LastEditor"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ConsentAssignedOffer", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Consent", "Consent") + .WithMany("ConsentAssignedOffers") + .HasForeignKey("ConsentId") + .IsRequired() + .HasConstraintName("fk_consent_assigned_offers_consents_consent_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Offer", "Offer") + .WithMany("ConsentAssignedOffers") + .HasForeignKey("OfferId") + .IsRequired() + .HasConstraintName("fk_consent_assigned_offers_offers_offer_id"); + + b.Navigation("Consent"); + + b.Navigation("Offer"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ConsentAssignedOfferSubscription", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Consent", "Consent") + .WithMany("ConsentAssignedOfferSubscriptions") + .HasForeignKey("ConsentId") + .IsRequired() + .HasConstraintName("fk_consent_assigned_offer_subscriptions_consents_consent_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferSubscription", "OfferSubscription") + .WithMany("ConsentAssignedOfferSubscriptions") + .HasForeignKey("OfferSubscriptionId") + .IsRequired() + .HasConstraintName("fk_consent_assigned_offer_subscriptions_offer_subscriptions_of"); + + b.Navigation("Consent"); + + b.Navigation("OfferSubscription"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CountryAssignedIdentifier", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.BpdmIdentifier", "BpdmIdentifier") + .WithMany("CountryAssignedIdentifiers") + .HasForeignKey("BpdmIdentifierId") + .HasConstraintName("fk_country_assigned_identifiers_bpdm_identifiers_bpdm_identifi"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Country", "Country") + .WithMany("CountryAssignedIdentifiers") + .HasForeignKey("CountryAlpha2Code") + .IsRequired() + .HasConstraintName("fk_country_assigned_identifiers_countries_country_alpha2code"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UniqueIdentifier", "UniqueIdentifier") + .WithMany("CountryAssignedIdentifiers") + .HasForeignKey("UniqueIdentifierId") + .IsRequired() + .HasConstraintName("fk_country_assigned_identifiers_unique_identifiers_unique_iden"); + + b.Navigation("BpdmIdentifier"); + + b.Navigation("Country"); + + b.Navigation("UniqueIdentifier"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Document", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyUser", "CompanyUser") + .WithMany("Documents") + .HasForeignKey("CompanyUserId") + .HasConstraintName("fk_documents_company_users_company_user_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.DocumentStatus", "DocumentStatus") + .WithMany("Documents") + .HasForeignKey("DocumentStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_documents_document_status_document_status_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.DocumentType", "DocumentType") + .WithMany("Documents") + .HasForeignKey("DocumentTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_documents_document_types_document_type_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.MediaType", "MediaType") + .WithMany("Documents") + .HasForeignKey("MediaTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_documents_media_types_media_type_id"); + + b.Navigation("CompanyUser"); + + b.Navigation("DocumentStatus"); + + b.Navigation("DocumentType"); + + b.Navigation("MediaType"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IamIdentityProvider", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IdentityProvider", "IdentityProvider") + .WithOne("IamIdentityProvider") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IamIdentityProvider", "IdentityProviderId") + .IsRequired() + .HasConstraintName("fk_iam_identity_providers_identity_providers_identity_provider"); + + b.Navigation("IdentityProvider"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Identity", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Company", "Company") + .WithMany("Identities") + .HasForeignKey("CompanyId") + .IsRequired() + .HasConstraintName("fk_identities_companies_company_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IdentityType", "IdentityType") + .WithMany("Identities") + .HasForeignKey("IdentityTypeId") + .IsRequired() + .HasConstraintName("fk_identities_identity_type_identity_type_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Identity", "LastEditor") + .WithMany() + .HasForeignKey("LastEditorId") + .HasConstraintName("fk_identities_identities_last_editor_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IdentityUserStatus", "IdentityStatus") + .WithMany("Identities") + .HasForeignKey("UserStatusId") + .IsRequired() + .HasConstraintName("fk_identities_identity_user_statuses_identity_status_id"); + + b.Navigation("Company"); + + b.Navigation("IdentityStatus"); + + b.Navigation("IdentityType"); + + b.Navigation("LastEditor"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IdentityAssignedRole", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Identity", "Identity") + .WithMany("IdentityAssignedRoles") + .HasForeignKey("IdentityId") + .IsRequired() + .HasConstraintName("fk_identity_assigned_roles_identities_identity_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Identity", "LastEditor") + .WithMany() + .HasForeignKey("LastEditorId") + .HasConstraintName("fk_identity_assigned_roles_identities_last_editor_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UserRole", "UserRole") + .WithMany("IdentityAssignedRoles") + .HasForeignKey("UserRoleId") + .IsRequired() + .HasConstraintName("fk_identity_assigned_roles_user_roles_user_role_id"); + + b.Navigation("Identity"); + + b.Navigation("LastEditor"); + + b.Navigation("UserRole"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IdentityProvider", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IdentityProviderCategory", "IdentityProviderCategory") + .WithMany("IdentityProviders") + .HasForeignKey("IdentityProviderCategoryId") + .IsRequired() + .HasConstraintName("fk_identity_providers_identity_provider_categories_identity_pr"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IdentityProviderType", "IdentityProviderType") + .WithMany("IdentityProviders") + .HasForeignKey("IdentityProviderTypeId") + .IsRequired() + .HasConstraintName("fk_identity_providers_identity_provider_types_identity_provide"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Company", "Owner") + .WithMany("OwnedIdentityProviders") + .HasForeignKey("OwnerId") + .IsRequired() + .HasConstraintName("fk_identity_providers_companies_owner_id"); + + b.Navigation("IdentityProviderCategory"); + + b.Navigation("IdentityProviderType"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Invitation", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyApplication", "CompanyApplication") + .WithMany("Invitations") + .HasForeignKey("CompanyApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_invitations_company_applications_company_application_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyUser", "CompanyUser") + .WithMany("Invitations") + .HasForeignKey("CompanyUserId") + .IsRequired() + .HasConstraintName("fk_invitations_company_users_company_user_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.InvitationStatus", "InvitationStatus") + .WithMany("Invitations") + .HasForeignKey("InvitationStatusId") + .IsRequired() + .HasConstraintName("fk_invitations_invitation_statuses_invitation_status_id"); + + b.Navigation("CompanyApplication"); + + b.Navigation("CompanyUser"); + + b.Navigation("InvitationStatus"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.LanguageLongName", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Language", "LongNameLanguage") + .WithMany("LanguageLongNameLanguages") + .HasForeignKey("LanguageShortName") + .IsRequired() + .HasConstraintName("fk_language_long_names_languages_long_name_language_short_name"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Language", "Language") + .WithMany("LanguageLongNames") + .HasForeignKey("ShortName") + .IsRequired() + .HasConstraintName("fk_language_long_names_languages_language_short_name"); + + b.Navigation("Language"); + + b.Navigation("LongNameLanguage"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.NetworkRegistration", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyApplication", "CompanyApplication") + .WithOne("NetworkRegistration") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.NetworkRegistration", "ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_network_registrations_company_applications_application_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Company", "Company") + .WithOne("NetworkRegistration") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.NetworkRegistration", "CompanyId") + .IsRequired() + .HasConstraintName("fk_network_registrations_companies_company_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Company", "OnboardingServiceProvider") + .WithMany("OnboardedNetworkRegistrations") + .HasForeignKey("OnboardingServiceProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_network_registrations_companies_onboarding_service_provider"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Process", "Process") + .WithOne("NetworkRegistration") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.NetworkRegistration", "ProcessId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_network_registrations_processes_process_id"); + + b.Navigation("Company"); + + b.Navigation("CompanyApplication"); + + b.Navigation("OnboardingServiceProvider"); + + b.Navigation("Process"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Notification", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Identity", "Creator") + .WithMany("CreatedNotifications") + .HasForeignKey("CreatorUserId") + .HasConstraintName("fk_notifications_identities_creator_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.NotificationType", "NotificationType") + .WithMany("Notifications") + .HasForeignKey("NotificationTypeId") + .IsRequired() + .HasConstraintName("fk_notifications_notification_type_notification_type_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyUser", "Receiver") + .WithMany("Notifications") + .HasForeignKey("ReceiverUserId") + .IsRequired() + .HasConstraintName("fk_notifications_company_users_receiver_id"); + + b.Navigation("Creator"); + + b.Navigation("NotificationType"); + + b.Navigation("Receiver"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.NotificationTypeAssignedTopic", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.NotificationTopic", "NotificationTopic") + .WithMany("NotificationTypeAssignedTopics") + .HasForeignKey("NotificationTopicId") + .IsRequired() + .HasConstraintName("fk_notification_type_assigned_topics_notification_topic_notifi"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.NotificationType", "NotificationType") + .WithOne("NotificationTypeAssignedTopic") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.NotificationTypeAssignedTopic", "NotificationTypeId") + .IsRequired() + .HasConstraintName("fk_notification_type_assigned_topics_notification_type_notific"); + + b.Navigation("NotificationTopic"); + + b.Navigation("NotificationType"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Offer", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Identity", "LastEditor") + .WithMany() + .HasForeignKey("LastEditorId") + .HasConstraintName("fk_offers_identities_last_editor_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.LicenseType", "LicenseType") + .WithMany("Offers") + .HasForeignKey("LicenseTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_offers_license_types_license_type_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferStatus", "OfferStatus") + .WithMany("Offers") + .HasForeignKey("OfferStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_offers_offer_statuses_offer_status_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferType", "OfferType") + .WithMany("Offers") + .HasForeignKey("OfferTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_offers_offer_types_offer_type_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Company", "ProviderCompany") + .WithMany("ProvidedOffers") + .HasForeignKey("ProviderCompanyId") + .HasConstraintName("fk_offers_companies_provider_company_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyUser", "SalesManager") + .WithMany("SalesManagerOfOffers") + .HasForeignKey("SalesManagerId") + .HasConstraintName("fk_offers_company_users_sales_manager_id"); + + b.Navigation("LastEditor"); + + b.Navigation("LicenseType"); + + b.Navigation("OfferStatus"); + + b.Navigation("OfferType"); + + b.Navigation("ProviderCompany"); + + b.Navigation("SalesManager"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferAssignedDocument", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Document", "Document") + .WithMany() + .HasForeignKey("DocumentId") + .IsRequired() + .HasConstraintName("fk_offer_assigned_documents_documents_document_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Offer", "Offer") + .WithMany() + .HasForeignKey("OfferId") + .IsRequired() + .HasConstraintName("fk_offer_assigned_documents_offers_offer_id"); + + b.Navigation("Document"); + + b.Navigation("Offer"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferAssignedLicense", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Offer", "Offer") + .WithMany() + .HasForeignKey("OfferId") + .IsRequired() + .HasConstraintName("fk_offer_assigned_licenses_offers_offer_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferLicense", "OfferLicense") + .WithMany() + .HasForeignKey("OfferLicenseId") + .IsRequired() + .HasConstraintName("fk_offer_assigned_licenses_offer_licenses_offer_license_id"); + + b.Navigation("Offer"); + + b.Navigation("OfferLicense"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferAssignedPrivacyPolicy", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Offer", "Offer") + .WithMany("OfferAssignedPrivacyPolicies") + .HasForeignKey("OfferId") + .IsRequired() + .HasConstraintName("fk_offer_assigned_privacy_policies_offers_offer_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.PrivacyPolicy", "PrivacyPolicy") + .WithMany("OfferAssignedPrivacyPolicies") + .HasForeignKey("PrivacyPolicyId") + .IsRequired() + .HasConstraintName("fk_offer_assigned_privacy_policies_privacy_policies_privacy_po"); + + b.Navigation("Offer"); + + b.Navigation("PrivacyPolicy"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferDescription", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Language", "Language") + .WithMany("AppDescriptions") + .HasForeignKey("LanguageShortName") + .IsRequired() + .HasConstraintName("fk_offer_descriptions_languages_language_short_name"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Offer", "Offer") + .WithMany("OfferDescriptions") + .HasForeignKey("OfferId") + .IsRequired() + .HasConstraintName("fk_offer_descriptions_offers_offer_id"); + + b.Navigation("Language"); + + b.Navigation("Offer"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferSubscription", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Company", "Company") + .WithMany("OfferSubscriptions") + .HasForeignKey("CompanyId") + .IsRequired() + .HasConstraintName("fk_offer_subscriptions_companies_company_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Identity", "LastEditor") + .WithMany() + .HasForeignKey("LastEditorId") + .HasConstraintName("fk_offer_subscriptions_identities_last_editor_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Offer", "Offer") + .WithMany("OfferSubscriptions") + .HasForeignKey("OfferId") + .IsRequired() + .HasConstraintName("fk_offer_subscriptions_offers_offer_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferSubscriptionStatus", "OfferSubscriptionStatus") + .WithMany("OfferSubscriptions") + .HasForeignKey("OfferSubscriptionStatusId") + .IsRequired() + .HasConstraintName("fk_offer_subscriptions_offer_subscription_statuses_offer_subsc"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Process", "Process") + .WithOne("OfferSubscription") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferSubscription", "ProcessId") + .HasConstraintName("fk_offer_subscriptions_processes_process_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyUser", "Requester") + .WithMany("RequestedSubscriptions") + .HasForeignKey("RequesterId") + .IsRequired() + .HasConstraintName("fk_offer_subscriptions_company_users_requester_id"); + + b.Navigation("Company"); + + b.Navigation("LastEditor"); + + b.Navigation("Offer"); + + b.Navigation("OfferSubscriptionStatus"); + + b.Navigation("Process"); + + b.Navigation("Requester"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferSubscriptionProcessData", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferSubscription", "OfferSubscription") + .WithOne("OfferSubscriptionProcessData") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferSubscriptionProcessData", "OfferSubscriptionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_offer_subscriptions_process_datas_offer_subscriptions_offer"); + + b.Navigation("OfferSubscription"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferTag", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Offer", "Offer") + .WithMany("Tags") + .HasForeignKey("OfferId") + .IsRequired() + .HasConstraintName("fk_offer_tags_offers_offer_id"); + + b.Navigation("Offer"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OnboardingServiceProviderDetail", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Company", "Company") + .WithOne("OnboardingServiceProviderDetail") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OnboardingServiceProviderDetail", "CompanyId") + .IsRequired() + .HasConstraintName("fk_onboarding_service_provider_details_companies_company_id"); + + b.Navigation("Company"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Process", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ProcessType", "ProcessType") + .WithMany("Processes") + .HasForeignKey("ProcessTypeId") + .IsRequired() + .HasConstraintName("fk_processes_process_types_process_type_id"); + + b.Navigation("ProcessType"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ProcessStep", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Process", "Process") + .WithMany("ProcessSteps") + .HasForeignKey("ProcessId") + .IsRequired() + .HasConstraintName("fk_process_steps_processes_process_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ProcessStepStatus", "ProcessStepStatus") + .WithMany("ProcessSteps") + .HasForeignKey("ProcessStepStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_process_steps_process_step_statuses_process_step_status_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ProcessStepType", "ProcessStepType") + .WithMany("ProcessSteps") + .HasForeignKey("ProcessStepTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_process_steps_process_step_types_process_step_type_id"); + + b.Navigation("Process"); + + b.Navigation("ProcessStepStatus"); + + b.Navigation("ProcessStepType"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ProviderCompanyDetail", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Company", "Company") + .WithOne("ProviderCompanyDetail") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ProviderCompanyDetail", "CompanyId") + .IsRequired() + .HasConstraintName("fk_provider_company_details_companies_company_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Identity", "LastEditor") + .WithMany() + .HasForeignKey("LastEditorId") + .HasConstraintName("fk_provider_company_details_identities_last_editor_id"); + + b.Navigation("Company"); + + b.Navigation("LastEditor"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ServiceDetail", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Offer", "Service") + .WithMany("ServiceDetails") + .HasForeignKey("ServiceId") + .IsRequired() + .HasConstraintName("fk_service_details_offers_service_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ServiceType", "ServiceType") + .WithMany("ServiceDetails") + .HasForeignKey("ServiceTypeId") + .IsRequired() + .HasConstraintName("fk_service_details_service_types_service_type_id"); + + b.Navigation("Service"); + + b.Navigation("ServiceType"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.TechnicalUserProfile", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Offer", "Offer") + .WithMany("TechnicalUserProfiles") + .HasForeignKey("OfferId") + .IsRequired() + .HasConstraintName("fk_technical_user_profiles_offers_offer_id"); + + b.Navigation("Offer"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.TechnicalUserProfileAssignedUserRole", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.TechnicalUserProfile", "TechnicalUserProfile") + .WithMany("TechnicalUserProfileAssignedUserRoles") + .HasForeignKey("TechnicalUserProfileId") + .IsRequired() + .HasConstraintName("fk_technical_user_profile_assigned_user_roles_technical_user_p"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UserRole", "UserRole") + .WithMany("TechnicalUserProfileAssignedUserRole") + .HasForeignKey("UserRoleId") + .IsRequired() + .HasConstraintName("fk_technical_user_profile_assigned_user_roles_user_roles_user_r"); + + b.Navigation("TechnicalUserProfile"); + + b.Navigation("UserRole"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UseCaseDescription", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Language", "Language") + .WithMany("UseCases") + .HasForeignKey("LanguageShortName") + .IsRequired() + .HasConstraintName("fk_use_case_descriptions_languages_language_short_name"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UseCase", "UseCase") + .WithMany("UseCaseDescriptions") + .HasForeignKey("UseCaseId") + .IsRequired() + .HasConstraintName("fk_use_case_descriptions_use_cases_use_case_id"); + + b.Navigation("Language"); + + b.Navigation("UseCase"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UserRole", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Identity", "LastEditor") + .WithMany() + .HasForeignKey("LastEditorId") + .HasConstraintName("fk_user_roles_identities_last_editor_id"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Offer", "Offer") + .WithMany("UserRoles") + .HasForeignKey("OfferId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_roles_offers_offer_id"); + + b.Navigation("LastEditor"); + + b.Navigation("Offer"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UserRoleAssignedCollection", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UserRoleCollection", "UserRoleCollection") + .WithMany() + .HasForeignKey("UserRoleCollectionId") + .IsRequired() + .HasConstraintName("fk_user_role_assigned_collections_user_role_collections_user_r"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UserRole", "UserRole") + .WithMany() + .HasForeignKey("UserRoleId") + .IsRequired() + .HasConstraintName("fk_user_role_assigned_collections_user_roles_user_role_id"); + + b.Navigation("UserRole"); + + b.Navigation("UserRoleCollection"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UserRoleCollectionDescription", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Language", "Language") + .WithMany() + .HasForeignKey("LanguageShortName") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_role_collection_descriptions_languages_language_short_"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UserRoleCollection", "UserRoleCollection") + .WithMany("UserRoleCollectionDescriptions") + .HasForeignKey("UserRoleCollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_role_collection_descriptions_user_role_collections_use"); + + b.Navigation("Language"); + + b.Navigation("UserRoleCollection"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UserRoleDescription", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Language", "Language") + .WithMany("UserRoleDescriptions") + .HasForeignKey("LanguageShortName") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_role_descriptions_languages_language_short_name"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UserRole", "UserRole") + .WithMany("UserRoleDescriptions") + .HasForeignKey("UserRoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_role_descriptions_user_roles_user_role_id"); + + b.Navigation("Language"); + + b.Navigation("UserRole"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialExternalTypeUseCaseDetailVersion", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialExternalType", "VerifiedCredentialExternalType") + .WithMany("VerifiedCredentialExternalTypeUseCaseDetailVersions") + .HasForeignKey("VerifiedCredentialExternalTypeId") + .IsRequired() + .HasConstraintName("fk_verified_credential_external_type_use_case_detail_versions_"); + + b.Navigation("VerifiedCredentialExternalType"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialTypeAssignedExternalType", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialExternalType", "VerifiedCredentialExternalType") + .WithMany("VerifiedCredentialTypeAssignedExternalTypes") + .HasForeignKey("VerifiedCredentialExternalTypeId") + .IsRequired() + .HasConstraintName("fk_verified_credential_type_assigned_external_types_verified_c"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialType", "VerifiedCredentialType") + .WithOne("VerifiedCredentialTypeAssignedExternalType") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialTypeAssignedExternalType", "VerifiedCredentialTypeId") + .IsRequired() + .HasConstraintName("fk_verified_credential_type_assigned_external_types_verified_c1"); + + b.Navigation("VerifiedCredentialExternalType"); + + b.Navigation("VerifiedCredentialType"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialTypeAssignedKind", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialType", "VerifiedCredentialType") + .WithOne("VerifiedCredentialTypeAssignedKind") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialTypeAssignedKind", "VerifiedCredentialTypeId") + .IsRequired() + .HasConstraintName("fk_verified_credential_type_assigned_kinds_verified_credential"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialTypeKind", "VerifiedCredentialTypeKind") + .WithMany("VerifiedCredentialTypeAssignedKinds") + .HasForeignKey("VerifiedCredentialTypeKindId") + .IsRequired() + .HasConstraintName("fk_verified_credential_type_assigned_kinds_verified_credential1"); + + b.Navigation("VerifiedCredentialType"); + + b.Navigation("VerifiedCredentialTypeKind"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialTypeAssignedUseCase", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UseCase", "UseCase") + .WithOne("VerifiedCredentialAssignedUseCase") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialTypeAssignedUseCase", "UseCaseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_verified_credential_type_assigned_use_cases_use_cases_use_c"); + + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialType", "VerifiedCredentialType") + .WithOne("VerifiedCredentialTypeAssignedUseCase") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialTypeAssignedUseCase", "VerifiedCredentialTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_verified_credential_type_assigned_use_cases_verified_creden"); + + b.Navigation("UseCase"); + + b.Navigation("VerifiedCredentialType"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Views.CompaniesLinkedServiceAccount", b => + { + b.HasOne("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyServiceAccount", "CompanyServiceAccount") + .WithOne("CompaniesLinkedServiceAccount") + .HasForeignKey("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Views.CompaniesLinkedServiceAccount", "ServiceAccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_company_linked_service_accounts_company_service_accounts_co"); + + b.Navigation("CompanyServiceAccount"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Address", b => + { + b.Navigation("Companies"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Agreement", b => + { + b.Navigation("AgreementAssignedCompanyRoles"); + + b.Navigation("AgreementAssignedOfferTypes"); + + b.Navigation("AgreementAssignedOffers"); + + b.Navigation("Consents"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AgreementCategory", b => + { + b.Navigation("Agreements"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.AppInstance", b => + { + b.Navigation("AppSubscriptionDetails"); + + b.Navigation("ServiceAccounts"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ApplicationChecklistEntryStatus", b => + { + b.Navigation("ApplicationChecklistEntries"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ApplicationChecklistEntryType", b => + { + b.Navigation("ApplicationChecklistEntries"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.BpdmIdentifier", b => + { + b.Navigation("CountryAssignedIdentifiers"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Company", b => + { + b.Navigation("Agreements"); + + b.Navigation("CompanyApplications"); + + b.Navigation("CompanyAssignedRoles"); + + b.Navigation("CompanyAssignedUseCase"); + + b.Navigation("CompanyIdentifiers"); + + b.Navigation("CompanySsiDetails"); + + b.Navigation("Consents"); + + b.Navigation("HostedConnectors"); + + b.Navigation("Identities"); + + b.Navigation("NetworkRegistration"); + + b.Navigation("OfferSubscriptions"); + + b.Navigation("OnboardedNetworkRegistrations"); + + b.Navigation("OnboardingServiceProviderDetail"); + + b.Navigation("OwnedIdentityProviders"); + + b.Navigation("ProvidedApplications"); + + b.Navigation("ProvidedConnectors"); + + b.Navigation("ProvidedOffers"); + + b.Navigation("ProviderCompanyDetail"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyApplication", b => + { + b.Navigation("ApplicationChecklistEntries"); + + b.Navigation("Invitations"); + + b.Navigation("NetworkRegistration"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyApplicationStatus", b => + { + b.Navigation("CompanyApplications"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyApplicationType", b => + { + b.Navigation("CompanyApplications"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyRole", b => + { + b.Navigation("AgreementAssignedCompanyRoles"); + + b.Navigation("CompanyAssignedRoles"); + + b.Navigation("CompanyRoleAssignedRoleCollection"); + + b.Navigation("CompanyRoleDescriptions"); + + b.Navigation("CompanyRoleRegistrationData"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyServiceAccount", b => + { + b.Navigation("AppInstances"); + + b.Navigation("CompaniesLinkedServiceAccount"); + + b.Navigation("Connector"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyServiceAccountType", b => + { + b.Navigation("CompanyServiceAccounts"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanySsiDetailStatus", b => + { + b.Navigation("CompanySsiDetails"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyStatus", b => + { + b.Navigation("Companies"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.CompanyUser", b => + { + b.Navigation("CompanySsiDetails"); + + b.Navigation("CompanyUserAssignedBusinessPartners"); + + b.Navigation("CompanyUserAssignedIdentityProviders"); + + b.Navigation("Consents"); + + b.Navigation("Documents"); + + b.Navigation("Invitations"); + + b.Navigation("Notifications"); + + b.Navigation("RequestedSubscriptions"); + + b.Navigation("SalesManagerOfOffers"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Connector", b => + { + b.Navigation("ConnectorAssignedOfferSubscriptions"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ConnectorStatus", b => + { + b.Navigation("Connectors"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ConnectorType", b => + { + b.Navigation("Connectors"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Consent", b => + { + b.Navigation("ConsentAssignedOfferSubscriptions"); + + b.Navigation("ConsentAssignedOffers"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ConsentStatus", b => + { + b.Navigation("Consents"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Country", b => + { + b.Navigation("Addresses"); + + b.Navigation("Connectors"); + + b.Navigation("CountryAssignedIdentifiers"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Document", b => + { + b.Navigation("Agreements"); + + b.Navigation("Companies"); + + b.Navigation("CompanySsiDetail"); + + b.Navigation("Connector"); + + b.Navigation("Consents"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.DocumentStatus", b => + { + b.Navigation("Documents"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.DocumentType", b => + { + b.Navigation("Documents"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IamClient", b => + { + b.Navigation("AppInstances"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Identity", b => + { + b.Navigation("CompanyServiceAccount"); + + b.Navigation("CompanyUser"); + + b.Navigation("CreatedNotifications"); + + b.Navigation("IdentityAssignedRoles"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IdentityProvider", b => + { + b.Navigation("CompanyIdentityProviders"); + + b.Navigation("CompanyUserAssignedIdentityProviders"); + + b.Navigation("IamIdentityProvider"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IdentityProviderCategory", b => + { + b.Navigation("IdentityProviders"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IdentityProviderType", b => + { + b.Navigation("IdentityProviders"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IdentityType", b => + { + b.Navigation("Identities"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.IdentityUserStatus", b => + { + b.Navigation("Identities"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.InvitationStatus", b => + { + b.Navigation("Invitations"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Language", b => + { + b.Navigation("AppDescriptions"); + + b.Navigation("CompanyRoleDescriptions"); + + b.Navigation("LanguageLongNameLanguages"); + + b.Navigation("LanguageLongNames"); + + b.Navigation("UseCases"); + + b.Navigation("UserRoleDescriptions"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.LicenseType", b => + { + b.Navigation("Offers"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.MediaType", b => + { + b.Navigation("Documents"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.NotificationTopic", b => + { + b.Navigation("NotificationTypeAssignedTopics"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.NotificationType", b => + { + b.Navigation("NotificationTypeAssignedTopic"); + + b.Navigation("Notifications"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Offer", b => + { + b.Navigation("AgreementAssignedOffers"); + + b.Navigation("AppInstanceSetup"); + + b.Navigation("AppInstances"); + + b.Navigation("ConsentAssignedOffers"); + + b.Navigation("OfferAssignedPrivacyPolicies"); + + b.Navigation("OfferDescriptions"); + + b.Navigation("OfferSubscriptions"); + + b.Navigation("ServiceDetails"); + + b.Navigation("Tags"); + + b.Navigation("TechnicalUserProfiles"); + + b.Navigation("UserRoles"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferStatus", b => + { + b.Navigation("Offers"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferSubscription", b => + { + b.Navigation("AppSubscriptionDetail"); + + b.Navigation("CompanyServiceAccounts"); + + b.Navigation("ConnectorAssignedOfferSubscriptions"); + + b.Navigation("ConsentAssignedOfferSubscriptions"); + + b.Navigation("OfferSubscriptionProcessData"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferSubscriptionStatus", b => + { + b.Navigation("OfferSubscriptions"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferType", b => + { + b.Navigation("AgreementAssignedOfferTypes"); + + b.Navigation("Offers"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.PrivacyPolicy", b => + { + b.Navigation("OfferAssignedPrivacyPolicies"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Process", b => + { + b.Navigation("CompanyApplication"); + + b.Navigation("NetworkRegistration"); + + b.Navigation("OfferSubscription"); + + b.Navigation("ProcessSteps"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ProcessStepStatus", b => + { + b.Navigation("ProcessSteps"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ProcessStepType", b => + { + b.Navigation("ProcessSteps"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ProcessType", b => + { + b.Navigation("Processes"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.ServiceType", b => + { + b.Navigation("ServiceDetails"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.TechnicalUserProfile", b => + { + b.Navigation("TechnicalUserProfileAssignedUserRoles"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UniqueIdentifier", b => + { + b.Navigation("CompanyIdentifiers"); + + b.Navigation("CountryAssignedIdentifiers"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UseCase", b => + { + b.Navigation("Agreements"); + + b.Navigation("CompanyAssignedUseCase"); + + b.Navigation("UseCaseDescriptions"); + + b.Navigation("VerifiedCredentialAssignedUseCase"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UserRole", b => + { + b.Navigation("IdentityAssignedRoles"); + + b.Navigation("TechnicalUserProfileAssignedUserRole"); + + b.Navigation("UserRoleDescriptions"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.UserRoleCollection", b => + { + b.Navigation("CompanyRoleAssignedRoleCollection"); + + b.Navigation("UserRoleCollectionDescriptions"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialExternalType", b => + { + b.Navigation("VerifiedCredentialExternalTypeUseCaseDetailVersions"); + + b.Navigation("VerifiedCredentialTypeAssignedExternalTypes"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialExternalTypeUseCaseDetailVersion", b => + { + b.Navigation("CompanySsiDetails"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialType", b => + { + b.Navigation("CompanySsiDetails"); + + b.Navigation("VerifiedCredentialTypeAssignedExternalType"); + + b.Navigation("VerifiedCredentialTypeAssignedKind"); + + b.Navigation("VerifiedCredentialTypeAssignedUseCase"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.VerifiedCredentialTypeKind", b => + { + b.Navigation("VerifiedCredentialTypeAssignedKinds"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/portalbackend/PortalBackend.Migrations/Migrations/20231024094241_1.7.0-rc1.cs b/src/portalbackend/PortalBackend.Migrations/Migrations/20231024094241_1.7.0-rc1.cs new file mode 100644 index 0000000000..a547a19038 --- /dev/null +++ b/src/portalbackend/PortalBackend.Migrations/Migrations/20231024094241_1.7.0-rc1.cs @@ -0,0 +1,316 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 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 Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Org.Eclipse.TractusX.Portal.Backend.PortalBackend.Migrations.Migrations +{ + /// + public partial class _170rc1 : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.Sql("DROP FUNCTION \"portal\".\"LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION\"() CASCADE;"); + migrationBuilder.Sql("DROP FUNCTION \"portal\".\"LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION\"() CASCADE;"); + + migrationBuilder.AddColumn( + name: "date_created", + schema: "portal", + table: "offer_subscriptions", + type: "timestamp with time zone", + nullable: false, + defaultValue: new DateTimeOffset(new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), new TimeSpan(0, 0, 0, 0, 0))); + + migrationBuilder.CreateTable( + name: "audit_offer_subscription20231013", + schema: "portal", + columns: table => new + { + audit_v1id = table.Column(type: "uuid", nullable: false), + id = table.Column(type: "uuid", nullable: false), + company_id = table.Column(type: "uuid", nullable: false), + offer_id = table.Column(type: "uuid", nullable: false), + offer_subscription_status_id = table.Column(type: "integer", nullable: false), + display_name = table.Column(type: "text", nullable: true), + description = table.Column(type: "text", nullable: true), + requester_id = table.Column(type: "uuid", nullable: false), + last_editor_id = table.Column(type: "uuid", nullable: true), + process_id = table.Column(type: "uuid", nullable: true), + date_created = table.Column(type: "timestamp with time zone", nullable: false), + audit_v1last_editor_id = table.Column(type: "uuid", nullable: true), + audit_v1date_last_changed = table.Column(type: "timestamp with time zone", nullable: false), + audit_v1operation_id = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_audit_offer_subscription20231013", x => x.audit_v1id); + }); + + migrationBuilder.InsertData( + schema: "portal", + table: "process_step_types", + columns: new[] { "id", "label" }, + values: new object[] { 300, "SYNCHRONIZE_SERVICE_ACCOUNTS" }); + + migrationBuilder.InsertData( + schema: "portal", + table: "process_types", + columns: new[] { "id", "label" }, + values: new object[] { 5, "SERVICE_ACCOUNT_SYNC" }); + + migrationBuilder.Sql("ALTER TABLE portal.connector_assigned_offer_subscriptions DROP CONSTRAINT IF EXISTS CK_Connector_ConnectorType_IsManaged;"); + migrationBuilder.Sql("DROP FUNCTION IF EXISTS portal.is_connector_managed;"); + + migrationBuilder.Sql("ALTER TABLE portal.verified_credential_type_assigned_use_cases DROP CONSTRAINT IF EXISTS CK_VCTypeAssignedUseCase_VerifiedCredentialType_UseCase;"); + migrationBuilder.Sql("DROP FUNCTION IF EXISTS portal.is_credential_type_use_case;"); + + migrationBuilder.Sql("ALTER TABLE portal.company_ssi_details DROP CONSTRAINT IF EXISTS CK_VC_ExternalType_DetailId_UseCase;"); + migrationBuilder.Sql("DROP FUNCTION IF EXISTS portal.is_external_type_use_case;"); + + migrationBuilder.Sql(@"DROP TRIGGER IF EXISTS ct_is_connector_managed ON portal.connector_assigned_offer_subscriptions;"); + migrationBuilder.Sql(@"DROP FUNCTION IF EXISTS portal.tr_is_connector_managed;"); + + migrationBuilder.Sql(@"DROP TRIGGER IF EXISTS ct_is_credential_type_use_case ON portal.verified_credential_type_assigned_use_cases;"); + migrationBuilder.Sql(@"DROP FUNCTION IF EXISTS portal.tr_is_credential_type_use_case;"); + + migrationBuilder.Sql(@"DROP TRIGGER IF EXISTS ct_is_external_type_use_case ON portal.company_ssi_details;"); + migrationBuilder.Sql(@"DROP FUNCTION IF EXISTS portal.tr_is_external_type_use_case;"); + + migrationBuilder.Sql(@"CREATE FUNCTION portal.tr_is_connector_managed() + RETURNS trigger + VOLATILE + COST 100 + AS $$ + BEGIN + IF EXISTS( + SELECT 1 + FROM portal.connectors + WHERE Id = NEW.connector_id + AND type_id = 2 + ) + THEN RETURN NEW; + END IF; + RAISE EXCEPTION 'the connector % is not managed', NEW.connector_id; + END + $$ LANGUAGE plpgsql;"); + + migrationBuilder.Sql(@"CREATE CONSTRAINT TRIGGER ct_is_connector_managed + AFTER INSERT + ON portal.connector_assigned_offer_subscriptions + INITIALLY DEFERRED + FOR EACH ROW + EXECUTE PROCEDURE portal.tr_is_connector_managed();"); + + migrationBuilder.Sql(@"CREATE FUNCTION portal.tr_is_credential_type_use_case() + RETURNS trigger + VOLATILE + COST 100 + AS $$ + BEGIN + IF EXISTS ( + SELECT 1 + FROM portal.verified_credential_types + WHERE Id = NEW.verified_credential_type_id + AND NEW.verified_credential_type_id IN ( + SELECT verified_credential_type_id + FROM portal.verified_credential_type_assigned_kinds + WHERE verified_credential_type_kind_id = '1' + ) + ) + THEN RETURN NEW; + END IF; + RAISE EXCEPTION 'The credential % is not a use case', NEW.verified_credential_type_id; + END + $$ LANGUAGE plpgsql;"); + + migrationBuilder.Sql(@"CREATE CONSTRAINT TRIGGER ct_is_credential_type_use_case + AFTER INSERT + ON portal.verified_credential_type_assigned_use_cases + INITIALLY DEFERRED + FOR EACH ROW + EXECUTE PROCEDURE portal.tr_is_credential_type_use_case();"); + + migrationBuilder.Sql(@"CREATE FUNCTION portal.tr_is_external_type_use_case() + RETURNS trigger + VOLATILE + COST 100 + AS $$ + BEGIN + IF NEW.verified_credential_external_type_use_case_detail_id IS NULL + THEN RETURN NEW; + END IF; + IF EXISTS ( + SELECT 1 + FROM portal.verified_credential_external_type_use_case_detail_versions + WHERE Id = NEW.verified_credential_external_type_use_case_detail_id + AND verified_credential_external_type_id IN ( + SELECT verified_credential_external_type_id + FROM portal.verified_credential_type_assigned_external_types + WHERE verified_credential_type_id IN ( + SELECT verified_credential_type_id + FROM portal.verified_credential_type_assigned_kinds + WHERE verified_credential_type_kind_id = '1' + ) + ) + ) + THEN RETURN NEW; + END IF; + RAISE EXCEPTION 'the detail % is not an use case', NEW.verified_credential_external_type_use_case_detail_id; + END + $$ LANGUAGE plpgsql;"); + + migrationBuilder.Sql(@"CREATE CONSTRAINT TRIGGER ct_is_external_type_use_case + AFTER INSERT + ON portal.company_ssi_details + INITIALLY DEFERRED + FOR EACH ROW + EXECUTE PROCEDURE portal.tr_is_external_type_use_case();"); + + migrationBuilder.Sql("CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_offer_subscription20231013\" (\"id\", \"company_id\", \"offer_id\", \"offer_subscription_status_id\", \"display_name\", \"description\", \"requester_id\", \"last_editor_id\", \"process_id\", \"date_created\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"company_id\", \r\n NEW.\"offer_id\", \r\n NEW.\"offer_subscription_status_id\", \r\n NEW.\"display_name\", \r\n NEW.\"description\", \r\n NEW.\"requester_id\", \r\n NEW.\"last_editor_id\", \r\n NEW.\"process_id\", \r\n NEW.\"date_created\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION AFTER INSERT\r\nON \"portal\".\"offer_subscriptions\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION\"();"); + migrationBuilder.Sql("CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_offer_subscription20231013\" (\"id\", \"company_id\", \"offer_id\", \"offer_subscription_status_id\", \"display_name\", \"description\", \"requester_id\", \"last_editor_id\", \"process_id\", \"date_created\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"company_id\", \r\n NEW.\"offer_id\", \r\n NEW.\"offer_subscription_status_id\", \r\n NEW.\"display_name\", \r\n NEW.\"description\", \r\n NEW.\"requester_id\", \r\n NEW.\"last_editor_id\", \r\n NEW.\"process_id\", \r\n NEW.\"date_created\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION AFTER UPDATE\r\nON \"portal\".\"offer_subscriptions\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION\"();"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.Sql("DROP FUNCTION \"portal\".\"LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION\"() CASCADE;"); + migrationBuilder.Sql("DROP FUNCTION \"portal\".\"LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION\"() CASCADE;"); + + migrationBuilder.DropTable( + name: "audit_offer_subscription20231013", + schema: "portal"); + + migrationBuilder.DeleteData( + schema: "portal", + table: "process_step_types", + keyColumn: "id", + keyValue: 300); + + migrationBuilder.DeleteData( + schema: "portal", + table: "process_types", + keyColumn: "id", + keyValue: 5); + + migrationBuilder.DropColumn( + name: "date_created", + schema: "portal", + table: "offer_subscriptions"); + + migrationBuilder.Sql(@"DROP TRIGGER IF EXISTS ct_is_connector_managed ON portal.connector_assigned_offer_subscriptions;"); + migrationBuilder.Sql(@"DROP FUNCTION IF EXISTS portal.tr_is_connector_managed;"); + + migrationBuilder.Sql(@"DROP TRIGGER IF EXISTS ct_is_credential_type_use_case ON portal.verified_credential_type_assigned_use_cases;"); + migrationBuilder.Sql(@"DROP FUNCTION IF EXISTS portal.tr_is_credential_type_use_case;"); + + migrationBuilder.Sql(@"DROP TRIGGER IF EXISTS ct_is_external_type_use_case ON portal.company_ssi_details;"); + migrationBuilder.Sql(@"DROP FUNCTION IF EXISTS portal.tr_is_external_type_use_case;"); + + migrationBuilder.Sql("ALTER TABLE portal.connector_assigned_offer_subscriptions DROP CONSTRAINT IF EXISTS CK_Connector_ConnectorType_IsManaged;"); + migrationBuilder.Sql("DROP FUNCTION IF EXISTS portal.is_connector_managed;"); + + migrationBuilder.Sql("ALTER TABLE portal.verified_credential_type_assigned_use_cases DROP CONSTRAINT IF EXISTS CK_VCTypeAssignedUseCase_VerifiedCredentialType_UseCase;"); + migrationBuilder.Sql("DROP FUNCTION IF EXISTS portal.is_credential_type_use_case;"); + + migrationBuilder.Sql("ALTER TABLE portal.company_ssi_details DROP CONSTRAINT IF EXISTS CK_VC_ExternalType_DetailId_UseCase;"); + migrationBuilder.Sql("DROP FUNCTION IF EXISTS portal.is_external_type_use_case;"); + + migrationBuilder.Sql(@"CREATE FUNCTION portal.is_connector_managed(connectorId uuid) + RETURNS BOOLEAN + LANGUAGE plpgsql + AS + $$ + BEGIN + RETURN EXISTS ( + SELECT 1 + FROM portal.connectors + WHERE Id = connectorId + AND type_id = 2 + ); + END; + $$"); + + migrationBuilder.Sql(@" + ALTER TABLE portal.connector_assigned_offer_subscriptions + ADD CONSTRAINT CK_Connector_ConnectorType_IsManaged + CHECK (portal.is_connector_managed(connector_id))"); + + migrationBuilder.Sql(@"CREATE FUNCTION portal.is_credential_type_use_case(vc_type_id integer) + RETURNS BOOLEAN + LANGUAGE plpgsql + AS + $$ + BEGIN + RETURN EXISTS ( + SELECT 1 + FROM portal.verified_credential_types + WHERE Id = vc_type_id + AND vc_type_id IN ( + SELECT verified_credential_type_id + FROM portal.verified_credential_type_assigned_kinds + WHERE verified_credential_type_kind_id = '1' + ) + ); + END; + $$"); + + migrationBuilder.Sql(@" + ALTER TABLE portal.verified_credential_type_assigned_use_cases + ADD CONSTRAINT CK_VCTypeAssignedUseCase_VerifiedCredentialType_UseCase + CHECK (portal.is_credential_type_use_case(verified_credential_type_id))"); + + migrationBuilder.Sql(@"CREATE FUNCTION portal.is_external_type_use_case(verified_credential_external_type_use_case_detail_id UUID) + RETURNS BOOLEAN + LANGUAGE plpgsql + AS + $$ + BEGIN + IF verified_credential_external_type_use_case_detail_id IS NULL THEN + RETURN TRUE; + END IF; + RETURN EXISTS ( + SELECT 1 + FROM portal.verified_credential_external_type_use_case_detail_versions + WHERE Id = verified_credential_external_type_use_case_detail_id + AND verified_credential_external_type_id IN ( + SELECT verified_credential_external_type_id + FROM portal.verified_credential_type_assigned_external_types + WHERE verified_credential_type_id IN ( + SELECT verified_credential_type_id + FROM portal.verified_credential_type_assigned_kinds + WHERE verified_credential_type_kind_id = '1' + ) + ) + ); + END; + $$"); + + migrationBuilder.Sql(@" + ALTER TABLE portal.company_ssi_details + ADD CONSTRAINT CK_VC_ExternalType_DetailId_UseCase + CHECK (portal.is_external_type_use_case(verified_credential_external_type_use_case_detail_id))"); + + migrationBuilder.Sql("CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_offer_subscription20230317\" (\"id\", \"company_id\", \"offer_id\", \"offer_subscription_status_id\", \"display_name\", \"description\", \"requester_id\", \"last_editor_id\", \"process_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"company_id\", \r\n NEW.\"offer_id\", \r\n NEW.\"offer_subscription_status_id\", \r\n NEW.\"display_name\", \r\n NEW.\"description\", \r\n NEW.\"requester_id\", \r\n NEW.\"last_editor_id\", \r\n NEW.\"process_id\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION AFTER INSERT\r\nON \"portal\".\"offer_subscriptions\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION\"();"); + migrationBuilder.Sql("CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_offer_subscription20230317\" (\"id\", \"company_id\", \"offer_id\", \"offer_subscription_status_id\", \"display_name\", \"description\", \"requester_id\", \"last_editor_id\", \"process_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"company_id\", \r\n NEW.\"offer_id\", \r\n NEW.\"offer_subscription_status_id\", \r\n NEW.\"display_name\", \r\n NEW.\"description\", \r\n NEW.\"requester_id\", \r\n NEW.\"last_editor_id\", \r\n NEW.\"process_id\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION AFTER UPDATE\r\nON \"portal\".\"offer_subscriptions\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION\"();"); + } + } +} diff --git a/src/portalbackend/PortalBackend.Migrations/Migrations/PortalDbContextModelSnapshot.cs b/src/portalbackend/PortalBackend.Migrations/Migrations/PortalDbContextModelSnapshot.cs index 9ad54dade4..48b8ac0561 100644 --- a/src/portalbackend/PortalBackend.Migrations/Migrations/PortalDbContextModelSnapshot.cs +++ b/src/portalbackend/PortalBackend.Migrations/Migrations/PortalDbContextModelSnapshot.cs @@ -1,5 +1,4 @@ -/******************************************************************************** - * Copyright (c) 2021, 2023 BMW Group AG +/******************************************************************************** * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional @@ -1089,6 +1088,71 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("audit_offer_subscription20230317", "portal"); }); + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.AuditEntities.AuditOfferSubscription20231013", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("DisplayName") + .HasColumnType("text") + .HasColumnName("display_name"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("OfferId") + .HasColumnType("uuid") + .HasColumnName("offer_id"); + + b.Property("OfferSubscriptionStatusId") + .HasColumnType("integer") + .HasColumnName("offer_subscription_status_id"); + + b.Property("ProcessId") + .HasColumnType("uuid") + .HasColumnName("process_id"); + + b.Property("RequesterId") + .HasColumnType("uuid") + .HasColumnName("requester_id"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_offer_subscription20231013"); + + b.ToTable("audit_offer_subscription20231013", "portal"); + }); + modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.AuditEntities.AuditProviderCompanyDetail20230614", b => { b.Property("AuditV1Id") @@ -4469,6 +4533,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("uuid") .HasColumnName("company_id"); + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + b.Property("Description") .HasMaxLength(4096) .HasColumnType("character varying(4096)") @@ -4531,8 +4599,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) }); b - .HasAnnotation("LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_offer_subscription20230317\" (\"id\", \"company_id\", \"offer_id\", \"offer_subscription_status_id\", \"display_name\", \"description\", \"requester_id\", \"last_editor_id\", \"process_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"company_id\", \r\n NEW.\"offer_id\", \r\n NEW.\"offer_subscription_status_id\", \r\n NEW.\"display_name\", \r\n NEW.\"description\", \r\n NEW.\"requester_id\", \r\n NEW.\"last_editor_id\", \r\n NEW.\"process_id\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION AFTER INSERT\r\nON \"portal\".\"offer_subscriptions\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION\"();") - .HasAnnotation("LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_offer_subscription20230317\" (\"id\", \"company_id\", \"offer_id\", \"offer_subscription_status_id\", \"display_name\", \"description\", \"requester_id\", \"last_editor_id\", \"process_id\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"company_id\", \r\n NEW.\"offer_id\", \r\n NEW.\"offer_subscription_status_id\", \r\n NEW.\"display_name\", \r\n NEW.\"description\", \r\n NEW.\"requester_id\", \r\n NEW.\"last_editor_id\", \r\n NEW.\"process_id\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION AFTER UPDATE\r\nON \"portal\".\"offer_subscriptions\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION\"();"); + .HasAnnotation("LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_offer_subscription20231013\" (\"id\", \"company_id\", \"offer_id\", \"offer_subscription_status_id\", \"display_name\", \"description\", \"requester_id\", \"last_editor_id\", \"process_id\", \"date_created\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"company_id\", \r\n NEW.\"offer_id\", \r\n NEW.\"offer_subscription_status_id\", \r\n NEW.\"display_name\", \r\n NEW.\"description\", \r\n NEW.\"requester_id\", \r\n NEW.\"last_editor_id\", \r\n NEW.\"process_id\", \r\n NEW.\"date_created\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION AFTER INSERT\r\nON \"portal\".\"offer_subscriptions\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_INSERT_OFFERSUBSCRIPTION\"();") + .HasAnnotation("LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION", "CREATE FUNCTION \"portal\".\"LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION$\r\nBEGIN\r\n INSERT INTO \"portal\".\"audit_offer_subscription20231013\" (\"id\", \"company_id\", \"offer_id\", \"offer_subscription_status_id\", \"display_name\", \"description\", \"requester_id\", \"last_editor_id\", \"process_id\", \"date_created\", \"audit_v1id\", \"audit_v1operation_id\", \"audit_v1date_last_changed\", \"audit_v1last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"company_id\", \r\n NEW.\"offer_id\", \r\n NEW.\"offer_subscription_status_id\", \r\n NEW.\"display_name\", \r\n NEW.\"description\", \r\n NEW.\"requester_id\", \r\n NEW.\"last_editor_id\", \r\n NEW.\"process_id\", \r\n NEW.\"date_created\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION AFTER UPDATE\r\nON \"portal\".\"offer_subscriptions\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"portal\".\"LC_TRIGGER_AFTER_UPDATE_OFFERSUBSCRIPTION\"();"); }); modelBuilder.Entity("Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.OfferSubscriptionProcessData", b => @@ -5049,6 +5117,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) { Id = 207, Label = "RETRIGGER_CALLBACK_OSP_DECLINED" + }, + new + { + Id = 300, + Label = "SYNCHRONIZE_SERVICE_ACCOUNTS" }); }); @@ -5084,6 +5157,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) { Id = 4, Label = "PARTNER_REGISTRATION" + }, + new + { + Id = 5, + Label = "SERVICE_ACCOUNT_SYNC" }); }); diff --git a/src/portalbackend/PortalBackend.Migrations/Seeder/Data/agreements.json b/src/portalbackend/PortalBackend.Migrations/Seeder/Data/agreements.json index 53a1266481..fa2f9c4bf5 100644 --- a/src/portalbackend/PortalBackend.Migrations/Seeder/Data/agreements.json +++ b/src/portalbackend/PortalBackend.Migrations/Seeder/Data/agreements.json @@ -104,7 +104,7 @@ "date_created": "2022-01-01 00:00:00.388000 +00:00", "date_last_changed": "2022-01-01 00:00:00.388000 +00:00", "agreement_type": null, - "name": "I confirm that the application I want to offer has successfully received a Catena-X certificate issued by an official Conformity Assessment Body (CAB). I aknowledge to upload the certificate.", + "name": "I confirm that the application I want to offer has successfully received a Catena-X certificate issued by an official Conformity Assessment Body (CAB). I acknowledge to upload the certificate.", "issuer_company_id": "2dc4249f-b5ca-4d42-bef1-7a7a950a4f87", "use_case_id": "1aacde78-35ec-4df3-ba1e-f988cddcbbd9", "document_id": null diff --git a/src/portalbackend/PortalBackend.Migrations/Seeder/Data/identity_assigned_roles.consortia.json b/src/portalbackend/PortalBackend.Migrations/Seeder/Data/identity_assigned_roles.consortia.json index a553b904cd..234821536d 100644 --- a/src/portalbackend/PortalBackend.Migrations/Seeder/Data/identity_assigned_roles.consortia.json +++ b/src/portalbackend/PortalBackend.Migrations/Seeder/Data/identity_assigned_roles.consortia.json @@ -109,76 +109,6 @@ "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51157", "last_editor_id": null }, - { - "identity_id": "7e85a0b8-0001-ab67-10d1-0ef508201009", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51155", - "last_editor_id": null - }, - { - "identity_id": "7e85a0b8-0001-ab67-10d1-0ef508201010", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51155", - "last_editor_id": null - }, - { - "identity_id": "7e85a0b8-0001-ab67-10d1-0ef508201011", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51155", - "last_editor_id": null - }, - { - "identity_id": "7e85a0b8-0001-ab67-10d1-0ef508201012", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51155", - "last_editor_id": null - }, - { - "identity_id": "7e85a0b8-0001-ab67-10d1-0ef508201013", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51155", - "last_editor_id": null - }, - { - "identity_id": "7e85a0b8-0001-ab67-10d1-0ef508201014", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51155", - "last_editor_id": null - }, - { - "identity_id": "7e85a0b8-0001-ab67-10d1-0ef508201015", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51155", - "last_editor_id": null - }, - { - "identity_id": "7e85a0b8-0001-ab67-10d1-0ef508201016", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51155", - "last_editor_id": null - }, - { - "identity_id": "7e85a0b8-0001-ab67-10d1-0ef508201017", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51155", - "last_editor_id": null - }, - { - "identity_id": "7e85a0b8-0001-ab67-10d1-0ef508201018", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51155", - "last_editor_id": null - }, - { - "identity_id": "7e85a0b8-0001-ab67-10d1-0ef508201019", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51155", - "last_editor_id": null - }, - { - "identity_id": "7e85a0b8-0001-ab67-10d1-0ef508201020", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51155", - "last_editor_id": null - }, - { - "identity_id": "7e85a0b8-0001-ab67-10d1-0ef508201021", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51155", - "last_editor_id": null - }, - { - "identity_id": "7e85a0b8-0001-ab67-10d1-0ef508201022", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51155", - "last_editor_id": null - }, { "identity_id": "c3819cfb-72c2-45bf-9666-895af2e7fc19", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51180", diff --git a/src/portalbackend/PortalBackend.Migrations/Seeder/Data/technical_user_profile_assigned_user_roles.consortia.json b/src/portalbackend/PortalBackend.Migrations/Seeder/Data/technical_user_profile_assigned_user_roles.consortia.json index 32b7ebd01c..f5c6cafa3b 100644 --- a/src/portalbackend/PortalBackend.Migrations/Seeder/Data/technical_user_profile_assigned_user_roles.consortia.json +++ b/src/portalbackend/PortalBackend.Migrations/Seeder/Data/technical_user_profile_assigned_user_roles.consortia.json @@ -1,98 +1,71 @@ [ - { - "technical_user_profile_id": "ed128b45-d390-4875-983d-f7477c5c10ae", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51169" - }, - { - "technical_user_profile_id": "c89977b4-f43b-4ab9-808f-a86f6891ee12", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51169" - }, - { - "technical_user_profile_id": "0b906cbc-82da-4ae6-afe5-55f81aa158eb", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51169" - }, - { - "technical_user_profile_id": "6a3205d3-96ec-454d-b705-d9e9eb5edc85", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51169" - }, - { - "technical_user_profile_id": "2822ab7d-ba62-4c58-bc05-8cc6ce73e38e", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51169" - }, - { - "technical_user_profile_id": "68424069-db8c-48db-8278-53fcbb2276af", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51169" - }, - { - "technical_user_profile_id": "9bd7c137-e38b-47c1-acb7-fd69f41d6ee2", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51169" - }, - { - "technical_user_profile_id": "3fab5374-039d-4abb-93e1-e02cb28ffc8c", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51169" - }, - { - "technical_user_profile_id": "c7a4ce0b-f9d7-4338-b5ae-a56ca0583ba0", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51169" - }, - { - "technical_user_profile_id": "318d8ccd-4d84-475f-ae65-e65a88cabe78", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51169" - }, - { - "technical_user_profile_id": "9b0f11fb-8f89-43af-9ab0-e69fe943fe8f", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51169" - }, - { - "technical_user_profile_id": "721a7070-3f87-4213-a2d5-033ab1541853", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51169" - }, - { - "technical_user_profile_id": "f605eef3-5876-435d-9516-8a1c10e84ad4", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51169" - }, - { - "technical_user_profile_id": "43ce6b90-d089-45d7-88c2-0e047a7ecc86", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51169" - }, - { - "technical_user_profile_id": "04b92324-db2c-4d9b-b22a-7420cdab047f", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51169" - }, - { - "technical_user_profile_id": "5e2e87ba-d620-4871-9de8-d228ede2af7d", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51169" - }, - { - "technical_user_profile_id": "dcfa29fc-a036-44e0-80a6-436c6b04bc98", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51169" - }, - { - "technical_user_profile_id": "e0d5859a-7a0b-4e65-aaea-07cb27b76b11", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51169" - }, - { - "technical_user_profile_id": "e6a50691-cdf1-472f-976b-711b44ca8610", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51169" - }, - { - "technical_user_profile_id": "6212e6bf-123f-43c6-a579-7e85e095d796", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51169" - }, - { - "technical_user_profile_id": "d5eb0132-0391-408c-9d1e-d197d52a59ba", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51155" - }, - { - "technical_user_profile_id": "24f8bb90-8543-487b-98f0-e8d96b49e3e4", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51155" - }, - { - "technical_user_profile_id": "51435c54-bad0-4853-8e80-21f8a9bc995b", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51155" - }, - { - "technical_user_profile_id": "faa2ee27-9dca-41f6-825f-0bf05ca8d309", - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51155" - } + {"technical_user_profile_id": "d5eb0132-0391-408c-9d1e-d197d52a59ba", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165" }, + {"technical_user_profile_id": "d5eb0132-0391-408c-9d1e-d197d52a59ba", "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" }, + {"technical_user_profile_id": "24f8bb90-8543-487b-98f0-e8d96b49e3e4", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165" }, + {"technical_user_profile_id": "24f8bb90-8543-487b-98f0-e8d96b49e3e4", "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" }, + {"technical_user_profile_id": "51435c54-bad0-4853-8e80-21f8a9bc995b", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165" }, + {"technical_user_profile_id": "51435c54-bad0-4853-8e80-21f8a9bc995b", "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" }, + {"technical_user_profile_id": "faa2ee27-9dca-41f6-825f-0bf05ca8d309", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165" }, + {"technical_user_profile_id": "faa2ee27-9dca-41f6-825f-0bf05ca8d309", "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" }, + + {"technical_user_profile_id": "ed128b45-d390-4875-983d-f7477c5c10ae", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165" }, + {"technical_user_profile_id": "ed128b45-d390-4875-983d-f7477c5c10ae", "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" }, + {"technical_user_profile_id": "ed128b45-d390-4875-983d-f7477c5c10ae", "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7" }, + {"technical_user_profile_id": "c89977b4-f43b-4ab9-808f-a86f6891ee12", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165" }, + {"technical_user_profile_id": "c89977b4-f43b-4ab9-808f-a86f6891ee12", "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" }, + {"technical_user_profile_id": "c89977b4-f43b-4ab9-808f-a86f6891ee12", "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7" }, + {"technical_user_profile_id": "0b906cbc-82da-4ae6-afe5-55f81aa158eb", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165" }, + {"technical_user_profile_id": "0b906cbc-82da-4ae6-afe5-55f81aa158eb", "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" }, + {"technical_user_profile_id": "0b906cbc-82da-4ae6-afe5-55f81aa158eb", "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7" }, + {"technical_user_profile_id": "6a3205d3-96ec-454d-b705-d9e9eb5edc85", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165" }, + {"technical_user_profile_id": "6a3205d3-96ec-454d-b705-d9e9eb5edc85", "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" }, + {"technical_user_profile_id": "6a3205d3-96ec-454d-b705-d9e9eb5edc85", "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7" }, + {"technical_user_profile_id": "2822ab7d-ba62-4c58-bc05-8cc6ce73e38e", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165" }, + {"technical_user_profile_id": "2822ab7d-ba62-4c58-bc05-8cc6ce73e38e", "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" }, + {"technical_user_profile_id": "2822ab7d-ba62-4c58-bc05-8cc6ce73e38e", "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7" }, + {"technical_user_profile_id": "68424069-db8c-48db-8278-53fcbb2276af", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165" }, + {"technical_user_profile_id": "68424069-db8c-48db-8278-53fcbb2276af", "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" }, + {"technical_user_profile_id": "68424069-db8c-48db-8278-53fcbb2276af", "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7" }, + {"technical_user_profile_id": "9bd7c137-e38b-47c1-acb7-fd69f41d6ee2", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165" }, + {"technical_user_profile_id": "9bd7c137-e38b-47c1-acb7-fd69f41d6ee2", "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" }, + {"technical_user_profile_id": "9bd7c137-e38b-47c1-acb7-fd69f41d6ee2", "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7" }, + {"technical_user_profile_id": "3fab5374-039d-4abb-93e1-e02cb28ffc8c", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165" }, + {"technical_user_profile_id": "3fab5374-039d-4abb-93e1-e02cb28ffc8c", "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" }, + {"technical_user_profile_id": "3fab5374-039d-4abb-93e1-e02cb28ffc8c", "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7" }, + {"technical_user_profile_id": "c7a4ce0b-f9d7-4338-b5ae-a56ca0583ba0", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165" }, + {"technical_user_profile_id": "c7a4ce0b-f9d7-4338-b5ae-a56ca0583ba0", "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" }, + {"technical_user_profile_id": "c7a4ce0b-f9d7-4338-b5ae-a56ca0583ba0", "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7" }, + {"technical_user_profile_id": "318d8ccd-4d84-475f-ae65-e65a88cabe78", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165" }, + {"technical_user_profile_id": "318d8ccd-4d84-475f-ae65-e65a88cabe78", "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" }, + {"technical_user_profile_id": "318d8ccd-4d84-475f-ae65-e65a88cabe78", "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7" }, + {"technical_user_profile_id": "9b0f11fb-8f89-43af-9ab0-e69fe943fe8f", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165" }, + {"technical_user_profile_id": "9b0f11fb-8f89-43af-9ab0-e69fe943fe8f", "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" }, + {"technical_user_profile_id": "9b0f11fb-8f89-43af-9ab0-e69fe943fe8f", "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7" }, + {"technical_user_profile_id": "721a7070-3f87-4213-a2d5-033ab1541853", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165" }, + {"technical_user_profile_id": "721a7070-3f87-4213-a2d5-033ab1541853", "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" }, + {"technical_user_profile_id": "721a7070-3f87-4213-a2d5-033ab1541853", "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7" }, + {"technical_user_profile_id": "f605eef3-5876-435d-9516-8a1c10e84ad4", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165" }, + {"technical_user_profile_id": "f605eef3-5876-435d-9516-8a1c10e84ad4", "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" }, + {"technical_user_profile_id": "f605eef3-5876-435d-9516-8a1c10e84ad4", "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7" }, + {"technical_user_profile_id": "43ce6b90-d089-45d7-88c2-0e047a7ecc86", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165" }, + {"technical_user_profile_id": "43ce6b90-d089-45d7-88c2-0e047a7ecc86", "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" }, + {"technical_user_profile_id": "43ce6b90-d089-45d7-88c2-0e047a7ecc86", "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7" }, + {"technical_user_profile_id": "04b92324-db2c-4d9b-b22a-7420cdab047f", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165" }, + {"technical_user_profile_id": "04b92324-db2c-4d9b-b22a-7420cdab047f", "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" }, + {"technical_user_profile_id": "04b92324-db2c-4d9b-b22a-7420cdab047f", "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7" }, + {"technical_user_profile_id": "5e2e87ba-d620-4871-9de8-d228ede2af7d", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165" }, + {"technical_user_profile_id": "5e2e87ba-d620-4871-9de8-d228ede2af7d", "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" }, + {"technical_user_profile_id": "5e2e87ba-d620-4871-9de8-d228ede2af7d", "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7" }, + {"technical_user_profile_id": "dcfa29fc-a036-44e0-80a6-436c6b04bc98", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165" }, + {"technical_user_profile_id": "dcfa29fc-a036-44e0-80a6-436c6b04bc98", "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" }, + {"technical_user_profile_id": "dcfa29fc-a036-44e0-80a6-436c6b04bc98", "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7" }, + {"technical_user_profile_id": "e0d5859a-7a0b-4e65-aaea-07cb27b76b11", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165" }, + {"technical_user_profile_id": "e0d5859a-7a0b-4e65-aaea-07cb27b76b11", "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" }, + {"technical_user_profile_id": "e0d5859a-7a0b-4e65-aaea-07cb27b76b11", "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7" }, + {"technical_user_profile_id": "e6a50691-cdf1-472f-976b-711b44ca8610", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165" }, + {"technical_user_profile_id": "e6a50691-cdf1-472f-976b-711b44ca8610", "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" }, + {"technical_user_profile_id": "e6a50691-cdf1-472f-976b-711b44ca8610", "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7" }, + {"technical_user_profile_id": "6212e6bf-123f-43c6-a579-7e85e095d796", "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165" }, + {"technical_user_profile_id": "6212e6bf-123f-43c6-a579-7e85e095d796", "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" }, + {"technical_user_profile_id": "6212e6bf-123f-43c6-a579-7e85e095d796", "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7" } ] diff --git a/src/portalbackend/PortalBackend.Migrations/Seeder/Data/user_role_assigned_collections.json b/src/portalbackend/PortalBackend.Migrations/Seeder/Data/user_role_assigned_collections.json index 2bab2ee63b..e8d602a3e4 100644 --- a/src/portalbackend/PortalBackend.Migrations/Seeder/Data/user_role_assigned_collections.json +++ b/src/portalbackend/PortalBackend.Migrations/Seeder/Data/user_role_assigned_collections.json @@ -15,10 +15,6 @@ "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51162", "user_role_collection_id": "1a24eca5-901f-4191-84a7-4ef09a894575" }, - { - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51155", - "user_role_collection_id": "1a24eca5-901f-4191-84a7-4ef09a894575" - }, { "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165", "user_role_collection_id": "1a24eca5-901f-4191-84a7-4ef09a894575" @@ -55,10 +51,6 @@ "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51162", "user_role_collection_id": "8cb12ea2-aed4-4d75-b041-ba297df3d2f2" }, - { - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51155", - "user_role_collection_id": "8cb12ea2-aed4-4d75-b041-ba297df3d2f2" - }, { "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165", "user_role_collection_id": "8cb12ea2-aed4-4d75-b041-ba297df3d2f2" @@ -83,10 +75,6 @@ "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51162", "user_role_collection_id": "a5b8b1de-7759-4620-9c87-6b6d74fb4fbc" }, - { - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51155", - "user_role_collection_id": "a5b8b1de-7759-4620-9c87-6b6d74fb4fbc" - }, { "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165", "user_role_collection_id": "a5b8b1de-7759-4620-9c87-6b6d74fb4fbc" @@ -115,24 +103,20 @@ "user_role_id": "95fe4014-4d1b-47af-a22e-72a12f9470db", "user_role_collection_id": "ec428950-8b64-4646-b336-28af869b5d73" }, - { - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51169", - "user_role_collection_id": "ec428950-8b64-4646-b336-28af869b5d73" - }, { "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51162", "user_role_collection_id": "ec428950-8b64-4646-b336-28af869b5d73" }, { - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51155", + "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165", "user_role_collection_id": "ec428950-8b64-4646-b336-28af869b5d73" }, { - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165", + "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51157", "user_role_collection_id": "ec428950-8b64-4646-b336-28af869b5d73" }, { - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51157", + "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51168", "user_role_collection_id": "ec428950-8b64-4646-b336-28af869b5d73" }, { @@ -150,5 +134,37 @@ { "user_role_id": "34c42896-a003-4653-af8f-ba06ca595752", "user_role_collection_id": "916b09e7-7841-4e57-bdca-e0d3bd329c27" + }, + { + "user_role_collection_id": "1a24eca5-901f-4191-84a7-4ef09a894575", + "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" + }, + { + "user_role_collection_id": "8cb12ea2-aed4-4d75-b041-ba297df3d2f2", + "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" + }, + { + "user_role_collection_id": "a5b8b1de-7759-4620-9c87-6b6d74fb4fbc", + "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" + }, + { + "user_role_collection_id": "ec428950-8b64-4646-b336-28af869b5d73", + "user_role_id": "3940f9b0-4393-4463-b659-15463098557b" + }, + { + "user_role_collection_id": "1a24eca5-901f-4191-84a7-4ef09a894575", + "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7" + }, + { + "user_role_collection_id": "8cb12ea2-aed4-4d75-b041-ba297df3d2f2", + "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7" + }, + { + "user_role_collection_id": "a5b8b1de-7759-4620-9c87-6b6d74fb4fbc", + "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7" + }, + { + "user_role_collection_id": "ec428950-8b64-4646-b336-28af869b5d73", + "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7" } ] diff --git a/src/portalbackend/PortalBackend.Migrations/Seeder/Data/user_role_descriptions.json b/src/portalbackend/PortalBackend.Migrations/Seeder/Data/user_role_descriptions.json index 643f6e7d8c..2f87928941 100644 --- a/src/portalbackend/PortalBackend.Migrations/Seeder/Data/user_role_descriptions.json +++ b/src/portalbackend/PortalBackend.Migrations/Seeder/Data/user_role_descriptions.json @@ -119,54 +119,94 @@ "language_short_name": "en", "description": "App Manager" }, - { - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51155", - "language_short_name": "de", - "description": "Hinzufügen, Ändern und Löschen von eigenen Digitalen Zwillingen" - }, - { - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51155", - "language_short_name": "en", - "description": "Add, Change and Delete own Digital Twins" - }, { "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51157", "language_short_name": "de", - "description": "Anzeigen und Ändern des Unternehmens-Wallets" + "description": "Technischer Benutzer zum Zugriff auf das eigene Wallet - VC abfragen, VC anfragen, VC speicher, etc." }, { "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51157", "language_short_name": "en", - "description": "View and modify own company wallet" + "description": "Technical user to access own company wallet - request VC, request VP, store VC, etc." }, { "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165", "language_short_name": "de", - "description": "Discovery Funktion EDC Endpoints" + "description": "TEchnischer Benutzer für Dataspace Discovery Endpunkte" }, { "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51165", "language_short_name": "en", - "description": "Discovery Function EDC Endpoints" + "description": "Technical user for dataspace discovery endpoints." }, { "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51168", "language_short_name": "de", - "description": "Service Management for Service Providers" + "description": "Technischer Benutzer zum Hinzufügen von Dienstangeboten, Aktivieren von Abonnementanfragen und Erstellen von verwalteten Connectorregistrierungen für Dritte." }, { "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51168", "language_short_name": "en", - "description": "Service Management for Service Providers" + "description": "Technical user to add offers; activate subscription requests and create managed connector registrations for 3rd parties." + }, + { + "user_role_id": "34c42896-a003-4653-af8f-ba06ca595752", + "language_short_name": "de", + "description": "Technischer Benutzer zur Erstellung von Registrierungen von Drittanbietern durch Onboarding von Dienstleistungsunternehmen." + }, + { + "user_role_id": "34c42896-a003-4653-af8f-ba06ca595752", + "language_short_name": "en", + "description": "Technical user to generate 3rd party registrations by onboarding service provider companies." + }, + { + "user_role_id": "a6b6a5b6-d7fe-42af-94ce-35c16b3ae538", + "language_short_name": "de", + "description": "Ermöglicht das Anzeigen und Hinzufügen von Geschäftspartnerdaten über das eigene Service gate." + }, + { + "user_role_id": "a6b6a5b6-d7fe-42af-94ce-35c16b3ae538", + "language_short_name": "en", + "description": "Allows to view and add business partner data via the owned service gate." + }, + { + "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51162", + "language_short_name": "de", + "description": "Anzeigen der in der Pool-Datenbank verfügbaren Geschäftspartnerdaten." + }, + { + "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51162", + "language_short_name": "en", + "description": "View business partner data available in the pool database." + }, + { + "user_role_id": "3940f9b0-4393-4463-b659-15463098557b", + "language_short_name": "de", + "description": "Technischer Benutzer zur Ansicht semantischer Modelle." + }, + { + "user_role_id": "3940f9b0-4393-4463-b659-15463098557b", + "language_short_name": "en", + "description": "Technical user to view semantic models." + }, + { + "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7", + "language_short_name": "de", + "description": "Technischer Benutzer für den Zugang zu den Mitgliedsinformationen von Catena-X." + }, + { + "user_role_id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7", + "language_short_name": "en", + "description": "Technical user to access catena-x membership information." }, { - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51169", + "user_role_id": "9956fa8d-e454-49ca-a3b1-83e2c106fe59", "language_short_name": "de", - "description": "App user profile for technical users of apps registered in the cx dataspace." + "description": "Anzeigen, hinzufügen und löschen von Geschäftspartnerdatensätzen aus dem Geschäftspartner-Datenpool." }, { - "user_role_id": "607818be-4978-41f4-bf63-fa8d2de51169", + "user_role_id": "9956fa8d-e454-49ca-a3b1-83e2c106fe59", "language_short_name": "en", - "description": "App user profile for technical users of apps registered in the cx dataspace." + "description": "View, add and delete business partner records from the business partner data pool." } ] diff --git a/src/portalbackend/PortalBackend.Migrations/Seeder/Data/user_roles.json b/src/portalbackend/PortalBackend.Migrations/Seeder/Data/user_roles.json index d251c0f1dc..ad0b3505d0 100644 --- a/src/portalbackend/PortalBackend.Migrations/Seeder/Data/user_roles.json +++ b/src/portalbackend/PortalBackend.Migrations/Seeder/Data/user_roles.json @@ -77,12 +77,6 @@ "offer_id": "9b957704-3505-4445-822c-d7ef80f27fcd", "last_editor_id": null }, - { - "id": "607818be-4978-41f4-bf63-fa8d2de51169", - "user_role": "App Tech User", - "offer_id": "0ffcb416-1101-4ba6-8d4a-a9dfa31745a4", - "last_editor_id": null - }, { "id": "9956fa8d-e454-49ca-a3b1-83e2c106fe59", "user_role": "BPDM Management", @@ -95,18 +89,12 @@ "offer_id": "0ffcb416-1101-4ba6-8d4a-a9dfa31745a4", "last_editor_id": null }, - { + { "id": "607818be-4978-41f4-bf63-fa8d2de51162", "user_role": "BPDM Pool", "offer_id": "0ffcb416-1101-4ba6-8d4a-a9dfa31745a4", "last_editor_id": null }, - { - "id": "607818be-4978-41f4-bf63-fa8d2de51155", - "user_role": "Connector User", - "offer_id": "0ffcb416-1101-4ba6-8d4a-a9dfa31745a4", - "last_editor_id": null - }, { "id": "607818be-4978-41f4-bf63-fa8d2de51165", "user_role": "Dataspace Discovery", @@ -127,7 +115,19 @@ }, { "id": "607818be-4978-41f4-bf63-fa8d2de51168", - "user_role": "Service Management", + "user_role": "Offer Management", + "offer_id": "0ffcb416-1101-4ba6-8d4a-a9dfa31745a4", + "last_editor_id": null + }, + { + "id": "3940f9b0-4393-4463-b659-15463098557b", + "user_role": "Semantic Model Management", + "offer_id": "0ffcb416-1101-4ba6-8d4a-a9dfa31745a4", + "last_editor_id": null + }, + { + "id": "ec3a3005-b59c-4319-a8eb-3228014cd6e7", + "user_role": "CX Membership Info", "offer_id": "0ffcb416-1101-4ba6-8d4a-a9dfa31745a4", "last_editor_id": null } diff --git a/src/portalbackend/PortalBackend.PortalEntities/AuditEntities/AuditOfferSubscription20231013.cs b/src/portalbackend/PortalBackend.PortalEntities/AuditEntities/AuditOfferSubscription20231013.cs new file mode 100644 index 0000000000..a39272a034 --- /dev/null +++ b/src/portalbackend/PortalBackend.PortalEntities/AuditEntities/AuditOfferSubscription20231013.cs @@ -0,0 +1,84 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 BMW Group AG + * Copyright (c) 2021, 2023 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.PortalBackend.PortalEntities.Auditing; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; +using System.ComponentModel.DataAnnotations; + +namespace Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.AuditEntities; + +/// +/// Audit entity for relationship between companies and apps. +/// +public class AuditOfferSubscription20231013 : IAuditEntityV1 +{ + /// + [Key] + public Guid AuditV1Id { get; set; } + + /// + public Guid Id { get; set; } + + /// + /// ID of the company subscribing an app. + /// + public Guid CompanyId { get; set; } + + /// + /// ID of the apps subscribed by a company. + /// + public Guid OfferId { get; set; } + + /// + /// ID of the app subscription status. + /// + public OfferSubscriptionStatusId OfferSubscriptionStatusId { get; set; } + + /// + /// Display Name for the company app combination + /// + public string? DisplayName { get; set; } + + /// + /// Additional description for clarification + /// + public string? Description { get; set; } + + /// + /// Id of the app requester + /// + public Guid RequesterId { get; set; } + + public Guid? LastEditorId { get; set; } + + public Guid? ProcessId { get; set; } + + public DateTimeOffset DateCreated { get; private set; } + + /// + public Guid? AuditV1LastEditorId { get; set; } + + /// + public DateTimeOffset AuditV1DateLastChanged { get; set; } + + /// + public AuditOperationId AuditV1OperationId { get; set; } +} diff --git a/src/portalbackend/PortalBackend.PortalEntities/Entities/OfferSubscription.cs b/src/portalbackend/PortalBackend.PortalEntities/Entities/OfferSubscription.cs index dc66d8eb75..f8fb6c83ca 100644 --- a/src/portalbackend/PortalBackend.PortalEntities/Entities/OfferSubscription.cs +++ b/src/portalbackend/PortalBackend.PortalEntities/Entities/OfferSubscription.cs @@ -29,7 +29,7 @@ namespace Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entit /// /// App subscription relationship between companies and apps. /// -[AuditEntityV1(typeof(AuditOfferSubscription20230317))] +[AuditEntityV1(typeof(AuditOfferSubscription20231013))] public class OfferSubscription : IAuditableV1, IBaseEntity { /// @@ -51,7 +51,8 @@ public OfferSubscription() /// app subscription status. /// Id of the requester /// Id of the editor - public OfferSubscription(Guid id, Guid offerId, Guid companyId, OfferSubscriptionStatusId offerSubscriptionStatusId, Guid requesterId) + /// DateCreated of an Subscription + public OfferSubscription(Guid id, Guid offerId, Guid companyId, OfferSubscriptionStatusId offerSubscriptionStatusId, Guid requesterId, DateTimeOffset dateCreated) : this() { Id = id; @@ -59,6 +60,7 @@ public OfferSubscription(Guid id, Guid offerId, Guid companyId, OfferSubscriptio CompanyId = companyId; OfferSubscriptionStatusId = offerSubscriptionStatusId; RequesterId = requesterId; + DateCreated = dateCreated; } /// @@ -101,6 +103,11 @@ public OfferSubscription(Guid id, Guid offerId, Guid companyId, OfferSubscriptio public Guid? ProcessId { get; set; } + /// + /// DateCreated of an Subscription + /// + public DateTimeOffset DateCreated { get; private set; } + // Navigation properties /// /// Subscribed app. diff --git a/src/portalbackend/PortalBackend.PortalEntities/Enums/ProcessStepTypeId.cs b/src/portalbackend/PortalBackend.PortalEntities/Enums/ProcessStepTypeId.cs index 97e33af41b..f7b649eaf2 100644 --- a/src/portalbackend/PortalBackend.PortalEntities/Enums/ProcessStepTypeId.cs +++ b/src/portalbackend/PortalBackend.PortalEntities/Enums/ProcessStepTypeId.cs @@ -65,5 +65,8 @@ public enum ProcessStepTypeId TRIGGER_CALLBACK_OSP_DECLINED = 204, RETRIGGER_CALLBACK_OSP_SUBMITTED = 205, RETRIGGER_CALLBACK_OSP_APPROVED = 206, - RETRIGGER_CALLBACK_OSP_DECLINED = 207 + RETRIGGER_CALLBACK_OSP_DECLINED = 207, + + // ServiceACcountSync + SYNCHRONIZE_SERVICE_ACCOUNTS = 300, } diff --git a/src/portalbackend/PortalBackend.PortalEntities/Enums/ProcessTypeid.cs b/src/portalbackend/PortalBackend.PortalEntities/Enums/ProcessTypeid.cs index 2826b55516..30fd4f8b17 100644 --- a/src/portalbackend/PortalBackend.PortalEntities/Enums/ProcessTypeid.cs +++ b/src/portalbackend/PortalBackend.PortalEntities/Enums/ProcessTypeid.cs @@ -25,4 +25,5 @@ public enum ProcessTypeId APPLICATION_CHECKLIST = 1, OFFER_SUBSCRIPTION = 3, PARTNER_REGISTRATION = 4, + SERVICE_ACCOUNT_SYNC = 5 } diff --git a/src/portalbackend/PortalBackend.PortalEntities/PortalDbContext.cs b/src/portalbackend/PortalBackend.PortalEntities/PortalDbContext.cs index dfe89a54b5..33fab83f1c 100644 --- a/src/portalbackend/PortalBackend.PortalEntities/PortalDbContext.cs +++ b/src/portalbackend/PortalBackend.PortalEntities/PortalDbContext.cs @@ -72,6 +72,7 @@ public PortalDbContext(DbContextOptions options, IAuditHandler public virtual DbSet AuditOffer20230406 { get; set; } = default!; public virtual DbSet AuditOfferSubscription20221005 { get; set; } = default!; public virtual DbSet AuditOfferSubscription20230317 { get; set; } = default!; + public virtual DbSet AuditOfferSubscription20231013 { get; set; } = default!; public virtual DbSet AuditCompanyApplication20221005 { get; set; } = default!; public virtual DbSet AuditCompanyApplication20230214 { get; set; } = default!; public virtual DbSet AuditCompanyApplication20230824 { get; set; } = default!; @@ -311,7 +312,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) j.Property(e => e.OfferSubscriptionStatusId) .HasDefaultValue(OfferSubscriptionStatusId.PENDING); - j.HasAuditV1Triggers(); + j.HasAuditV1Triggers(); } ); diff --git a/src/processes/ApplicationChecklist.Config/ApplicationChecklistExtensions.cs b/src/processes/ApplicationChecklist.Config/ApplicationChecklistExtensions.cs index 1b25a887cb..f0c60d92c9 100644 --- a/src/processes/ApplicationChecklist.Config/ApplicationChecklistExtensions.cs +++ b/src/processes/ApplicationChecklist.Config/ApplicationChecklistExtensions.cs @@ -31,20 +31,16 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Processes.ApplicationChecklist.Con public static class ApplicationChecklistExtensions { - public static IServiceCollection AddApplicationChecklist(this IServiceCollection services, IConfigurationSection section) - { - return services + public static IServiceCollection AddApplicationChecklist(this IServiceCollection services, IConfigurationSection section) => + services .AddTransient() .AddTransient() .AddBpdmService(section.GetSection("Bpdm")) .AddCustodianService(section.GetSection("Custodian")) .AddClearinghouseService(section.GetSection("Clearinghouse")) .AddSdFactoryService(section.GetSection("SdFactory")); - } - public static IServiceCollection AddApplicationChecklistCreation(this IServiceCollection services) - { - return services + public static IServiceCollection AddApplicationChecklistCreation(this IServiceCollection services) => + services .AddTransient(); - } } diff --git a/src/processes/NetworkRegistration.Library/DependencyInjection/NetworkRegistrationHandlerExtensions.cs b/src/processes/NetworkRegistration.Library/DependencyInjection/NetworkRegistrationHandlerExtensions.cs index 5adc8ae9f1..fd1bdb32dd 100644 --- a/src/processes/NetworkRegistration.Library/DependencyInjection/NetworkRegistrationHandlerExtensions.cs +++ b/src/processes/NetworkRegistration.Library/DependencyInjection/NetworkRegistrationHandlerExtensions.cs @@ -1,5 +1,4 @@ /******************************************************************************** - * Copyright (c) 2021, 2023 BMW Group AG * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional @@ -32,6 +31,9 @@ public class NetworkRegistrationProcessSettings [Required] [DistinctValues("x => x.ClientId")] public IEnumerable InitialRoles { get; set; } = null!; + + [Required(AllowEmptyStrings = false)] + public string BasePortalAddress { get; set; } = null!; } public static class NetworkRegistrationHandlerExtensions @@ -41,6 +43,7 @@ public static IServiceCollection AddNetworkRegistrationHandler(this IServiceColl var section = config.GetSection("NetworkRegistration"); services.AddOptions() .Bind(section) + .ValidateDataAnnotations() .ValidateDistinctValues(section) .ValidateOnStart(); diff --git a/src/processes/NetworkRegistration.Library/INetworkRegistrationHandler.cs b/src/processes/NetworkRegistration.Library/INetworkRegistrationHandler.cs index 4f4133fb06..f562464594 100644 --- a/src/processes/NetworkRegistration.Library/INetworkRegistrationHandler.cs +++ b/src/processes/NetworkRegistration.Library/INetworkRegistrationHandler.cs @@ -1,5 +1,4 @@ /******************************************************************************** - * Copyright (c) 2021, 2023 BMW Group AG * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional diff --git a/src/processes/NetworkRegistration.Library/INetworkRegistrationProcessHelper.cs b/src/processes/NetworkRegistration.Library/INetworkRegistrationProcessHelper.cs index 413d60a6ec..8c014ee160 100644 --- a/src/processes/NetworkRegistration.Library/INetworkRegistrationProcessHelper.cs +++ b/src/processes/NetworkRegistration.Library/INetworkRegistrationProcessHelper.cs @@ -1,5 +1,4 @@ /******************************************************************************** - * Copyright (c) 2021, 2023 BMW Group AG * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional diff --git a/src/processes/NetworkRegistration.Library/Models/UserMailInformation.cs b/src/processes/NetworkRegistration.Library/Models/UserMailInformation.cs new file mode 100644 index 0000000000..d07af71a83 --- /dev/null +++ b/src/processes/NetworkRegistration.Library/Models/UserMailInformation.cs @@ -0,0 +1,24 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 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.Collections.Generic; + +namespace Org.Eclipse.TractusX.Portal.Backend.Processes.NetworkRegistration.Library.Models; + +public record UserMailInformation(string Email, string? FirstName, string? LastName, IEnumerable IdpAliasse); diff --git a/src/processes/NetworkRegistration.Library/NetworkRegistration.Library.csproj b/src/processes/NetworkRegistration.Library/NetworkRegistration.Library.csproj index 4db5590cf9..9babed5eed 100644 --- a/src/processes/NetworkRegistration.Library/NetworkRegistration.Library.csproj +++ b/src/processes/NetworkRegistration.Library/NetworkRegistration.Library.csproj @@ -29,6 +29,7 @@ + diff --git a/src/processes/NetworkRegistration.Library/NetworkRegistrationHandler.cs b/src/processes/NetworkRegistration.Library/NetworkRegistrationHandler.cs index ce2df221d0..fa1bcb6729 100644 --- a/src/processes/NetworkRegistration.Library/NetworkRegistrationHandler.cs +++ b/src/processes/NetworkRegistration.Library/NetworkRegistrationHandler.cs @@ -1,5 +1,4 @@ /******************************************************************************** - * Copyright (c) 2021, 2023 BMW Group AG * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional @@ -20,10 +19,12 @@ using Microsoft.Extensions.Options; using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; +using Org.Eclipse.TractusX.Portal.Backend.Mailing.SendMail; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; using Org.Eclipse.TractusX.Portal.Backend.Processes.NetworkRegistration.Library.DependencyInjection; +using Org.Eclipse.TractusX.Portal.Backend.Processes.NetworkRegistration.Library.Models; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Models; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Service; @@ -36,16 +37,19 @@ public class NetworkRegistrationHandler : INetworkRegistrationHandler private readonly IUserProvisioningService _userProvisioningService; private readonly IProvisioningManager _provisioningManager; private readonly NetworkRegistrationProcessSettings _settings; + private readonly IMailingService _mailingService; public NetworkRegistrationHandler( IPortalRepositories portalRepositories, IUserProvisioningService userProvisioningService, IProvisioningManager provisioningManager, + IMailingService mailingService, IOptions options) { _portalRepositories = portalRepositories; _userProvisioningService = userProvisioningService; _provisioningManager = provisioningManager; + _mailingService = mailingService; _settings = options.Value; } @@ -53,6 +57,13 @@ public NetworkRegistrationHandler( public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> SynchronizeUser(Guid networkRegistrationId) { var userRepository = _portalRepositories.GetInstance(); + var userRoleRepository = _portalRepositories.GetInstance(); + var ospName = await _portalRepositories.GetInstance().GetOspCompanyName(networkRegistrationId).ConfigureAwait(false); + if (string.IsNullOrWhiteSpace(ospName)) + { + throw new UnexpectedConditionException("Onboarding Service Provider name must be set"); + } + var companyAssignedIdentityProviders = await userRepository .GetUserAssignedIdentityProviderForNetworkRegistration(networkRegistrationId) .ToListAsync() @@ -75,19 +86,25 @@ public NetworkRegistrationHandler( try { - var userId = await _provisioningManager.GetUserByUserName(cu.CompanyUserId.ToString()).ConfigureAwait(false) ?? - await _userProvisioningService.CreateCentralUserWithProviderLinks(cu.CompanyUserId, new UserCreationRoleDataIdpInfo(cu.FirstName!, cu.LastName!, cu.Email!, roleData, string.Empty, string.Empty, UserStatusId.ACTIVE, true), cu.CompanyName, cu.Bpn, cu.ProviderLinkData.Select(x => new IdentityProviderLink(x.Alias!, x.ProviderUserId, x.UserName))); + var userId = await _provisioningManager.GetUserByUserName(cu.CompanyUserId.ToString()).ConfigureAwait(false); + if (!string.IsNullOrWhiteSpace(userId)) + { + userRepository.AttachAndModifyIdentity(cu.CompanyUserId, i => + { + i.UserStatusId = UserStatusId.PENDING; + i.UserEntityId = null; + }, + i => + { + i.UserStatusId = UserStatusId.ACTIVE; + i.UserEntityId = userId; + }); - userRepository.AttachAndModifyIdentity(cu.CompanyUserId, i => - { - i.UserStatusId = UserStatusId.PENDING; - i.UserEntityId = null; - }, - i => - { - i.UserStatusId = UserStatusId.ACTIVE; - i.UserEntityId = userId; - }); + await _userProvisioningService.AssignRolesToNewUserAsync(userRoleRepository, roleData, (userId, cu.CompanyUserId)).ConfigureAwait(false); + continue; + } + + await _userProvisioningService.HandleCentralKeycloakCreation(new UserCreationRoleDataIdpInfo(cu.FirstName!, cu.LastName!, cu.Email!, roleData, string.Empty, string.Empty, UserStatusId.ACTIVE, true), cu.CompanyUserId, cu.CompanyName, cu.Bpn, null, cu.ProviderLinkData.Select(x => new IdentityProviderLink(x.Alias!, x.ProviderUserId, x.UserName)), userRepository, userRoleRepository).ConfigureAwait(false); } catch (Exception e) { @@ -95,10 +112,29 @@ public NetworkRegistrationHandler( } } + await SendMails(companyAssignedIdentityProviders.Select(x => new UserMailInformation(x.Email!, x.FirstName, x.LastName, x.ProviderLinkData.Select(pld => pld.Alias!))), ospName).ConfigureAwait(false); return new ValueTuple?, ProcessStepStatusId, bool, string?>( null, ProcessStepStatusId.DONE, false, null); } + + private async Task SendMails(IEnumerable companyUserWithRoleIdForCompany, string ospName) + { + var templates = Enumerable.Repeat("OspWelcomeMail", 1); + foreach (var (receiver, firstName, lastName, idpAliasse) in companyUserWithRoleIdForCompany) + { + var userName = string.Join(" ", firstName, lastName); + var mailParameters = new Dictionary + { + { "userName", !string.IsNullOrWhiteSpace(userName) ? userName : receiver }, + { "hostname", _settings.BasePortalAddress }, + { "osp", ospName }, + { "url", _settings.BasePortalAddress }, + { "idpalias", string.Join(",", idpAliasse) } + }; + await _mailingService.SendMails(receiver, mailParameters, templates).ConfigureAwait(false); + } + } } diff --git a/src/processes/NetworkRegistration.Library/NetworkRegistrationProcessHelper.cs b/src/processes/NetworkRegistration.Library/NetworkRegistrationProcessHelper.cs index afd1380dd2..c5c968c5aa 100644 --- a/src/processes/NetworkRegistration.Library/NetworkRegistrationProcessHelper.cs +++ b/src/processes/NetworkRegistration.Library/NetworkRegistrationProcessHelper.cs @@ -1,5 +1,4 @@ /******************************************************************************** - * Copyright (c) 2021, 2023 BMW Group AG * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional @@ -20,7 +19,6 @@ using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess; -using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; using Org.Eclipse.TractusX.Portal.Backend.Processes.Library; diff --git a/src/processes/Processes.Worker/Processes.Worker.csproj b/src/processes/Processes.Worker/Processes.Worker.csproj index 595b6509d0..8756f5801d 100644 --- a/src/processes/Processes.Worker/Processes.Worker.csproj +++ b/src/processes/Processes.Worker/Processes.Worker.csproj @@ -51,6 +51,7 @@ + diff --git a/src/processes/Processes.Worker/Program.cs b/src/processes/Processes.Worker/Program.cs index 272f337e2b..39b57820d2 100644 --- a/src/processes/Processes.Worker/Program.cs +++ b/src/processes/Processes.Worker/Program.cs @@ -32,6 +32,7 @@ using Org.Eclipse.TractusX.Portal.Backend.Processes.ApplicationChecklist.Executor; using Org.Eclipse.TractusX.Portal.Backend.Processes.NetworkRegistration.Executor.DependencyInjection; using Org.Eclipse.TractusX.Portal.Backend.Processes.OfferSubscription.Executor.DependencyInjection; +using Org.Eclipse.TractusX.Portal.Backend.Processes.ServiceAccountSync.Executor.DependencyInjection; using Org.Eclipse.TractusX.Portal.Backend.Processes.Worker.Library; using Serilog; @@ -54,7 +55,8 @@ .AddApplicationChecklistCreation() .AddApplicationActivation(hostContext.Configuration) .AddProcessIdentity(hostContext.Configuration.GetSection("ProcessIdentity")) - .AddNetworkRegistrationProcessExecutor(hostContext.Configuration); + .AddNetworkRegistrationProcessExecutor(hostContext.Configuration) + .AddServiceAccountSyncProcessExecutor(hostContext.Configuration); if (hostContext.HostingEnvironment.IsDevelopment()) { diff --git a/src/processes/Processes.Worker/appsettings.json b/src/processes/Processes.Worker/appsettings.json index 73f2067f3a..4a138e27ab 100644 --- a/src/processes/Processes.Worker/appsettings.json +++ b/src/processes/Processes.Worker/appsettings.json @@ -353,6 +353,13 @@ "Subject": "Welcome to the Catena-X Network.", "EmailTemplateType": "PortalWelcomeEmail" } + }, + { + "Name": "OspWelcomeMail", + "Setting": { + "Subject": "Welcome to Catena-X - Your user account has been created.", + "EmailTemplateType": "OspWelcomeMail" + } } ], "Mail": { diff --git a/src/processes/ServiceAccountSync.Executor/DependencyInjection/ServiceAccountSyncProcessCollectionExtensions.cs b/src/processes/ServiceAccountSync.Executor/DependencyInjection/ServiceAccountSyncProcessCollectionExtensions.cs new file mode 100644 index 0000000000..b430f44559 --- /dev/null +++ b/src/processes/ServiceAccountSync.Executor/DependencyInjection/ServiceAccountSyncProcessCollectionExtensions.cs @@ -0,0 +1,34 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 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 Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Org.Eclipse.TractusX.Portal.Backend.Processes.ServiceACcountSync.Executor; +using Org.Eclipse.TractusX.Portal.Backend.Processes.Worker.Library; +using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library; + +namespace Org.Eclipse.TractusX.Portal.Backend.Processes.ServiceAccountSync.Executor.DependencyInjection; + +public static class ServiceAccountSyncProcessCollectionExtensions +{ + public static IServiceCollection AddServiceAccountSyncProcessExecutor(this IServiceCollection services, IConfiguration config) => + services + .AddTransient() + .AddProvisioningManager(config); +} diff --git a/src/processes/ServiceAccountSync.Executor/ServiceAccountSync.Executor.csproj b/src/processes/ServiceAccountSync.Executor/ServiceAccountSync.Executor.csproj new file mode 100644 index 0000000000..3edd3d63be --- /dev/null +++ b/src/processes/ServiceAccountSync.Executor/ServiceAccountSync.Executor.csproj @@ -0,0 +1,35 @@ + + + + + + Org.Eclipse.TractusX.Portal.Backend.Processes.ServiceAccountSync.Executor + Org.Eclipse.TractusX.Portal.Backend.Processes.ServiceAccountSync.Executor + net7.0 + enable + enable + + + + + + + + diff --git a/src/processes/ServiceAccountSync.Executor/ServiceAccountSyncProcessTypeExecutor.cs b/src/processes/ServiceAccountSync.Executor/ServiceAccountSyncProcessTypeExecutor.cs new file mode 100644 index 0000000000..a32f652f22 --- /dev/null +++ b/src/processes/ServiceAccountSync.Executor/ServiceAccountSyncProcessTypeExecutor.cs @@ -0,0 +1,105 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 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; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; +using Org.Eclipse.TractusX.Portal.Backend.Processes.Worker.Library; +using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library; +using System.Collections.Immutable; + +namespace Org.Eclipse.TractusX.Portal.Backend.Processes.ServiceACcountSync.Executor; + +public class ServiceAccountSyncProcessTypeExecutor : IProcessTypeExecutor +{ + private readonly IPortalRepositories _portalRepositories; + private readonly IProvisioningManager _provisioningManager; + + private static readonly IEnumerable _executableProcessSteps = ImmutableArray.Create(ProcessStepTypeId.SYNCHRONIZE_SERVICE_ACCOUNTS); + + public ServiceAccountSyncProcessTypeExecutor(IPortalRepositories portalRepositories, IProvisioningManager provisioningManager) + { + _portalRepositories = portalRepositories; + _provisioningManager = provisioningManager; + } + + public ProcessTypeId GetProcessTypeId() => ProcessTypeId.SERVICE_ACCOUNT_SYNC; + public bool IsExecutableStepTypeId(ProcessStepTypeId processStepTypeId) => _executableProcessSteps.Contains(processStepTypeId); + public IEnumerable GetExecutableStepTypeIds() => _executableProcessSteps; + public ValueTask IsLockRequested(ProcessStepTypeId processStepTypeId) => new(false); + + public async ValueTask InitializeProcess(Guid processId, IEnumerable processStepTypeIds) + { + return await Task.FromResult(new IProcessTypeExecutor.InitializationResult(false, null)); + } + + public async ValueTask ExecuteProcessStep(ProcessStepTypeId processStepTypeId, IEnumerable processStepTypeIds, CancellationToken cancellationToken) + { + IEnumerable? nextStepTypeIds; + ProcessStepStatusId stepStatusId; + bool modified; + string? processMessage; + + try + { + (nextStepTypeIds, stepStatusId, modified, processMessage) = processStepTypeId switch + { + ProcessStepTypeId.SYNCHRONIZE_SERVICE_ACCOUNTS => await SynchonizeNextServiceAccount().ConfigureAwait(false), + _ => throw new UnexpectedConditionException($"unexpected processStepTypeId {processStepTypeId} for process {ProcessTypeId.SERVICE_ACCOUNT_SYNC}") + }; + } + catch (Exception ex) when (ex is not SystemException) + { + (stepStatusId, processMessage, nextStepTypeIds) = ProcessError(ex); + modified = true; + } + + return new IProcessTypeExecutor.StepExecutionResult(modified, stepStatusId, nextStepTypeIds, null, processMessage); + } + + private async Task<(IEnumerable? NextStepTypeIds, ProcessStepStatusId StepStatusId, bool Modified, string? ProcessMessage)> SynchonizeNextServiceAccount() + { + var userRepository = _portalRepositories.GetInstance(); + var serviceAccountIds = userRepository.GetNextServiceAccountsWithoutUserEntityId(); + await using var enumerator = serviceAccountIds.GetAsyncEnumerator(); + if (await enumerator.MoveNextAsync().ConfigureAwait(false)) + { + var (serviceAccountId, clientClientId) = enumerator.Current; + var userEntityId = await _provisioningManager.GetServiceAccountUserId(clientClientId).ConfigureAwait(false); + userRepository.AttachAndModifyIdentity(serviceAccountId, + i => + { + i.UserEntityId = null; + }, + i => + { + i.UserEntityId = userEntityId; + }); + var nextStepTypeIds = await enumerator.MoveNextAsync().ConfigureAwait(false) + ? Enumerable.Repeat(ProcessStepTypeId.SYNCHRONIZE_SERVICE_ACCOUNTS, 1) // in case there are further serviceAccounts eligible for sync reschedule the same stepTypeId + : null; + return (nextStepTypeIds, ProcessStepStatusId.DONE, true, $"synchronized serviceAccountId {serviceAccountId}, clientClientId {clientClientId} with userEntityId {userEntityId}"); + } + return (null, ProcessStepStatusId.DONE, false, "no serviceAccounts to synchronize found"); + } + + private static (ProcessStepStatusId StatusId, string? ProcessMessage, IEnumerable? nextSteps) ProcessError(Exception ex) => + (ex is ServiceException { IsRecoverable: true } ? ProcessStepStatusId.TODO : ProcessStepStatusId.FAILED, ex.Message, null); +} diff --git a/src/provisioning/Provisioning.Library/Extensions/ServiceAccountManager.cs b/src/provisioning/Provisioning.Library/Extensions/ServiceAccountManager.cs index 4f9a841f8f..fb17416be9 100644 --- a/src/provisioning/Provisioning.Library/Extensions/ServiceAccountManager.cs +++ b/src/provisioning/Provisioning.Library/Extensions/ServiceAccountManager.cs @@ -20,6 +20,7 @@ using Org.Eclipse.TractusX.Portal.Backend.Keycloak.ErrorHandling; using Org.Eclipse.TractusX.Portal.Backend.Keycloak.Library; +using Org.Eclipse.TractusX.Portal.Backend.Keycloak.Library.Models.Users; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Enums; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Models; @@ -53,6 +54,16 @@ public async Task SetupCentralServiceAccountClientAsync(stri await GetCentralClientAuthDataAsync(internalClientId).ConfigureAwait(false)); } + public async Task GetServiceAccountUserId(string clientId) + { + var internalClientId = (await _CentralIdp.GetClientsAsync(_Settings.CentralRealm, clientId).ConfigureAwait(false)).FirstOrDefault(c => c.ClientId == clientId)?.Id; + if (internalClientId == null) + { + throw new KeycloakEntityNotFoundException($"clientId {clientId} not found on central idp"); + } + return (await _CentralIdp.GetUserForServiceAccountAsync(_Settings.CentralRealm, internalClientId).ConfigureAwait(false)).Id; + } + private async Task<(string ClientId, string Secret)> CreateSharedIdpServiceAccountAsync(string realm) { var sharedIdp = _Factory.CreateKeycloakClient("shared"); diff --git a/src/provisioning/Provisioning.Library/IProvisioningManager.cs b/src/provisioning/Provisioning.Library/IProvisioningManager.cs index 74208250f0..9385223ee4 100644 --- a/src/provisioning/Provisioning.Library/IProvisioningManager.cs +++ b/src/provisioning/Provisioning.Library/IProvisioningManager.cs @@ -42,6 +42,7 @@ public interface IProvisioningManager Task DeleteCentralRealmUserAsync(string userId); Task SetupClientAsync(string redirectUrl, string? baseUrl = null, IEnumerable? optionalRoleNames = null, bool enabled = true); Task SetupCentralServiceAccountClientAsync(string clientId, ClientConfigRolesData config, bool enabled); + Task GetServiceAccountUserId(string clientId); Task UpdateCentralClientAsync(string internalClientId, ClientConfigData config); Task DeleteCentralClientAsync(string internalClientId); Task UpdateClient(string clientId, string url, string redirectUrl); diff --git a/src/provisioning/Provisioning.Library/ProvisioningManager.cs b/src/provisioning/Provisioning.Library/ProvisioningManager.cs index de9212fe4f..7731efc384 100644 --- a/src/provisioning/Provisioning.Library/ProvisioningManager.cs +++ b/src/provisioning/Provisioning.Library/ProvisioningManager.cs @@ -54,7 +54,7 @@ public async Task SetupSharedIdpAsync(string idpName, string organisationName, s await CreateCentralIdentityProviderAsync(idpName, organisationName, _Settings.CentralIdentityProvider).ConfigureAwait(false); var (clientId, secret) = await CreateSharedIdpServiceAccountAsync(idpName).ConfigureAwait(false); - var sharedKeycloak = _Factory.CreateKeycloakClient("shared", clientId, secret, _Settings.UseAuthTrail); + var sharedKeycloak = _Factory.CreateKeycloakClient("shared", clientId, secret); await CreateSharedRealmAsync(sharedKeycloak, idpName, organisationName, loginTheme).ConfigureAwait(false); @@ -285,7 +285,7 @@ public async ValueTask UpdateCentralIdentityProviderDataSAMLAsync(IdentityProvid private async Task GetSharedKeycloakClient(string realm) { var (clientId, secret) = await GetSharedIdpServiceAccountSecretAsync(realm).ConfigureAwait(false); - return _Factory.CreateKeycloakClient("shared", clientId, secret, _Settings.UseAuthTrail); + return _Factory.CreateKeycloakClient("shared", clientId, secret); } private static T Clone(T cloneObject) diff --git a/src/provisioning/Provisioning.Library/ProvisioningSettings.cs b/src/provisioning/Provisioning.Library/ProvisioningSettings.cs index 94c1dd0b43..48cb445269 100644 --- a/src/provisioning/Provisioning.Library/ProvisioningSettings.cs +++ b/src/provisioning/Provisioning.Library/ProvisioningSettings.cs @@ -33,8 +33,6 @@ public partial class ProvisioningSettings public string MappedBpnAttribute { get; set; } public string UserNameMapperTemplate { get; set; } - - public bool UseAuthTrail { get; set; } } public static class ProvisioningSettingsExtension diff --git a/src/provisioning/Provisioning.Library/Service/IUserProvisioningService.cs b/src/provisioning/Provisioning.Library/Service/IUserProvisioningService.cs index f686052f71..3dc302b5db 100644 --- a/src/provisioning/Provisioning.Library/Service/IUserProvisioningService.cs +++ b/src/provisioning/Provisioning.Library/Service/IUserProvisioningService.cs @@ -22,7 +22,6 @@ using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities; -using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Models; namespace Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Service; @@ -30,10 +29,12 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Service; public interface IUserProvisioningService { IAsyncEnumerable<(Guid CompanyUserId, string UserName, string? Password, Exception? Error)> CreateOwnCompanyIdpUsersAsync(CompanyNameIdpAliasData companyNameIdpAliasData, IAsyncEnumerable userCreationInfos, CancellationToken cancellationToken = default); + 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 CreateCentralUserWithProviderLinks(Guid companyUserId, UserCreationRoleDataIdpInfo user, string companyName, string? businessPartnerNumber, IEnumerable identityProviderLinks); + Task<(Identity? identity, Guid companyUserId)> GetOrCreateCompanyUser(IUserRepository userRepository, string alias, UserCreationRoleDataIdpInfo user, Guid companyId, Guid identityProviderId, string? businessPartnerNumber); + Task AssignRolesToNewUserAsync(IUserRolesRepository userRolesRepository, IEnumerable roleDatas, (string UserEntityId, Guid CompanyUserId) userdata); } diff --git a/src/provisioning/Provisioning.Library/Service/ServiceAccountCreation.cs b/src/provisioning/Provisioning.Library/Service/ServiceAccountCreation.cs index 7c9d38d90f..aec5161329 100644 --- a/src/provisioning/Provisioning.Library/Service/ServiceAccountCreation.cs +++ b/src/provisioning/Provisioning.Library/Service/ServiceAccountCreation.cs @@ -105,7 +105,12 @@ public ServiceAccountCreation( await _provisioningManager.AddProtocolMapperAsync(serviceAccountData.InternalClientId).ConfigureAwait(false); } - var identity = _portalRepositories.GetInstance().CreateIdentity(companyId, UserStatusId.ACTIVE, IdentityTypeId.COMPANY_SERVICE_ACCOUNT); + var identity = _portalRepositories.GetInstance().CreateIdentity(companyId, UserStatusId.ACTIVE, IdentityTypeId.COMPANY_SERVICE_ACCOUNT, + i => + { + i.UserEntityId = serviceAccountData.UserEntityId; + }); + var serviceAccount = serviceAccountsRepository.CreateCompanyServiceAccount( identity.Id, enhancedName, diff --git a/src/provisioning/Provisioning.Library/Service/UserProvisioningService.cs b/src/provisioning/Provisioning.Library/Service/UserProvisioningService.cs index eb94a9db03..f2113807c4 100644 --- a/src/provisioning/Provisioning.Library/Service/UserProvisioningService.cs +++ b/src/provisioning/Provisioning.Library/Service/UserProvisioningService.cs @@ -36,6 +36,7 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Service; public class UserProvisioningService : IUserProvisioningService { + private static readonly IEnumerable ValidCompanyUserStatusIds = new[] { UserStatusId.ACTIVE, UserStatusId.INACTIVE, UserStatusId.PENDING }; private readonly IProvisioningManager _provisioningManager; private readonly IPortalRepositories _portalRepositories; @@ -68,35 +69,26 @@ public UserProvisioningService(IProvisioningManager provisioningManager, IPortal Exception? error = null; var nextPassword = passwordProvider.NextOptionalPassword(); - try { - var (identity, companyUserId) = await GetOrCreateCompanyUser(userRepository, alias, user, companyId, businessPartnerNumber); - - cancellationToken.ThrowIfCancellationRequested(); + var (identity, companyUserId) = await GetOrCreateCompanyUser(userRepository, alias, user, companyId, identityProviderId, businessPartnerNumber); - userRepository.AddCompanyUserAssignedIdentityProvider(companyUserId, identityProviderId, user.UserId, user.UserName); - var providerUserId = await CreateSharedIdpUserOrReturnUserId(user, alias, nextPassword, isSharedIdp).ConfigureAwait(false); - var centralUserId = await CreateCentralUserWithProviderLinks(companyUserId, user, companyName, businessPartnerNumber, Enumerable.Repeat(new IdentityProviderLink(alias, providerUserId, user.UserName), 1)); - userdata = new(centralUserId, companyUserId); - if (identity == null) + userdata.CompanyUserId = companyUserId; + if (!string.IsNullOrWhiteSpace(identity?.UserEntityId)) { - userRepository.AttachAndModifyIdentity(companyUserId, null, cu => - { - cu.UserEntityId = centralUserId; - }); - } - else - { - identity.UserEntityId = centralUserId; + userdata.UserEntityId = identity.UserEntityId; } - await AssignRolesToNewUserAsync(userRolesRepository, user.RoleDatas, userdata).ConfigureAwait(false); + cancellationToken.ThrowIfCancellationRequested(); + + var providerUserId = await CreateSharedIdpUserOrReturnUserId(user, alias, nextPassword, isSharedIdp).ConfigureAwait(false); + await HandleCentralKeycloakCreation(user, companyUserId, companyName, businessPartnerNumber, identity, Enumerable.Repeat(new IdentityProviderLink(alias, providerUserId, user.UserName), 1), userRepository, userRolesRepository).ConfigureAwait(false); } catch (Exception e) when (e is not OperationCanceledException) { error = e; } + if (userdata == default && error == null) { error = new UnexpectedConditionException($"failed to create companyUser for provider userid {user.UserId}, username {user.UserName} while not throwing any error"); @@ -108,7 +100,27 @@ public UserProvisioningService(IProvisioningManager provisioningManager, IPortal } } - public async Task CreateCentralUserWithProviderLinks(Guid companyUserId, UserCreationRoleDataIdpInfo user, string companyName, string? businessPartnerNumber, IEnumerable identityProviderLinks) + public async Task HandleCentralKeycloakCreation(UserCreationRoleDataIdpInfo user, Guid companyUserId, string companyName, string? businessPartnerNumber, Identity? identity, IEnumerable identityProviderLinks, IUserRepository userRepository, IUserRolesRepository userRolesRepository) + { + var centralUserId = await CreateCentralUserWithProviderLinks(companyUserId, user, companyName, businessPartnerNumber, identityProviderLinks).ConfigureAwait(false); + if (identity == null) + { + userRepository.AttachAndModifyIdentity(companyUserId, null, cu => + { + cu.UserEntityId = centralUserId; + cu.UserStatusId = user.UserStatusId; + }); + } + else + { + identity.UserEntityId = centralUserId; + identity.UserStatusId = user.UserStatusId; + } + + await AssignRolesToNewUserAsync(userRolesRepository, user.RoleDatas, (centralUserId, companyUserId)).ConfigureAwait(false); + } + + private async Task CreateCentralUserWithProviderLinks(Guid companyUserId, UserCreationRoleDataIdpInfo user, string companyName, string? businessPartnerNumber, IEnumerable identityProviderLinks) { var centralUserId = await _provisioningManager.CreateCentralUserAsync( new UserProfile( @@ -133,11 +145,12 @@ await _provisioningManager.AddProviderUserLinkToCentralUserAsync(centralUserId, return centralUserId; } - private async Task<(Identity? identity, Guid companyUserId)> GetOrCreateCompanyUser( + public async Task<(Identity? identity, Guid companyUserId)> GetOrCreateCompanyUser( IUserRepository userRepository, string alias, UserCreationRoleDataIdpInfo user, Guid companyId, + Guid identityProviderId, string? businessPartnerNumber) { var businessPartnerRepository = _portalRepositories.GetInstance(); @@ -149,13 +162,15 @@ await _provisioningManager.AddProviderUserLinkToCentralUserAsync(centralUserId, return (identity, companyUserId); } - identity = userRepository.CreateIdentity(companyId, user.UserStatusId, IdentityTypeId.COMPANY_USER); + identity = userRepository.CreateIdentity(companyId, user.UserStatusId, IdentityTypeId.COMPANY_USER, null); companyUserId = userRepository.CreateCompanyUser(identity.Id, user.FirstName, user.LastName, user.Email).Id; if (businessPartnerNumber != null) { businessPartnerRepository.CreateCompanyUserAssignedBusinessPartner(companyUserId, businessPartnerNumber); } + userRepository.AddCompanyUserAssignedIdentityProvider(companyUserId, identityProviderId, user.UserId, user.UserName); + return (identity, companyUserId); } @@ -191,6 +206,7 @@ private Task CreateSharedIdpUserOrReturnUserId(UserCreationRoleDataIdpIn { throw new ControllerArgumentException($"user {companyUserId} does not exist"); } + var (company, companyUser, identityProvider) = result; if (identityProvider.IdpAlias == null) { @@ -216,15 +232,18 @@ private Task CreateSharedIdpUserOrReturnUserId(UserCreationRoleDataIdpIn ? new ControllerArgumentException($"user {companyUserId} does not exist") : new ControllerArgumentException($"user {companyUserId} is not associated with application {applicationId}"); } + var (company, companyUser, idpAliase) = result; if (company.CompanyName == null) { throw new ConflictException($"assertion failed: companyName of company {company.CompanyId} should never be null here"); } + if (!idpAliase.Any()) { throw new ConflictException($"user {companyUserId} is not associated with any shared idp"); } + if (idpAliase.Count() > 1) { throw new ConflictException($"user {companyUserId} is associated with more than one shared idp"); @@ -243,14 +262,17 @@ private static string CreateNameString(string? firstName, string? lastName, stri { sb.Append(firstName); } + if (lastName != null) { sb.AppendFormat((firstName == null ? "{0}" : ", {0}"), lastName); } + if (email != null) { sb.AppendFormat((firstName == null && lastName == null) ? "{0}" : " ({0})", email); } + return firstName == null && lastName == null && email == null ? "Dear User" : sb.ToString(); } @@ -261,9 +283,7 @@ private async Task ValidateDuplicateIdpUsersAsync(IUserRepository userRepo { var existingCompanyUserId = Guid.Empty; - var validCompanyUserStatusIds = new[] { UserStatusId.ACTIVE, UserStatusId.INACTIVE }; - - await foreach (var (userEntityId, companyUserId) in userRepository.GetMatchingCompanyIamUsersByNameEmail(user.FirstName, user.LastName, user.Email, companyId, validCompanyUserStatusIds).ConfigureAwait(false)) + await foreach (var (userEntityId, companyUserId) in userRepository.GetMatchingCompanyIamUsersByNameEmail(user.FirstName, user.LastName, user.Email, companyId, ValidCompanyUserStatusIds).ConfigureAwait(false)) { if (userEntityId == null) { @@ -271,8 +291,10 @@ private async Task ValidateDuplicateIdpUsersAsync(IUserRepository userRepo { existingCompanyUserId = companyUserId; } + continue; } + try { if (await _provisioningManager.GetProviderUserLinkDataForCentralUserIdAsync(userEntityId).AnyAsync(link => @@ -286,10 +308,11 @@ private async Task ValidateDuplicateIdpUsersAsync(IUserRepository userRepo // when searching for duplicates this is not a validation-error } } + return existingCompanyUserId; } - private async Task AssignRolesToNewUserAsync(IUserRolesRepository userRolesRepository, IEnumerable roleDatas, (string UserEntityId, Guid CompanyUserId) userdata) + public async Task AssignRolesToNewUserAsync(IUserRolesRepository userRolesRepository, IEnumerable roleDatas, (string UserEntityId, Guid CompanyUserId) userdata) { if (roleDatas.Any()) { @@ -304,6 +327,7 @@ private async Task AssignRolesToNewUserAsync(IUserRolesRepository userRolesRepos var roleId = roleDatas.First(roleInfo => roleInfo.ClientClientId == assigned.Client && roleInfo.UserRoleText == role).UserRoleId; userRolesRepository.CreateIdentityAssignedRole(userdata.CompanyUserId, roleId); } + messages.AddRange(clientRoleNames[assigned.Client].Except(assigned.Roles).Select(roleName => $"clientId: {assigned.Client}, role: {roleName}")); } diff --git a/src/registration/Registration.Service/BusinessLogic/INetworkBusinessLogic.cs b/src/registration/Registration.Service/BusinessLogic/INetworkBusinessLogic.cs new file mode 100644 index 0000000000..e2ccf31488 --- /dev/null +++ b/src/registration/Registration.Service/BusinessLogic/INetworkBusinessLogic.cs @@ -0,0 +1,27 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 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.Registration.Service.Model; + +namespace Org.Eclipse.TractusX.Portal.Backend.Registration.Service.BusinessLogic; + +public interface INetworkBusinessLogic +{ + Task Submit(PartnerSubmitData submitData); +} diff --git a/src/registration/Registration.Service/BusinessLogic/IRegistrationBusinessLogic.cs b/src/registration/Registration.Service/BusinessLogic/IRegistrationBusinessLogic.cs index 0d10101730..01e67538c5 100644 --- a/src/registration/Registration.Service/BusinessLogic/IRegistrationBusinessLogic.cs +++ b/src/registration/Registration.Service/BusinessLogic/IRegistrationBusinessLogic.cs @@ -29,31 +29,30 @@ public interface IRegistrationBusinessLogic { Task GetCompanyBpdmDetailDataByBusinessPartnerNumber(string businessPartnerNumber, string token, CancellationToken cancellationToken); IAsyncEnumerable GetClientRolesCompositeAsync(); - Task UploadDocumentAsync(Guid applicationId, IFormFile document, DocumentTypeId documentTypeId, (Guid UserId, Guid CompanyId) identity, CancellationToken cancellationToken); + Task UploadDocumentAsync(Guid applicationId, IFormFile document, DocumentTypeId documentTypeId, CancellationToken cancellationToken); /// /// Gets the file content from the persistence store for the given user /// /// The Id of the document that should be get - /// The Identity of the current user /// - Task<(string FileName, byte[] Content, string MediaType)> GetDocumentContentAsync(Guid documentId, Guid userId); + Task<(string FileName, byte[] Content, string MediaType)> GetDocumentContentAsync(Guid documentId); - IAsyncEnumerable GetAllApplicationsForUserWithStatus(Guid companyId); - Task GetCompanyDetailData(Guid applicationId, Guid companyId); - Task SetCompanyDetailDataAsync(Guid applicationId, CompanyDetailData companyDetails, Guid companyId); - Task InviteNewUserAsync(Guid applicationId, UserCreationInfoWithMessage userCreationInfo, (Guid UserId, Guid CompanyId) identity); - Task SetOwnCompanyApplicationStatusAsync(Guid applicationId, CompanyApplicationStatusId status, Guid companyId); - Task GetOwnCompanyApplicationStatusAsync(Guid applicationId, Guid companyId); - Task SubmitRoleConsentAsync(Guid applicationId, CompanyRoleAgreementConsents roleAgreementConsentStatuses, Guid userId, Guid companyId); - Task GetRoleAgreementConsentsAsync(Guid applicationId, Guid userId); + IAsyncEnumerable GetAllApplicationsForUserWithStatus(); + Task GetCompanyDetailData(Guid applicationId); + Task SetCompanyDetailDataAsync(Guid applicationId, CompanyDetailData companyDetails); + Task InviteNewUserAsync(Guid applicationId, UserCreationInfoWithMessage userCreationInfo); + Task SetOwnCompanyApplicationStatusAsync(Guid applicationId, CompanyApplicationStatusId status); + Task GetOwnCompanyApplicationStatusAsync(Guid applicationId); + Task SubmitRoleConsentAsync(Guid applicationId, CompanyRoleAgreementConsents roleAgreementConsentStatuses); + Task GetRoleAgreementConsentsAsync(Guid applicationId); Task GetCompanyRoleAgreementDataAsync(); - Task SubmitRegistrationAsync(Guid applicationId, Guid userId); + Task SubmitRegistrationAsync(Guid applicationId); IAsyncEnumerable GetInvitedUsersAsync(Guid applicationId); - Task> GetUploadedDocumentsAsync(Guid applicationId, DocumentTypeId documentTypeId, Guid userId); - Task SetInvitationStatusAsync(Guid userId); - Task GetRegistrationDataAsync(Guid applicationId, Guid companyId); - Task DeleteRegistrationDocumentAsync(Guid documentId, Guid companyId); + Task> GetUploadedDocumentsAsync(Guid applicationId, DocumentTypeId documentTypeId); + Task SetInvitationStatusAsync(); + Task GetRegistrationDataAsync(Guid applicationId); + Task DeleteRegistrationDocumentAsync(Guid documentId); IAsyncEnumerable GetCompanyRoles(string? languageShortName = null); Task> GetCompanyIdentifiers(string alpha2Code); Task<(string fileName, byte[] content, string mediaType)> GetRegistrationDocumentAsync(Guid documentId); diff --git a/src/registration/Registration.Service/BusinessLogic/NetworkBusinessLogic.cs b/src/registration/Registration.Service/BusinessLogic/NetworkBusinessLogic.cs new file mode 100644 index 0000000000..b4c535f7c0 --- /dev/null +++ b/src/registration/Registration.Service/BusinessLogic/NetworkBusinessLogic.cs @@ -0,0 +1,111 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 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.Framework.Linq; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities; +using Org.Eclipse.TractusX.Portal.Backend.Processes.ApplicationChecklist.Library; +using Org.Eclipse.TractusX.Portal.Backend.Registration.Service.Model; +using System.Collections.Immutable; + +namespace Org.Eclipse.TractusX.Portal.Backend.Registration.Service.BusinessLogic; + +public class NetworkBusinessLogic : INetworkBusinessLogic +{ + private readonly IPortalRepositories _portalRepositories; + private readonly IIdentityService _identityService; + private readonly IApplicationChecklistCreationService _checklistService; + + public NetworkBusinessLogic(IPortalRepositories portalRepositories, IIdentityService identityService, IApplicationChecklistCreationService checklistService) + { + _portalRepositories = portalRepositories; + _identityService = identityService; + _checklistService = checklistService; + } + + public async Task Submit(PartnerSubmitData submitData) + { + var companyId = _identityService.IdentityData.CompanyId; + var userId = _identityService.IdentityData.UserId; + var data = await _portalRepositories.GetInstance() + .GetSubmitData(companyId) + .ConfigureAwait(false); + if (!data.Exists) + { + throw new NotFoundException($"Company {companyId} not found"); + } + + if (data.CompanyApplications.Count() != 1) + { + throw new ConflictException($"Company {companyId} has no or more than one application"); + } + + if (data.ProcessId == null) + { + throw new ConflictException("There must be an process"); + } + + var companyApplication = data.CompanyApplications.Single(); + if (companyApplication.CompanyApplicationStatusId != CompanyApplicationStatusId.CREATED) + { + throw new ConflictException($"Application {companyApplication.CompanyApplicationId} is not in state CREATED"); + } + + submitData.Agreements.Where(x => x.ConsentStatusId != ConsentStatusId.ACTIVE).IfAny(inactive => + throw new ControllerArgumentException($"All agreements must be agreed to. Agreements that are not active: {string.Join(",", inactive.Select(x => x.AgreementId))}", nameof(submitData.Agreements))); + + data.CompanyRoleAgreementIds + .ExceptBy(submitData.CompanyRoles, x => x.CompanyRoleId) + .IfAny(missing => + throw new ControllerArgumentException($"CompanyRoles {string.Join(",", missing.Select(x => x.CompanyRoleId))} are missing", nameof(submitData.CompanyRoles))); + + var requiredAgreementIds = data.CompanyRoleAgreementIds + .SelectMany(x => x.AgreementIds) + .Distinct().ToImmutableList(); + + requiredAgreementIds.Except(submitData.Agreements.Where(x => x.ConsentStatusId == ConsentStatusId.ACTIVE).Select(x => x.AgreementId)) + .IfAny(missing => + throw new ControllerArgumentException($"All Agreements for the company roles must be agreed to, missing agreementIds: {string.Join(",", missing)}", nameof(submitData.Agreements))); + + _portalRepositories.GetInstance() + .CreateConsents(requiredAgreementIds.Select(agreementId => (agreementId, companyId, userId, ConsentStatusId.ACTIVE))); + + var entries = await _checklistService.CreateInitialChecklistAsync(companyApplication.CompanyApplicationId); + var processId = _portalRepositories.GetInstance().CreateProcess(ProcessTypeId.APPLICATION_CHECKLIST).Id; + _portalRepositories.GetInstance() + .CreateProcessStepRange( + _checklistService + .GetInitialProcessStepTypeIds(entries) + .Select(processStepTypeId => (processStepTypeId, ProcessStepStatusId.TODO, processId)) + // in addition to the initial steps of new process application_checklist also create next step for process network_registration + .Append((ProcessStepTypeId.TRIGGER_CALLBACK_OSP_SUBMITTED, ProcessStepStatusId.TODO, data.ProcessId.Value))); + + _portalRepositories.GetInstance().AttachAndModifyCompanyApplication(companyApplication.CompanyApplicationId, + ca => + { + ca.ApplicationStatusId = CompanyApplicationStatusId.SUBMITTED; + ca.ChecklistProcessId = processId; + }); + + await _portalRepositories.SaveAsync().ConfigureAwait(false); + } +} diff --git a/src/registration/Registration.Service/BusinessLogic/RegistrationBusinessLogic.cs b/src/registration/Registration.Service/BusinessLogic/RegistrationBusinessLogic.cs index 3cb894e71a..9c90a73208 100644 --- a/src/registration/Registration.Service/BusinessLogic/RegistrationBusinessLogic.cs +++ b/src/registration/Registration.Service/BusinessLogic/RegistrationBusinessLogic.cs @@ -21,6 +21,7 @@ using Microsoft.Extensions.Options; using Org.Eclipse.TractusX.Portal.Backend.Bpdm.Library; using Org.Eclipse.TractusX.Portal.Backend.Bpdm.Library.Models; +using Org.Eclipse.TractusX.Portal.Backend.Framework.DateTimeProvider; using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Configuration; using Org.Eclipse.TractusX.Portal.Backend.Framework.Web; @@ -31,6 +32,7 @@ using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities; using Org.Eclipse.TractusX.Portal.Backend.Processes.ApplicationChecklist.Library; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Models; @@ -50,6 +52,8 @@ public class RegistrationBusinessLogic : IRegistrationBusinessLogic private readonly IPortalRepositories _portalRepositories; private readonly ILogger _logger; private readonly IApplicationChecklistCreationService _checklistService; + private readonly IIdentityService _identityService; + private readonly IDateTimeProvider _dateTimeProvider; private static readonly Regex bpnRegex = new(@"(\w|\d){16}", RegexOptions.None, TimeSpan.FromSeconds(1)); @@ -61,7 +65,9 @@ public RegistrationBusinessLogic( IUserProvisioningService userProvisioningService, ILogger logger, IPortalRepositories portalRepositories, - IApplicationChecklistCreationService checklistService) + IApplicationChecklistCreationService checklistService, + IIdentityService identityService, + IDateTimeProvider dateTimeProvider) { _settings = settings.Value; _mailingService = mailingService; @@ -71,6 +77,8 @@ public RegistrationBusinessLogic( _logger = logger; _portalRepositories = portalRepositories; _checklistService = checklistService; + _identityService = identityService; + _dateTimeProvider = dateTimeProvider; } public IAsyncEnumerable GetClientRolesCompositeAsync() => @@ -138,7 +146,7 @@ private async Task GetCompanyBpdmDetailDataByBusinessPart } } - public async Task UploadDocumentAsync(Guid applicationId, IFormFile document, DocumentTypeId documentTypeId, (Guid UserId, Guid CompanyId) identity, CancellationToken cancellationToken) + public async Task UploadDocumentAsync(Guid applicationId, IFormFile document, DocumentTypeId documentTypeId, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(document.FileName)) { @@ -156,12 +164,16 @@ public async Task UploadDocumentAsync(Guid applicationId, IFormFile documen throw new ControllerArgumentException($"documentType must be either: {string.Join(",", _settings.DocumentTypeIds)}"); } + var identity = _identityService.IdentityData; var validApplicationForCompany = await _portalRepositories.GetInstance().IsValidApplicationForCompany(applicationId, identity.CompanyId).ConfigureAwait(false); if (!validApplicationForCompany) { throw new ForbiddenException($"The users company is not assigned with application {applicationId}"); } - + _portalRepositories.GetInstance().AttachAndModifyCompanyApplication(applicationId, application => + { + application.DateLastChanged = _dateTimeProvider.OffsetNow; + }); var mediaTypeId = document.ContentType.ParseMediaTypeId(); var (content, hash) = await document.GetContentAndHash(cancellationToken).ConfigureAwait(false); @@ -172,10 +184,10 @@ public async Task UploadDocumentAsync(Guid applicationId, IFormFile documen return await _portalRepositories.SaveAsync().ConfigureAwait(false); } - public async Task<(string FileName, byte[] Content, string MediaType)> GetDocumentContentAsync(Guid documentId, Guid userId) + public async Task<(string FileName, byte[] Content, string MediaType)> GetDocumentContentAsync(Guid documentId) { var documentRepository = _portalRepositories.GetInstance(); - var documentDetails = await documentRepository.GetDocumentIdWithCompanyUserCheckAsync(documentId, userId).ConfigureAwait(false); + var documentDetails = await documentRepository.GetDocumentIdWithCompanyUserCheckAsync(documentId, _identityService.IdentityData.UserId).ConfigureAwait(false); if (documentDetails.DocumentId == Guid.Empty) { throw new NotFoundException($"document {documentId} does not exist."); @@ -194,12 +206,12 @@ public async Task UploadDocumentAsync(Guid applicationId, IFormFile documen return (document.DocumentName, document.DocumentContent, document.MediaTypeId.MapToMediaType()); } - public IAsyncEnumerable GetAllApplicationsForUserWithStatus(Guid companyId) => - _portalRepositories.GetInstance().GetApplicationsWithStatusUntrackedAsync(companyId); + public IAsyncEnumerable GetAllApplicationsForUserWithStatus() => + _portalRepositories.GetInstance().GetApplicationsWithStatusUntrackedAsync(_identityService.IdentityData.CompanyId); - public async Task GetCompanyDetailData(Guid applicationId, Guid companyId) + public async Task GetCompanyDetailData(Guid applicationId) { - var result = await _portalRepositories.GetInstance().GetCompanyApplicationDetailDataAsync(applicationId, companyId).ConfigureAwait(false); + var result = await _portalRepositories.GetInstance().GetCompanyApplicationDetailDataAsync(applicationId, _identityService.IdentityData.CompanyId).ConfigureAwait(false); if (result == null) { throw new NotFoundException($"CompanyApplication {applicationId} not found"); @@ -224,7 +236,7 @@ public async Task GetCompanyDetailData(Guid applicationId, Gu ); } - public Task SetCompanyDetailDataAsync(Guid applicationId, CompanyDetailData companyDetails, Guid companyId) + public Task SetCompanyDetailDataAsync(Guid applicationId, CompanyDetailData companyDetails) { if (string.IsNullOrWhiteSpace(companyDetails.Name)) { @@ -253,17 +265,17 @@ public Task SetCompanyDetailDataAsync(Guid applicationId, CompanyDetailData comp var duplicateIds = companyDetails.UniqueIds.Except(distinctIds); throw new ControllerArgumentException($"uniqueIds must not contain duplicate types: '{string.Join(", ", duplicateIds.Select(uniqueId => uniqueId.UniqueIdentifierId))}'", nameof(companyDetails.UniqueIds)); } - return SetCompanyDetailDataInternal(applicationId, companyDetails, companyId); + return SetCompanyDetailDataInternal(applicationId, companyDetails); } - private async Task SetCompanyDetailDataInternal(Guid applicationId, CompanyDetailData companyDetails, Guid companyId) + private async Task SetCompanyDetailDataInternal(Guid applicationId, CompanyDetailData companyDetails) { await ValidateCountryAssignedIdentifiers(companyDetails).ConfigureAwait(false); var applicationRepository = _portalRepositories.GetInstance(); var companyRepository = _portalRepositories.GetInstance(); - var companyApplicationData = await GetAndValidateApplicationData(applicationId, companyDetails, companyId, applicationRepository).ConfigureAwait(false); + var companyApplicationData = await GetAndValidateApplicationData(applicationId, companyDetails, applicationRepository).ConfigureAwait(false); var addressId = CreateOrModifyAddress(companyApplicationData, companyDetails, companyRepository); @@ -271,7 +283,7 @@ private async Task SetCompanyDetailDataInternal(Guid applicationId, CompanyDetai companyRepository.CreateUpdateDeleteIdentifiers(companyDetails.CompanyId, companyApplicationData.UniqueIds, companyDetails.UniqueIds.Select(x => (x.UniqueIdentifierId, x.Value))); - UpdateApplicationStatus(applicationId, companyApplicationData.ApplicationStatusId, UpdateApplicationSteps.CompanyWithAddress, applicationRepository); + UpdateApplicationStatus(applicationId, companyApplicationData.ApplicationStatusId, UpdateApplicationSteps.CompanyWithAddress, applicationRepository, _dateTimeProvider); await _portalRepositories.SaveAsync().ConfigureAwait(false); } @@ -298,10 +310,10 @@ private async Task ValidateCountryAssignedIdentifiers(CompanyDetailData companyD } } - private static async Task GetAndValidateApplicationData(Guid applicationId, CompanyDetailData companyDetails, Guid companyId, IApplicationRepository applicationRepository) + private async Task GetAndValidateApplicationData(Guid applicationId, CompanyDetailData companyDetails, IApplicationRepository applicationRepository) { var companyApplicationData = await applicationRepository - .GetCompanyApplicationDetailDataAsync(applicationId, companyId, companyDetails.CompanyId) + .GetCompanyApplicationDetailDataAsync(applicationId, _identityService.IdentityData.CompanyId, companyDetails.CompanyId) .ConfigureAwait(false); if (companyApplicationData == null) @@ -383,17 +395,18 @@ private static void ModifyCompany(Guid addressId, CompanyApplicationDetailData i c.AddressId = addressId; }); - public Task InviteNewUserAsync(Guid applicationId, UserCreationInfoWithMessage userCreationInfo, (Guid UserId, Guid CompanyId) identity) + public Task InviteNewUserAsync(Guid applicationId, UserCreationInfoWithMessage userCreationInfo) { if (string.IsNullOrEmpty(userCreationInfo.eMail)) { throw new ControllerArgumentException($"email must not be empty"); } - return InviteNewUserInternalAsync(applicationId, userCreationInfo, identity); + return InviteNewUserInternalAsync(applicationId, userCreationInfo); } - private async Task InviteNewUserInternalAsync(Guid applicationId, UserCreationInfoWithMessage userCreationInfo, (Guid UserId, Guid CompanyId) identity) + private async Task InviteNewUserInternalAsync(Guid applicationId, UserCreationInfoWithMessage userCreationInfo) { + var identity = _identityService.IdentityData; if (await _portalRepositories.GetInstance().IsOwnCompanyUserWithEmailExisting(userCreationInfo.eMail, identity.CompanyId)) { throw new ControllerArgumentException($"user with email {userCreationInfo.eMail} does already exist"); @@ -428,6 +441,10 @@ private async Task InviteNewUserInternalAsync(Guid applicationId, UserCreat } _portalRepositories.GetInstance().CreateInvitation(applicationId, newCompanyUserId); + _portalRepositories.GetInstance().AttachAndModifyCompanyApplication(applicationId, application => + { + application.DateLastChanged = _dateTimeProvider.OffsetNow; + }); var modified = await _portalRepositories.SaveAsync().ConfigureAwait(false); @@ -454,7 +471,7 @@ private async Task InviteNewUserInternalAsync(Guid applicationId, UserCreat return modified; } - public async Task SetOwnCompanyApplicationStatusAsync(Guid applicationId, CompanyApplicationStatusId status, Guid companyId) + public async Task SetOwnCompanyApplicationStatusAsync(Guid applicationId, CompanyApplicationStatusId status) { if (status == 0) { @@ -462,20 +479,20 @@ public async Task SetOwnCompanyApplicationStatusAsync(Guid applicationId, C } var applicationRepository = _portalRepositories.GetInstance(); - var applicationUserData = await applicationRepository.GetOwnCompanyApplicationUserDataAsync(applicationId, companyId).ConfigureAwait(false); + var applicationUserData = await applicationRepository.GetOwnCompanyApplicationUserDataAsync(applicationId, _identityService.IdentityData.CompanyId).ConfigureAwait(false); if (!applicationUserData.Exists) { throw new NotFoundException($"CompanyApplication {applicationId} not found"); } - ValidateCompanyApplicationStatus(applicationId, status, applicationUserData, applicationRepository); + ValidateCompanyApplicationStatus(applicationId, status, applicationUserData, applicationRepository, _dateTimeProvider); return await _portalRepositories.SaveAsync().ConfigureAwait(false); } - public async Task GetOwnCompanyApplicationStatusAsync(Guid applicationId, Guid companyId) + public async Task GetOwnCompanyApplicationStatusAsync(Guid applicationId) { - var result = await _portalRepositories.GetInstance().GetOwnCompanyApplicationStatusUserDataUntrackedAsync(applicationId, companyId).ConfigureAwait(false); + var result = await _portalRepositories.GetInstance().GetOwnCompanyApplicationStatusUserDataUntrackedAsync(applicationId, _identityService.IdentityData.CompanyId).ConfigureAwait(false); if (!result.Exists) { throw new NotFoundException($"CompanyApplication {applicationId} not found"); @@ -487,7 +504,7 @@ public async Task GetOwnCompanyApplicationStatusAsyn return result.ApplicationStatus; } - public async Task SubmitRoleConsentAsync(Guid applicationId, CompanyRoleAgreementConsents roleAgreementConsentStatuses, Guid userId, Guid companyId) + public async Task SubmitRoleConsentAsync(Guid applicationId, CompanyRoleAgreementConsents roleAgreementConsentStatuses) { var companyRoleIdsToSet = roleAgreementConsentStatuses.CompanyRoleIds; var agreementConsentsToSet = roleAgreementConsentStatuses.AgreementConsentStatuses; @@ -502,6 +519,8 @@ public async Task SubmitRoleConsentAsync(Guid applicationId, CompanyRoleAgr throw new NotFoundException($"application {applicationId} does not exist"); } + var companyId = _identityService.IdentityData.CompanyId; + var userId = _identityService.IdentityData.UserId; var (applicationCompanyId, applicationStatusId, companyAssignedRoleIds, consents) = companyRoleAgreementConsentData; if (applicationCompanyId != companyId) { @@ -537,14 +556,14 @@ public async Task SubmitRoleConsentAsync(Guid applicationId, CompanyRoleAgr HandleConsent(consents, agreementConsentsToSet, consentRepository, companyId, userId); - UpdateApplicationStatus(applicationId, applicationStatusId, UpdateApplicationSteps.CompanyRoleAgreementConsents, _portalRepositories.GetInstance()); + UpdateApplicationStatus(applicationId, applicationStatusId, UpdateApplicationSteps.CompanyRoleAgreementConsents, _portalRepositories.GetInstance(), _dateTimeProvider); return await _portalRepositories.SaveAsync().ConfigureAwait(false); } - public async Task GetRoleAgreementConsentsAsync(Guid applicationId, Guid userId) + public async Task GetRoleAgreementConsentsAsync(Guid applicationId) { - var result = await _portalRepositories.GetInstance().GetCompanyRoleAgreementConsentStatusUntrackedAsync(applicationId, userId).ConfigureAwait(false); + var result = await _portalRepositories.GetInstance().GetCompanyRoleAgreementConsentStatusUntrackedAsync(applicationId, _identityService.IdentityData.CompanyId).ConfigureAwait(false); if (result == null) { throw new ForbiddenException($"user is not assigned with CompanyApplication {applicationId}"); @@ -558,9 +577,9 @@ public async Task GetCompanyRoleAgreementDataAsync() = (await _portalRepositories.GetInstance().GetAgreementsForCompanyRolesUntrackedAsync().ToListAsync().ConfigureAwait(false)).AsEnumerable() ); - public async Task SubmitRegistrationAsync(Guid applicationId, Guid userId) + public async Task SubmitRegistrationAsync(Guid applicationId) { - var applicationUserData = await GetAndValidateCompanyDataDetails(applicationId, userId, _settings.SubmitDocumentTypeIds).ConfigureAwait(false); + var applicationUserData = await GetAndValidateCompanyDataDetails(applicationId, _settings.SubmitDocumentTypeIds).ConfigureAwait(false); if (GetAndValidateUpdateApplicationStatus(applicationUserData.CompanyApplicationStatusId, UpdateApplicationSteps.SubmitRegistration) != CompanyApplicationStatusId.SUBMITTED) { @@ -590,6 +609,7 @@ public async Task SubmitRegistrationAsync(Guid applicationId, Guid userId) { application.ApplicationStatusId = CompanyApplicationStatusId.SUBMITTED; application.ChecklistProcessId = process.Id; + application.DateLastChanged = _dateTimeProvider.OffsetNow; }); await _portalRepositories.SaveAsync().ConfigureAwait(false); @@ -605,14 +625,15 @@ public async Task SubmitRegistrationAsync(Guid applicationId, Guid userId) } else { - _logger.LogInformation("user {userId} has no email-address", userId); + _logger.LogInformation("user {userId} has no email-address", _identityService.IdentityData.UserId); } return true; } - private async ValueTask GetAndValidateCompanyDataDetails(Guid applicationId, Guid userId, IEnumerable docTypeIds) + private async ValueTask GetAndValidateCompanyDataDetails(Guid applicationId, IEnumerable docTypeIds) { + var userId = _identityService.IdentityData.UserId; var applicationUserData = await _portalRepositories.GetInstance() .GetOwnCompanyApplicationUserEmailDataAsync(applicationId, userId, docTypeIds).ConfigureAwait(false); @@ -681,9 +702,9 @@ public async IAsyncEnumerable GetInvitedUsersAsync(Guid application } } - public async Task> GetUploadedDocumentsAsync(Guid applicationId, DocumentTypeId documentTypeId, Guid userId) + public async Task> GetUploadedDocumentsAsync(Guid applicationId, DocumentTypeId documentTypeId) { - var result = await _portalRepositories.GetInstance().GetUploadedDocumentsAsync(applicationId, documentTypeId, userId).ConfigureAwait(false); + var result = await _portalRepositories.GetInstance().GetUploadedDocumentsAsync(applicationId, documentTypeId, _identityService.IdentityData.UserId).ConfigureAwait(false); if (result == default) { throw new NotFoundException($"application {applicationId} not found"); @@ -695,9 +716,9 @@ public async Task> GetUploadedDocumentsAsync(Guid a return result.Documents; } - public async Task SetInvitationStatusAsync(Guid userId) + public async Task SetInvitationStatusAsync() { - var invitationData = await _portalRepositories.GetInstance().GetInvitationStatusAsync(userId).ConfigureAwait(false); + var invitationData = await _portalRepositories.GetInstance().GetInvitationStatusAsync(_identityService.IdentityData.UserId).ConfigureAwait(false); if (invitationData == null) { @@ -708,13 +729,16 @@ public async Task SetInvitationStatusAsync(Guid userId) { invitationData.InvitationStatusId = InvitationStatusId.ACCEPTED; } - + _portalRepositories.GetInstance().AttachAndModifyCompanyApplication(invitationData.CompanyApplicationId, application => + { + application.DateLastChanged = _dateTimeProvider.OffsetNow; + }); return await _portalRepositories.SaveAsync().ConfigureAwait(false); } - public async Task GetRegistrationDataAsync(Guid applicationId, Guid companyId) + public async Task GetRegistrationDataAsync(Guid applicationId) { - var (isValidApplicationId, isValidCompany, data) = await _portalRepositories.GetInstance().GetRegistrationDataUntrackedAsync(applicationId, companyId, _settings.DocumentTypeIds).ConfigureAwait(false); + var (isValidApplicationId, isValidCompany, data) = await _portalRepositories.GetInstance().GetRegistrationDataUntrackedAsync(applicationId, _identityService.IdentityData.CompanyId, _settings.DocumentTypeIds).ConfigureAwait(false); if (!isValidApplicationId) { throw new NotFoundException($"application {applicationId} does not exist"); @@ -787,7 +811,7 @@ private static void HandleConsent(IEnumerable consents, IEnumerable private static void ValidateCompanyApplicationStatus(Guid applicationId, CompanyApplicationStatusId status, (bool Exists, CompanyApplicationStatusId StatusId) applicationData, - IApplicationRepository applicationRepository) + IApplicationRepository applicationRepository, IDateTimeProvider dateTimeProvider) { var allowedCombination = new (CompanyApplicationStatusId applicationStatus, CompanyApplicationStatusId status)[] { @@ -810,10 +834,11 @@ private static void ValidateCompanyApplicationStatus(Guid applicationId, applicationRepository.AttachAndModifyCompanyApplication(applicationId, a => { a.ApplicationStatusId = status; + a.DateLastChanged = dateTimeProvider.OffsetNow; }); } - private static void UpdateApplicationStatus(Guid applicationId, CompanyApplicationStatusId applicationStatusId, UpdateApplicationSteps type, IApplicationRepository applicationRepository) + private static void UpdateApplicationStatus(Guid applicationId, CompanyApplicationStatusId applicationStatusId, UpdateApplicationSteps type, IApplicationRepository applicationRepository, IDateTimeProvider dateTimeProvider) { var updateStatus = GetAndValidateUpdateApplicationStatus(applicationStatusId, type); if (updateStatus != default) @@ -821,6 +846,7 @@ private static void UpdateApplicationStatus(Guid applicationId, CompanyApplicati applicationRepository.AttachAndModifyCompanyApplication(applicationId, ca => { ca.ApplicationStatusId = updateStatus; + ca.DateLastChanged = dateTimeProvider.OffsetNow; }); } } @@ -857,14 +883,14 @@ _ when (applicationStatusId == CompanyApplicationStatusId.SUBMITTED || }; } - public async Task DeleteRegistrationDocumentAsync(Guid documentId, Guid companyId) + public async Task DeleteRegistrationDocumentAsync(Guid documentId) { if (documentId == Guid.Empty) { throw new ControllerArgumentException($"documentId must not be empty"); } var documentRepository = _portalRepositories.GetInstance(); - var details = await documentRepository.GetDocumentDetailsForApplicationUntrackedAsync(documentId, companyId, _settings.ApplicationStatusIds).ConfigureAwait(false); + var details = await documentRepository.GetDocumentDetailsForApplicationUntrackedAsync(documentId, _identityService.IdentityData.CompanyId, _settings.ApplicationStatusIds).ConfigureAwait(false); if (details == default) { throw new NotFoundException("Document does not exist."); @@ -888,6 +914,12 @@ public async Task DeleteRegistrationDocumentAsync(Guid documentId, Guid co documentRepository.RemoveDocument(details.DocumentId); + _portalRepositories.GetInstance().AttachAndModifyCompanyApplications( + details.applicationId.Select(applicationId => new ValueTuple?, Action>( + applicationId, + null, + application => application.DateLastChanged = _dateTimeProvider.OffsetNow))); + await this._portalRepositories.SaveAsync().ConfigureAwait(false); return true; } diff --git a/src/registration/Registration.Service/Controllers/NetworkController.cs b/src/registration/Registration.Service/Controllers/NetworkController.cs new file mode 100644 index 0000000000..d21e30ee33 --- /dev/null +++ b/src/registration/Registration.Service/Controllers/NetworkController.cs @@ -0,0 +1,67 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 BMW Group AG + * Copyright (c) 2021, 2023 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 Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Library; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Models; +using Org.Eclipse.TractusX.Portal.Backend.Registration.Service.BusinessLogic; +using Org.Eclipse.TractusX.Portal.Backend.Registration.Service.Model; + +namespace Org.Eclipse.TractusX.Portal.Backend.Registration.Service.Controllers; + +[ApiController] +[Route("api/registration/[controller]")] +[Produces("application/json")] +[Consumes("application/json")] +public class NetworkController : ControllerBase +{ + private readonly INetworkBusinessLogic _logic; + + /// + /// Creates a new instance of + /// + /// The business logic for the registration + public NetworkController(INetworkBusinessLogic logic) + { + _logic = logic; + } + + /// + /// Submits the application + /// + /// The agreements for the companyRoles + /// NoContent + /// Example: POST: api/administration/registration/network/partnerRegistration/submit + /// Empty response on success. + /// No registration found for the externalId. + [HttpPost] + [Authorize(Roles = "submit_registration")] + [Authorize(Policy = PolicyTypes.CompanyUser)] + [Route("partnerRegistration/submit")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] + public async Task Submit([FromBody] PartnerSubmitData data) + { + await _logic.Submit(data).ConfigureAwait(false); + return NoContent(); + } +} diff --git a/src/registration/Registration.Service/Controllers/RegistrationController.cs b/src/registration/Registration.Service/Controllers/RegistrationController.cs index 9359017af6..c9034bcb55 100644 --- a/src/registration/Registration.Service/Controllers/RegistrationController.cs +++ b/src/registration/Registration.Service/Controllers/RegistrationController.cs @@ -95,7 +95,7 @@ public Task GetCompanyBpdmDetailDataAsync([FromRoute] str [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status415UnsupportedMediaType)] public Task UploadDocumentAsync([FromRoute] Guid applicationId, [FromRoute] DocumentTypeId documentTypeId, [FromForm(Name = "document")] IFormFile document, CancellationToken cancellationToken) => - this.WithUserIdAndCompanyId(identity => _registrationBusinessLogic.UploadDocumentAsync(applicationId, document, documentTypeId, identity, cancellationToken)); + _registrationBusinessLogic.UploadDocumentAsync(applicationId, document, documentTypeId, cancellationToken); /// /// Gets a specific document by its id @@ -116,7 +116,7 @@ public Task UploadDocumentAsync([FromRoute] Guid applicationId, [FromRoute] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] public async Task GetDocumentContentFileAsync([FromRoute] Guid documentId) { - var (fileName, content, mediaType) = await this.WithUserId(userId => _registrationBusinessLogic.GetDocumentContentAsync(documentId, userId)); + var (fileName, content, mediaType) = await _registrationBusinessLogic.GetDocumentContentAsync(documentId); return File(content, mediaType, fileName); } @@ -138,7 +138,7 @@ public async Task GetDocumentContentFileAsync([FromRoute] Guid doc [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] public Task> GetUploadedDocumentsAsync([FromRoute] Guid applicationId, [FromRoute] DocumentTypeId documentTypeId) => - this.WithUserId(userId => _registrationBusinessLogic.GetUploadedDocumentsAsync(applicationId, documentTypeId, userId)); + _registrationBusinessLogic.GetUploadedDocumentsAsync(applicationId, documentTypeId); /// /// Get all composite client roles @@ -165,7 +165,7 @@ public IAsyncEnumerable GetClientRolesComposite() => [Route("applications")] [ProducesResponseType(typeof(IAsyncEnumerable), StatusCodes.Status200OK)] public IAsyncEnumerable GetApplicationsWithStatusAsync() => - this.WithCompanyId(companyId => _registrationBusinessLogic.GetAllApplicationsForUserWithStatus(companyId)); + _registrationBusinessLogic.GetAllApplicationsForUserWithStatus(); /// /// Sets the status of a specific application. @@ -187,7 +187,7 @@ public IAsyncEnumerable GetApplicationsWithStatusA [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)] public Task SetApplicationStatusAsync([FromRoute] Guid applicationId, [FromQuery] CompanyApplicationStatusId status) => - this.WithCompanyId(companyId => _registrationBusinessLogic.SetOwnCompanyApplicationStatusAsync(applicationId, status, companyId)); + _registrationBusinessLogic.SetOwnCompanyApplicationStatusAsync(applicationId, status); /// /// Gets the status of an application for the given id @@ -206,7 +206,7 @@ public Task SetApplicationStatusAsync([FromRoute] Guid applicationId, [From [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)] public Task GetApplicationStatusAsync([FromRoute] Guid applicationId) => - this.WithCompanyId(companyId => _registrationBusinessLogic.GetOwnCompanyApplicationStatusAsync(applicationId, companyId)); + _registrationBusinessLogic.GetOwnCompanyApplicationStatusAsync(applicationId); /// /// Gets the company of a specific application with its address @@ -225,8 +225,7 @@ public Task GetApplicationStatusAsync([FromRoute] Gu [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)] public Task GetCompanyDetailDataAsync([FromRoute] Guid applicationId) => - this.WithCompanyId(companyId => - _registrationBusinessLogic.GetCompanyDetailData(applicationId, companyId)); + _registrationBusinessLogic.GetCompanyDetailData(applicationId); /// /// Sets the company with its address for the given application id @@ -247,7 +246,7 @@ public Task GetCompanyDetailDataAsync([FromRoute] Guid applic [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)] public Task SetCompanyDetailDataAsync([FromRoute] Guid applicationId, [FromBody] CompanyDetailData companyDetailData) => - this.WithCompanyId(companyId => _registrationBusinessLogic.SetCompanyDetailDataAsync(applicationId, companyDetailData, companyId)); + _registrationBusinessLogic.SetCompanyDetailDataAsync(applicationId, companyDetailData); /// /// Invites the given user to the given application @@ -270,7 +269,7 @@ public Task SetCompanyDetailDataAsync([FromRoute] Guid applicationId, [FromBody] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status500InternalServerError)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)] public Task InviteNewUserAsync([FromRoute] Guid applicationId, [FromBody] UserCreationInfoWithMessage userCreationInfo) => - this.WithUserIdAndCompanyId(identity => _registrationBusinessLogic.InviteNewUserAsync(applicationId, userCreationInfo, identity)); + _registrationBusinessLogic.InviteNewUserAsync(applicationId, userCreationInfo); /// /// Post the agreement consent status for the given application. @@ -293,7 +292,7 @@ public Task InviteNewUserAsync([FromRoute] Guid applicationId, [FromBody] U [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)] public Task SubmitCompanyRoleConsentToAgreementsAsync([FromRoute] Guid applicationId, [FromBody] CompanyRoleAgreementConsents companyRolesAgreementConsents) => - this.WithUserIdAndCompanyId(identity => _registrationBusinessLogic.SubmitRoleConsentAsync(applicationId, companyRolesAgreementConsents, identity.UserId, identity.CompanyId)); + _registrationBusinessLogic.SubmitRoleConsentAsync(applicationId, companyRolesAgreementConsents); /// /// Gets the agreement consent statuses for the given application @@ -310,7 +309,7 @@ public Task SubmitCompanyRoleConsentToAgreementsAsync([FromRoute] Guid appl [ProducesResponseType(typeof(CompanyRoleAgreementConsents), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)] public Task GetAgreementConsentStatusesAsync([FromRoute] Guid applicationId) => - this.WithUserId(userId => _registrationBusinessLogic.GetRoleAgreementConsentsAsync(applicationId, userId)); + _registrationBusinessLogic.GetRoleAgreementConsentsAsync(applicationId); /// /// Gets the company role agreement data @@ -345,7 +344,7 @@ public Task GetCompanyRoleAgreementDataAsync() => [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status500InternalServerError)] public Task SubmitRegistrationAsync([FromRoute] Guid applicationId) => - this.WithUserId(userId => _registrationBusinessLogic.SubmitRegistrationAsync(applicationId, userId)); + _registrationBusinessLogic.SubmitRegistrationAsync(applicationId); /// /// Gets all invited users for a given application @@ -375,7 +374,7 @@ public IAsyncEnumerable GetInvitedUsersAsync([FromRoute] Guid appli [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)] public Task SetInvitationStatusAsync() => - this.WithUserId(userId => _registrationBusinessLogic.SetInvitationStatusAsync(userId)); + _registrationBusinessLogic.SetInvitationStatusAsync(); /// /// Gets the registration data for the given application id @@ -396,8 +395,7 @@ public Task SetInvitationStatusAsync() => [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status503ServiceUnavailable)] public Task GetRegistrationDataAsync([FromRoute] Guid applicationId) => - this.WithCompanyId(companyId => - _registrationBusinessLogic.GetRegistrationDataAsync(applicationId, companyId)); + _registrationBusinessLogic.GetRegistrationDataAsync(applicationId); /// /// Gets the company roles and roles description @@ -435,7 +433,7 @@ public IAsyncEnumerable GetCompanyRolesAsync([FromQuery] st [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status409Conflict)] public async Task DeleteRegistrationDocument([FromRoute] Guid documentId) { - await this.WithCompanyId(companyId => _registrationBusinessLogic.DeleteRegistrationDocumentAsync(documentId, companyId)); + await _registrationBusinessLogic.DeleteRegistrationDocumentAsync(documentId); return NoContent(); } diff --git a/src/registration/Registration.Service/Model/PartnerSubmitData.cs b/src/registration/Registration.Service/Model/PartnerSubmitData.cs new file mode 100644 index 0000000000..b8d10b5d27 --- /dev/null +++ b/src/registration/Registration.Service/Model/PartnerSubmitData.cs @@ -0,0 +1,40 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 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.PortalBackend.PortalEntities.Enums; +using System.Text.Json.Serialization; + +namespace Org.Eclipse.TractusX.Portal.Backend.Registration.Service.Model; + +public record PartnerSubmitData +( + IEnumerable CompanyRoles, + IEnumerable Agreements +); + +/// +/// +/// +/// +/// +/// +public record AgreementConsentData( + Guid AgreementId, + [property: JsonPropertyName("consentStatus")] ConsentStatusId ConsentStatusId +); diff --git a/src/registration/Registration.Service/Program.cs b/src/registration/Registration.Service/Program.cs index 23fae3c6c8..7469e19b6c 100644 --- a/src/registration/Registration.Service/Program.cs +++ b/src/registration/Registration.Service/Program.cs @@ -41,7 +41,8 @@ builder.Services.AddTransient(); builder.Services.AddTransient() - .ConfigureRegistrationSettings(builder.Configuration.GetSection("Registration")); + .ConfigureRegistrationSettings(builder.Configuration.GetSection("Registration")) + .AddTransient(); builder.Services.AddApplicationChecklistCreation(); builder.Services.AddBpnAccess(builder.Configuration.GetValue("BPN_Address") ?? throw new ConfigurationException("BPN_Address is not configured")); diff --git a/src/registration/Registration.Service/Registration.Service.csproj b/src/registration/Registration.Service/Registration.Service.csproj index 6e83605fc3..8d1158a692 100644 --- a/src/registration/Registration.Service/Registration.Service.csproj +++ b/src/registration/Registration.Service/Registration.Service.csproj @@ -1,72 +1,73 @@ - - - - - - Org.Eclipse.TractusX.Portal.Backend.Registration.Service - net7.0 - enable - enable - 1557fa58-6743-480f-8f98-155d33f89c0a - Linux - ..\..\.. - True - CS1591 - Org.Eclipse.TractusX.Portal.Backend.Registration.Service - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - - - - - - - - - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - - - - Program.cs - - - - + + + + + + Org.Eclipse.TractusX.Portal.Backend.Registration.Service + Org.Eclipse.TractusX.Portal.Backend.Registration.Service + net7.0 + enable + enable + 1557fa58-6743-480f-8f98-155d33f89c0a + Linux + ..\..\.. + True + CS1591 + Org.Eclipse.TractusX.Portal.Backend.Registration.Service + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + + + Program.cs + + + + diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/ConnectorsBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/ConnectorsBusinessLogicTests.cs index c4c579843a..10e9c9072b 100644 --- a/tests/administration/Administration.Service.Tests/BusinessLogic/ConnectorsBusinessLogicTests.cs +++ b/tests/administration/Administration.Service.Tests/BusinessLogic/ConnectorsBusinessLogicTests.cs @@ -18,6 +18,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLogic; using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models; @@ -103,8 +104,9 @@ public ConnectorsBusinessLogicTests() A.CallTo(() => options.Value).Returns(_settings); A.CallTo(() => _identityService.IdentityData).Returns(_identity); + var logger = A.Fake>(); - _logic = new ConnectorsBusinessLogic(_portalRepositories, options, _sdFactoryBusinessLogic, _identityService); + _logic = new ConnectorsBusinessLogic(_portalRepositories, options, _sdFactoryBusinessLogic, _identityService, logger); } #region GetAllCompanyConnectorDatas diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/DocumentsBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/DocumentsBusinessLogicTests.cs index 1078806779..dbd2f0718e 100644 --- a/tests/administration/Administration.Service.Tests/BusinessLogic/DocumentsBusinessLogicTests.cs +++ b/tests/administration/Administration.Service.Tests/BusinessLogic/DocumentsBusinessLogicTests.cs @@ -39,6 +39,7 @@ public class DocumentsBusinessLogicTests private readonly IPortalRepositories _portalRepositories; private readonly IOptions _options; private readonly DocumentsBusinessLogic _sut; + private readonly IIdentityService _identityService; public DocumentsBusinessLogicTests() { @@ -53,9 +54,11 @@ public DocumentsBusinessLogicTests() { EnableSeedEndpoint = true }); + _identityService = A.Fake(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_documentRepository); - _sut = new DocumentsBusinessLogic(_portalRepositories, _options); + _sut = new DocumentsBusinessLogic(_portalRepositories, _identityService, _options); } #region GetSeedData @@ -65,7 +68,7 @@ public async Task GetSeedData_WithValidId_ReturnsValidData() { // Arrange SetupFakesForGetSeedData(); - var sut = new DocumentsBusinessLogic(_portalRepositories, _options); + var sut = new DocumentsBusinessLogic(_portalRepositories, _identityService, _options); // Act var result = await sut.GetSeedData(ValidDocumentId).ConfigureAwait(false); @@ -80,7 +83,7 @@ public async Task CreateConnectorAsync_WithInvalidId_ThrowsNotFoundException() // Arrange var invalidId = Guid.NewGuid(); SetupFakesForGetSeedData(); - var sut = new DocumentsBusinessLogic(_portalRepositories, _options); + var sut = new DocumentsBusinessLogic(_portalRepositories, _identityService, _options); // Act async Task Act() => await sut.GetSeedData(invalidId).ConfigureAwait(false); @@ -96,7 +99,7 @@ public async Task CreateConnectorAsync_WithCallFromTest_ThrowsForbiddenException // Arrange SetupFakesForGetSeedData(); _options.Value.EnableSeedEndpoint = false; - var sut = new DocumentsBusinessLogic(_portalRepositories, _options); + var sut = new DocumentsBusinessLogic(_portalRepositories, _identityService, _options); // Act async Task Act() => await sut.GetSeedData(ValidDocumentId).ConfigureAwait(false); @@ -117,7 +120,7 @@ public async Task GetDocumentAsync_WithValidData_ReturnsExpected() SetupFakesForGetDocument(); // Act - var result = await _sut.GetDocumentAsync(ValidDocumentId, _identity.CompanyId).ConfigureAwait(false); + var result = await _sut.GetDocumentAsync(ValidDocumentId).ConfigureAwait(false); // Assert result.Should().NotBeNull(); @@ -133,7 +136,7 @@ public async Task GetDocumentAsync_WithNotExistingDocument_ThrowsNotFoundExcepti SetupFakesForGetDocument(); // Act - async Task Act() => await _sut.GetDocumentAsync(documentId, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.GetDocumentAsync(documentId).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -145,10 +148,11 @@ public async Task GetDocumentAsync_WithWrongUser_ThrowsForbiddenException() { // Arrange var identity = _fixture.Create(); + A.CallTo(() => _identityService.IdentityData).Returns(identity); SetupFakesForGetDocument(); // Act - async Task Act() => await _sut.GetDocumentAsync(ValidDocumentId, identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.GetDocumentAsync(ValidDocumentId).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/IdentityProviderBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/IdentityProviderBusinessLogicTests.cs index 4960d50ced..063e12c547 100644 --- a/tests/administration/Administration.Service.Tests/BusinessLogic/IdentityProviderBusinessLogicTests.cs +++ b/tests/administration/Administration.Service.Tests/BusinessLogic/IdentityProviderBusinessLogicTests.cs @@ -28,6 +28,7 @@ using Org.Eclipse.TractusX.Portal.Backend.Framework.IO; using Org.Eclipse.TractusX.Portal.Backend.Keycloak.ErrorHandling; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; @@ -131,7 +132,7 @@ public async Task TestUploadOwnCompanyUsersIdentityProviderLinkDataAsyncAllUncha _options, _logger); - var result = await sut.UploadOwnCompanyUsersIdentityProviderLinkDataAsync(_document, _identity.CompanyId, CancellationToken.None).ConfigureAwait(false); + var result = await sut.UploadOwnCompanyUsersIdentityProviderLinkDataAsync(_document, CancellationToken.None).ConfigureAwait(false); result.Updated.Should().Be(0); result.Unchanged.Should().Be(numUsers); @@ -167,7 +168,7 @@ public async Task TestUploadOwnCompanyUsersIdentityProviderLinkDataAsyncWrongCon _options, _logger); - async Task Act() => await sut.UploadOwnCompanyUsersIdentityProviderLinkDataAsync(_document, _identity.CompanyId, CancellationToken.None).ConfigureAwait(false); + async Task Act() => await sut.UploadOwnCompanyUsersIdentityProviderLinkDataAsync(_document, CancellationToken.None).ConfigureAwait(false); var error = await Assert.ThrowsAsync(Act).ConfigureAwait(false); error.Message.Should().Be($"Only contentType {_csvSettings.ContentType} files are allowed."); @@ -216,7 +217,7 @@ public async Task TestUploadOwnCompanyUsersIdentityProviderLinkDataAsyncEmailCha _options, _logger); - var result = await sut.UploadOwnCompanyUsersIdentityProviderLinkDataAsync(_document, _identity.CompanyId, CancellationToken.None).ConfigureAwait(false); + var result = await sut.UploadOwnCompanyUsersIdentityProviderLinkDataAsync(_document, CancellationToken.None).ConfigureAwait(false); result.Updated.Should().Be(1); result.Unchanged.Should().Be(numUsers - 1); @@ -262,7 +263,7 @@ public async Task TestUploadOwnCompanyUsersIdentityProviderLinkDataAsyncSharedId _options, _logger); - var result = await sut.UploadOwnCompanyUsersIdentityProviderLinkDataAsync(_document, _identity.CompanyId, CancellationToken.None).ConfigureAwait(false); + var result = await sut.UploadOwnCompanyUsersIdentityProviderLinkDataAsync(_document, CancellationToken.None).ConfigureAwait(false); result.Updated.Should().Be(0); result.Unchanged.Should().Be(numUsers - 1); @@ -306,7 +307,7 @@ public async Task TestUploadOwnCompanyUsersIdentityProviderLinkDataAsyncOtherIdp _options, _logger); - var result = await sut.UploadOwnCompanyUsersIdentityProviderLinkDataAsync(_document, _identity.CompanyId, CancellationToken.None).ConfigureAwait(false); + var result = await sut.UploadOwnCompanyUsersIdentityProviderLinkDataAsync(_document, CancellationToken.None).ConfigureAwait(false); result.Updated.Should().Be(1); result.Unchanged.Should().Be(numUsers - 1); @@ -349,7 +350,7 @@ public async Task TestUploadOwnCompanyUsersIdentityProviderLinkDataAsyncUnknownC _options, _logger); - var result = await sut.UploadOwnCompanyUsersIdentityProviderLinkDataAsync(_document, _identity.CompanyId, CancellationToken.None).ConfigureAwait(false); + var result = await sut.UploadOwnCompanyUsersIdentityProviderLinkDataAsync(_document, CancellationToken.None).ConfigureAwait(false); result.Updated.Should().Be(0); result.Unchanged.Should().Be(numUsers - 1); @@ -1480,7 +1481,6 @@ public async Task CreateOwnCompanyUserIdentityProviderLinkDataAsync_WithoutIamUs // Arrange var identityProviderId = Guid.NewGuid(); var companyUserId = Guid.NewGuid(); - var companyId = Guid.NewGuid(); var data = _fixture.Build() .With(x => x.identityProviderId, identityProviderId) .Create(); @@ -1490,11 +1490,11 @@ public async Task CreateOwnCompanyUserIdentityProviderLinkDataAsync_WithoutIamUs _identityService, _options, _logger); - A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, companyId)) + A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, _identity.CompanyId)) .Returns(((string?, string?, bool))default); // Act - async Task Act() => await sut.CreateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, data, companyId).ConfigureAwait(false); + async Task Act() => await sut.CreateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, data).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -1507,7 +1507,6 @@ public async Task CreateOwnCompanyUserIdentityProviderLinkDataAsync_WithoutIamUs // Arrange var identityProviderId = Guid.NewGuid(); var companyUserId = Guid.NewGuid(); - var companyId = Guid.NewGuid(); var data = _fixture.Build() .With(x => x.identityProviderId, identityProviderId) .Create(); @@ -1517,11 +1516,11 @@ public async Task CreateOwnCompanyUserIdentityProviderLinkDataAsync_WithoutIamUs _identityService, _options, _logger); - A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, companyId)) + A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, _identity.CompanyId)) .Returns((null, "cl1", false)); // Act - async Task Act() => await sut.CreateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, data, companyId).ConfigureAwait(false); + async Task Act() => await sut.CreateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, data).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -1535,7 +1534,6 @@ public async Task CreateOwnCompanyUserIdentityProviderLinkDataAsync_WithoutAlias var identityProviderId = Guid.NewGuid(); var userEntityId = Guid.NewGuid(); var companyUserId = Guid.NewGuid(); - var companyId = Guid.NewGuid(); var data = _fixture.Build() .With(x => x.identityProviderId, identityProviderId) .Create(); @@ -1545,11 +1543,11 @@ public async Task CreateOwnCompanyUserIdentityProviderLinkDataAsync_WithoutAlias _identityService, _options, _logger); - A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, companyId)) + A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, _identity.CompanyId)) .Returns((userEntityId.ToString(), null, false)); // Act - async Task Act() => await sut.CreateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, data, companyId).ConfigureAwait(false); + async Task Act() => await sut.CreateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, data).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -1563,7 +1561,6 @@ public async Task CreateOwnCompanyUserIdentityProviderLinkDataAsync_WithoutSameC var identityProviderId = Guid.NewGuid(); var userEntityId = Guid.NewGuid(); var companyUserId = Guid.NewGuid(); - var companyId = Guid.NewGuid(); var data = _fixture.Build() .With(x => x.identityProviderId, identityProviderId) .Create(); @@ -1573,15 +1570,15 @@ public async Task CreateOwnCompanyUserIdentityProviderLinkDataAsync_WithoutSameC _identityService, _options, _logger); - A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, companyId)) + A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, _identity.CompanyId)) .Returns((userEntityId.ToString(), "cl1", false)); // Act - async Task Act() => await sut.CreateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, data, companyId).ConfigureAwait(false); + async Task Act() => await sut.CreateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, data).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); - ex.Message.Should().Be($"identityProvider {identityProviderId} is not associated with company {companyId}"); + ex.Message.Should().Be($"identityProvider {identityProviderId} is not associated with company {_identity.CompanyId}"); } [Fact] @@ -1591,7 +1588,6 @@ public async Task CreateOwnCompanyUserIdentityProviderLinkDataAsync_WithKeycloak var identityProviderId = Guid.NewGuid(); var userEntityId = Guid.NewGuid(); var companyUserId = Guid.NewGuid(); - var companyId = Guid.NewGuid(); var data = _fixture.Build() .With(x => x.identityProviderId, identityProviderId) .Create(); @@ -1601,13 +1597,13 @@ public async Task CreateOwnCompanyUserIdentityProviderLinkDataAsync_WithKeycloak _identityService, _options, _logger); - A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, companyId)) + A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, _identity.CompanyId)) .Returns((userEntityId.ToString(), "cl1", true)); A.CallTo(() => _provisioningManager.AddProviderUserLinkToCentralUserAsync(userEntityId.ToString(), A._)) .Throws(new KeycloakEntityConflictException("test")); // Act - async Task Act() => await sut.CreateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, data, companyId).ConfigureAwait(false); + async Task Act() => await sut.CreateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, data).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -1621,7 +1617,6 @@ public async Task CreateOwnCompanyUserIdentityProviderLinkDataAsync_WithValid_Ca var identityProviderId = Guid.NewGuid(); var userEntityId = Guid.NewGuid(); var companyUserId = Guid.NewGuid(); - var companyId = Guid.NewGuid(); var data = _fixture.Build() .With(x => x.identityProviderId, identityProviderId) .With(x => x.userName, "test-user") @@ -1632,11 +1627,11 @@ public async Task CreateOwnCompanyUserIdentityProviderLinkDataAsync_WithValid_Ca _identityService, _options, _logger); - A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, companyId)) + A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, _identity.CompanyId)) .Returns((userEntityId.ToString(), "cl1", true)); // Act - var result = await sut.CreateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, data, companyId).ConfigureAwait(false); + var result = await sut.CreateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, data).ConfigureAwait(false); // Assert A.CallTo(() => _provisioningManager.AddProviderUserLinkToCentralUserAsync(userEntityId.ToString(), A._)) @@ -1654,7 +1649,6 @@ public async Task CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync_With // Arrange var identityProviderId = Guid.NewGuid(); var companyUserId = Guid.NewGuid(); - var companyId = Guid.NewGuid(); var data = _fixture.Build() .With(x => x.userName, "user-name") .Create(); @@ -1664,11 +1658,11 @@ public async Task CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync_With _identityService, _options, _logger); - A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, companyId)) + A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, _identity.CompanyId)) .Returns(((string?, string?, bool))default); // Act - async Task Act() => await sut.CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId, data, companyId).ConfigureAwait(false); + async Task Act() => await sut.CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId, data).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -1681,7 +1675,6 @@ public async Task CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync_With // Arrange var identityProviderId = Guid.NewGuid(); var companyUserId = Guid.NewGuid(); - var companyId = Guid.NewGuid(); var data = _fixture.Build() .With(x => x.userName, "user-name") .Create(); @@ -1691,11 +1684,11 @@ public async Task CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync_With _identityService, _options, _logger); - A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, companyId)) + A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, _identity.CompanyId)) .Returns((null, "cl1", false)); // Act - async Task Act() => await sut.CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId, data, companyId).ConfigureAwait(false); + async Task Act() => await sut.CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId, data).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -1709,7 +1702,6 @@ public async Task CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync_With var userEntityId = Guid.NewGuid(); var identityProviderId = Guid.NewGuid(); var companyUserId = Guid.NewGuid(); - var companyId = Guid.NewGuid(); var data = _fixture.Build() .With(x => x.userName, "user-name") .Create(); @@ -1719,11 +1711,11 @@ public async Task CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync_With _identityService, _options, _logger); - A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, companyId)) + A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, _identity.CompanyId)) .Returns((userEntityId.ToString(), null, false)); // Act - async Task Act() => await sut.CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId, data, companyId).ConfigureAwait(false); + async Task Act() => await sut.CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId, data).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -1737,7 +1729,6 @@ public async Task CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync_With var userEntityId = Guid.NewGuid(); var identityProviderId = Guid.NewGuid(); var companyUserId = Guid.NewGuid(); - var companyId = Guid.NewGuid(); var data = _fixture.Build() .With(x => x.userName, "user-name") .Create(); @@ -1747,15 +1738,15 @@ public async Task CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync_With _identityService, _options, _logger); - A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, companyId)) + A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, _identity.CompanyId)) .Returns((userEntityId.ToString(), "cl1", false)); // Act - async Task Act() => await sut.CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId, data, companyId).ConfigureAwait(false); + async Task Act() => await sut.CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId, data).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); - ex.Message.Should().Be($"identityProvider {identityProviderId} is not associated with company {companyId}"); + ex.Message.Should().Be($"identityProvider {identityProviderId} is not associated with company {_identity.CompanyId}"); } [Fact] @@ -1765,7 +1756,6 @@ public async Task CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync_With var userEntityId = Guid.NewGuid(); var identityProviderId = Guid.NewGuid(); var companyUserId = Guid.NewGuid(); - var companyId = Guid.NewGuid(); var data = _fixture.Build() .With(x => x.userName, "user-name") .Create(); @@ -1775,11 +1765,11 @@ public async Task CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync_With _identityService, _options, _logger); - A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, companyId)) + A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, _identity.CompanyId)) .Returns((userEntityId.ToString(), "cl1", true)); // Act - var result = await sut.CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId, data, companyId).ConfigureAwait(false); + var result = await sut.CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId, data).ConfigureAwait(false); // Assert A.CallTo(() => _provisioningManager.DeleteProviderUserLinkToCentralUserAsync(userEntityId.ToString(), "cl1")) @@ -1799,18 +1789,17 @@ public async Task GetOwnCompanyUserIdentityProviderLinkDataAsync_WithoutIamUserI // Arrange var identityProviderId = Guid.NewGuid(); var companyUserId = Guid.NewGuid(); - var companyId = Guid.NewGuid(); var sut = new IdentityProviderBusinessLogic( _portalRepositories, _provisioningManager, _identityService, _options, _logger); - A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, companyId)) + A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, _identity.CompanyId)) .Returns(((string?, string?, bool))default); // Act - async Task Act() => await sut.GetOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId, companyId).ConfigureAwait(false); + async Task Act() => await sut.GetOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -1823,18 +1812,17 @@ public async Task GetOwnCompanyUserIdentityProviderLinkDataAsync_WithoutIamUserI // Arrange var identityProviderId = Guid.NewGuid(); var companyUserId = Guid.NewGuid(); - var companyId = Guid.NewGuid(); var sut = new IdentityProviderBusinessLogic( _portalRepositories, _provisioningManager, _identityService, _options, _logger); - A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, companyId)) + A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, _identity.CompanyId)) .Returns((null, "cl1", false)); // Act - async Task Act() => await sut.GetOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId, companyId).ConfigureAwait(false); + async Task Act() => await sut.GetOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -1848,18 +1836,17 @@ public async Task GetOwnCompanyUserIdentityProviderLinkDataAsync_WithoutAlias_Th var userEntityId = Guid.NewGuid(); var identityProviderId = Guid.NewGuid(); var companyUserId = Guid.NewGuid(); - var companyId = Guid.NewGuid(); var sut = new IdentityProviderBusinessLogic( _portalRepositories, _provisioningManager, _identityService, _options, _logger); - A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, companyId)) + A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, _identity.CompanyId)) .Returns((userEntityId.ToString(), null, false)); // Act - async Task Act() => await sut.GetOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId, companyId).ConfigureAwait(false); + async Task Act() => await sut.GetOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -1873,22 +1860,21 @@ public async Task GetOwnCompanyUserIdentityProviderLinkDataAsync_WithoutSameComp var userEntityId = Guid.NewGuid(); var identityProviderId = Guid.NewGuid(); var companyUserId = Guid.NewGuid(); - var companyId = Guid.NewGuid(); var sut = new IdentityProviderBusinessLogic( _portalRepositories, _provisioningManager, _identityService, _options, _logger); - A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, companyId)) + A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, _identity.CompanyId)) .Returns((userEntityId.ToString(), "cl1", false)); // Act - async Task Act() => await sut.GetOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId, companyId).ConfigureAwait(false); + async Task Act() => await sut.GetOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); - ex.Message.Should().Be($"identityProvider {identityProviderId} is not associated with company {companyId}"); + ex.Message.Should().Be($"identityProvider {identityProviderId} is not associated with company {_identity.CompanyId}"); } [Fact] @@ -1898,20 +1884,19 @@ public async Task GetOwnCompanyUserIdentityProviderLinkDataAsync_WithoutExisting var userEntityId = Guid.NewGuid(); var identityProviderId = Guid.NewGuid(); var companyUserId = Guid.NewGuid(); - var companyId = Guid.NewGuid(); var sut = new IdentityProviderBusinessLogic( _portalRepositories, _provisioningManager, _identityService, _options, _logger); - A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, companyId)) + A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, _identity.CompanyId)) .Returns((userEntityId.ToString(), "cl1", true)); A.CallTo(() => _provisioningManager.GetProviderUserLinkDataForCentralUserIdAsync(userEntityId.ToString())) .Returns(Enumerable.Empty().ToAsyncEnumerable()); // Act - async Task Act() => await sut.GetOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId, companyId).ConfigureAwait(false); + async Task Act() => await sut.GetOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -1925,20 +1910,19 @@ public async Task GetOwnCompanyUserIdentityProviderLinkDataAsync_WithValid_Calls var userEntityId = Guid.NewGuid(); var identityProviderId = Guid.NewGuid(); var companyUserId = Guid.NewGuid(); - var companyId = Guid.NewGuid(); var sut = new IdentityProviderBusinessLogic( _portalRepositories, _provisioningManager, _identityService, _options, _logger); - A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, companyId)) + A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, _identity.CompanyId)) .Returns((userEntityId.ToString(), "cl1", true)); A.CallTo(() => _provisioningManager.GetProviderUserLinkDataForCentralUserIdAsync(userEntityId.ToString())) .Returns(Enumerable.Repeat(new IdentityProviderLink("cl1", userEntityId.ToString(), "user-name"), 1).ToAsyncEnumerable()); // Act - var result = await sut.GetOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId, companyId).ConfigureAwait(false); + var result = await sut.GetOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId).ConfigureAwait(false); // Assert result.userName.Should().Be("user-name"); @@ -1955,20 +1939,19 @@ public async Task DeleteOwnCompanyUserIdentityProviderDataAsync_WithKeycloakErro var userEntityId = Guid.NewGuid(); var identityProviderId = Guid.NewGuid(); var companyUserId = Guid.NewGuid(); - var companyId = Guid.NewGuid(); var sut = new IdentityProviderBusinessLogic( _portalRepositories, _provisioningManager, _identityService, _options, _logger); - A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, companyId)) + A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, _identity.CompanyId)) .Returns((userEntityId.ToString(), "cl1", true)); A.CallTo(() => _provisioningManager.DeleteProviderUserLinkToCentralUserAsync(userEntityId.ToString(), "cl1")) .Throws(new KeycloakEntityNotFoundException("just a test")); // Act - async Task Act() => await sut.DeleteOwnCompanyUserIdentityProviderDataAsync(companyUserId, identityProviderId, companyId).ConfigureAwait(false); + async Task Act() => await sut.DeleteOwnCompanyUserIdentityProviderDataAsync(companyUserId, identityProviderId).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -1982,18 +1965,17 @@ public async Task DeleteOwnCompanyUserIdentityProviderDataAsync_WithValid_CallsE var userEntityId = Guid.NewGuid(); var identityProviderId = Guid.NewGuid(); var companyUserId = Guid.NewGuid(); - var companyId = Guid.NewGuid(); var sut = new IdentityProviderBusinessLogic( _portalRepositories, _provisioningManager, _identityService, _options, _logger); - A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, companyId)) + A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, _identity.CompanyId)) .Returns((userEntityId.ToString(), "cl1", true)); // Act - await sut.DeleteOwnCompanyUserIdentityProviderDataAsync(companyUserId, identityProviderId, companyId).ConfigureAwait(false); + await sut.DeleteOwnCompanyUserIdentityProviderDataAsync(companyUserId, identityProviderId).ConfigureAwait(false); // Assert A.CallTo(() => _provisioningManager.DeleteProviderUserLinkToCentralUserAsync(userEntityId.ToString(), "cl1")) @@ -2011,18 +1993,17 @@ public async Task GetOwnCompanyUsersIdentityProviderDataAsync_WithoutIdentityPro var userEntityId = Guid.NewGuid(); var identityProviderId = Guid.NewGuid(); var companyUserId = Guid.NewGuid(); - var companyId = Guid.NewGuid(); var sut = new IdentityProviderBusinessLogic( _portalRepositories, _provisioningManager, _identityService, _options, _logger); - A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, companyId)) + A.CallTo(() => _identityProviderRepository.GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, _identity.CompanyId)) .Returns((userEntityId.ToString(), "cl1", true)); // Act - async Task Act() => await sut.GetOwnCompanyUsersIdentityProviderDataAsync(Enumerable.Empty(), companyId, false).ToListAsync().ConfigureAwait(false); + async Task Act() => await sut.GetOwnCompanyUsersIdentityProviderDataAsync(Enumerable.Empty(), false).ToListAsync().ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -2033,7 +2014,6 @@ public async Task GetOwnCompanyUsersIdentityProviderDataAsync_WithoutIdentityPro public async Task GetOwnCompanyUsersIdentityProviderDataAsync_WithoutMatchingIdps_ThrowsControllerArgumentException() { // Arrange - var companyId = Guid.NewGuid(); var identityProviderId = Guid.NewGuid(); var sut = new IdentityProviderBusinessLogic( _portalRepositories, @@ -2041,15 +2021,172 @@ public async Task GetOwnCompanyUsersIdentityProviderDataAsync_WithoutMatchingIdp _identityService, _options, _logger); - A.CallTo(() => _identityProviderRepository.GetOwnCompanyIdentityProviderAliasDataUntracked(companyId, A>._)) + A.CallTo(() => _identityProviderRepository.GetOwnCompanyIdentityProviderAliasDataUntracked(_identity.CompanyId, A>._)) .Returns(Enumerable.Empty<(Guid, string)>().ToAsyncEnumerable()); // Act - async Task Act() => await sut.GetOwnCompanyUsersIdentityProviderDataAsync(Enumerable.Repeat(identityProviderId, 1), companyId, false).ToListAsync().ConfigureAwait(false); + async Task Act() => await sut.GetOwnCompanyUsersIdentityProviderDataAsync(Enumerable.Repeat(identityProviderId, 1), false).ToListAsync().ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); - ex.Message.Should().Be($"invalid identityProviders: [{identityProviderId}] for company {companyId} (Parameter 'identityProviderIds')"); + ex.Message.Should().Be($"invalid identityProviders: [{identityProviderId}] for company {_identity.CompanyId} (Parameter 'identityProviderIds')"); + } + + #endregion + + #region GetOwnIdentityProviderWithConnectedCompanies + + [Fact] + public async Task GetOwnIdentityProviderWithConnectedCompanies_WithDifferentCompany_ThrowsConflictException() + { + // Arrange + var identityProviderId = Guid.NewGuid(); + var sut = new IdentityProviderBusinessLogic( + _portalRepositories, + _provisioningManager, + _identityService, + _options, + _logger); + A.CallTo(() => _identityProviderRepository.GetOwnIdentityProviderWithConnectedCompanies(identityProviderId, _companyId)) + .Returns((string.Empty, IdentityProviderCategoryId.KEYCLOAK_OIDC, false, IdentityProviderTypeId.OWN, Enumerable.Empty())); + + // Act + async Task Act() => await sut.GetOwnIdentityProviderWithConnectedCompanies(identityProviderId).ConfigureAwait(false); + + // Assert + var ex = await Assert.ThrowsAsync(Act); + ex.Message.Should().Be($"identityProvider {identityProviderId} is not associated with company {_companyId}"); + } + + [Fact] + public async Task GetOwnIdentityProviderWithConnectedCompanies_WithAliasNull_ThrowsNotFoundException() + { + // Arrange + var identityProviderId = Guid.NewGuid(); + var sut = new IdentityProviderBusinessLogic( + _portalRepositories, + _provisioningManager, + _identityService, + _options, + _logger); + A.CallTo(() => _identityProviderRepository.GetOwnIdentityProviderWithConnectedCompanies(identityProviderId, _companyId)) + .Returns((null, IdentityProviderCategoryId.KEYCLOAK_OIDC, true, IdentityProviderTypeId.OWN, Enumerable.Empty())); + + // Act + async Task Act() => await sut.GetOwnIdentityProviderWithConnectedCompanies(identityProviderId).ConfigureAwait(false); + + // Assert + var ex = await Assert.ThrowsAsync(Act); + ex.Message.Should().Be($"identityProvider {identityProviderId} does not exist"); + } + + [Fact] + public async Task GetOwnIdentityProviderWithConnectedCompanies_WithOidcWithoutExistingKeycloakClient_CallsExpected() + { + // Arrange + var identityProviderId = Guid.NewGuid(); + var sut = new IdentityProviderBusinessLogic( + _portalRepositories, + _provisioningManager, + _identityService, + _options, + _logger); + A.CallTo(() => _identityProviderRepository.GetOwnIdentityProviderWithConnectedCompanies(identityProviderId, _companyId)) + .Returns(("cl1", IdentityProviderCategoryId.KEYCLOAK_OIDC, true, IdentityProviderTypeId.OWN, Enumerable.Empty())); + A.CallTo(() => _provisioningManager.GetCentralIdentityProviderDataOIDCAsync("cl1")) + .Throws(new KeycloakEntityNotFoundException("cl1 not existing")); + + // Act + var result = await sut.GetOwnIdentityProviderWithConnectedCompanies(identityProviderId).ConfigureAwait(false); + + // Assert + result.DisplayName.Should().BeNull(); + result.Enabled.Should().BeNull(); + } + + [Fact] + public async Task GetOwnIdentityProviderWithConnectedCompanies_WithValidOidc_CallsExpected() + { + // Arrange + var identityProviderId = Guid.NewGuid(); + var companyId = Guid.NewGuid(); + + var sut = new IdentityProviderBusinessLogic( + _portalRepositories, + _provisioningManager, + _identityService, + _options, + _logger); + A.CallTo(() => _identityProviderRepository.GetOwnIdentityProviderWithConnectedCompanies(identityProviderId, _companyId)) + .Returns(("cl1", IdentityProviderCategoryId.KEYCLOAK_OIDC, true, IdentityProviderTypeId.OWN, Enumerable.Repeat(new ConnectedCompanyData(companyId, "Test Company"), 1))); + A.CallTo(() => _provisioningManager.GetCentralIdentityProviderDataOIDCAsync("cl1")) + .Returns(_fixture.Build().With(x => x.Enabled, true).With(x => x.DisplayName, "dis-oidc").Create()); + A.CallTo(() => _provisioningManager.GetIdentityProviderMappers("cl1")) + .Returns(_fixture.CreateMany(3).ToAsyncEnumerable()); + + // Act + var result = await sut.GetOwnIdentityProviderWithConnectedCompanies(identityProviderId).ConfigureAwait(false); + + // Assert + result.DisplayName.Should().Be("dis-oidc"); + result.Enabled.Should().BeTrue(); + result.ConnectedCompanies.Should().ContainSingle().And.Satisfy(x => x.CompanyId == companyId); + } + + [Fact] + public async Task GetOwnIdentityProviderWithConnectedCompanies_WithSamlWithoutExistingKeycloakClient_CallsExpected() + { + // Arrange + var identityProviderId = Guid.NewGuid(); + var companyId = Guid.NewGuid(); + + var sut = new IdentityProviderBusinessLogic( + _portalRepositories, + _provisioningManager, + _identityService, + _options, + _logger); + A.CallTo(() => _identityProviderRepository.GetOwnIdentityProviderWithConnectedCompanies(identityProviderId, _companyId)) + .Returns(("saml-alias", IdentityProviderCategoryId.KEYCLOAK_SAML, true, IdentityProviderTypeId.OWN, Enumerable.Repeat(new ConnectedCompanyData(companyId, "Test Company"), 1))); + A.CallTo(() => _provisioningManager.GetCentralIdentityProviderDataSAMLAsync("saml-alias")) + .Throws(new KeycloakEntityNotFoundException("saml-alias")); + + // Act + var result = await sut.GetOwnIdentityProviderWithConnectedCompanies(identityProviderId).ConfigureAwait(false); + + // Assert + result.DisplayName.Should().BeNull(); + result.Enabled.Should().BeNull(); + result.ConnectedCompanies.Should().ContainSingle().And.Satisfy(x => x.CompanyId == companyId); + } + + [Fact] + public async Task GetOwnIdentityProviderWithConnectedCompanies_WithValidSaml_CallsExpected() + { + // Arrange + var identityProviderId = Guid.NewGuid(); + var companyId = Guid.NewGuid(); + + var sut = new IdentityProviderBusinessLogic( + _portalRepositories, + _provisioningManager, + _identityService, + _options, + _logger); + A.CallTo(() => _identityProviderRepository.GetOwnIdentityProviderWithConnectedCompanies(identityProviderId, _companyId)) + .Returns(("saml-alias", IdentityProviderCategoryId.KEYCLOAK_SAML, true, IdentityProviderTypeId.OWN, Enumerable.Repeat(new ConnectedCompanyData(companyId, "Test Company"), 1))); + A.CallTo(() => _provisioningManager.GetCentralIdentityProviderDataSAMLAsync("saml-alias")) + .Returns(_fixture.Build().With(x => x.Enabled, true).With(x => x.DisplayName, "dis-saml").Create()); + A.CallTo(() => _provisioningManager.GetIdentityProviderMappers("saml-alias")) + .Returns(_fixture.CreateMany(2).ToAsyncEnumerable()); + + // Act + var result = await sut.GetOwnIdentityProviderWithConnectedCompanies(identityProviderId).ConfigureAwait(false); + + // Assert + result.DisplayName.Should().Be("dis-saml"); + result.Enabled.Should().BeTrue(); + result.ConnectedCompanies.Should().ContainSingle().And.Satisfy(x => x.CompanyId == companyId); } #endregion diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/NetworkBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/NetworkBusinessLogicTests.cs index 0dffdb26cb..112d7fc0de 100644 --- a/tests/administration/Administration.Service.Tests/BusinessLogic/NetworkBusinessLogicTests.cs +++ b/tests/administration/Administration.Service.Tests/BusinessLogic/NetworkBusinessLogicTests.cs @@ -1,5 +1,4 @@ /******************************************************************************** - * Copyright (c) 2021, 2023 BMW Group AG * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional @@ -24,7 +23,6 @@ using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models; using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Configuration; -using Org.Eclipse.TractusX.Portal.Backend.Mailing.SendMail; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; @@ -53,7 +51,6 @@ public class NetworkBusinessLogicTests private readonly IIdentityService _identityService; private readonly IUserProvisioningService _userProvisioningService; private readonly INetworkRegistrationProcessHelper _networkRegistrationProcessHelper; - private readonly IMailingService _mailingService; private readonly IPortalRepositories _portalRepositories; private readonly ICompanyRepository _companyRepository; @@ -64,8 +61,6 @@ public class NetworkBusinessLogicTests private readonly IIdentityProviderRepository _identityProviderRepository; private readonly ICountryRepository _countryRepository; private readonly NetworkBusinessLogic _sut; - private readonly PartnerRegistrationSettings _settings; - private readonly IConsentRepository _consentRepository; public NetworkBusinessLogicTests() { @@ -78,7 +73,6 @@ public NetworkBusinessLogicTests() _portalRepositories = A.Fake(); _identityService = A.Fake(); _networkRegistrationProcessHelper = A.Fake(); - _mailingService = A.Fake(); _companyRepository = A.Fake(); _companyRolesRepository = A.Fake(); @@ -87,19 +81,17 @@ public NetworkBusinessLogicTests() _networkRepository = A.Fake(); _identityProviderRepository = A.Fake(); _countryRepository = A.Fake(); - _consentRepository = A.Fake(); - _settings = new PartnerRegistrationSettings + var settings = new PartnerRegistrationSettings { InitialRoles = new[] { new UserRoleConfig("cl1", new[] { "Company Admin" }) } }; var options = A.Fake>(); - A.CallTo(() => options.Value).Returns(_settings); + A.CallTo(() => options.Value).Returns(settings); A.CallTo(() => _identityService.IdentityData).Returns(_identity); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_companyRepository); - A.CallTo(() => _portalRepositories.GetInstance()).Returns(_consentRepository); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_companyRolesRepository); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_processStepRepository); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_applicationRepository); @@ -107,7 +99,7 @@ public NetworkBusinessLogicTests() A.CallTo(() => _portalRepositories.GetInstance()).Returns(_identityProviderRepository); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_countryRepository); - _sut = new NetworkBusinessLogic(_portalRepositories, _identityService, _userProvisioningService, _networkRegistrationProcessHelper, _mailingService, options); + _sut = new NetworkBusinessLogic(_portalRepositories, _identityService, _userProvisioningService, _networkRegistrationProcessHelper, options); SetupRepos(); } @@ -115,7 +107,6 @@ public NetworkBusinessLogicTests() #region HandlePartnerRegistration [Theory] - [InlineData(null)] [InlineData("")] [InlineData("TEST00000012")] [InlineData("BPNL1234567899")] @@ -367,8 +358,8 @@ public async Task HandlePartnerRegistration_WithUserCreationThrowsException_Thro A.CallTo(() => _processStepRepository.CreateProcess(ProcessTypeId.PARTNER_REGISTRATION)) .Returns(new Process(processId, default, default)); - A.CallTo(() => _userProvisioningService.CreateOwnCompanyIdpUsersAsync(A._, A>._, A._)) - .Returns(new[] { (Guid.Empty, "", (string?)null, (Exception?)new UnexpectedConditionException("Test")) }.ToAsyncEnumerable()); + A.CallTo(() => _userProvisioningService.GetOrCreateCompanyUser(A._, A._, A._, A._, A._, "BPNL00000001TEST")) + .Throws(new UnexpectedConditionException("Test message")); // Act async Task Act() => await _sut.HandlePartnerRegistration(data).ConfigureAwait(false); @@ -382,9 +373,6 @@ public async Task HandlePartnerRegistration_WithUserCreationThrowsException_Thro public async Task HandlePartnerRegistration_WithSingleIdpWithoutAlias_ThrowsServiceException() { // Arrange - var newCompanyId = Guid.NewGuid(); - var processId = Guid.NewGuid(); - var data = new PartnerRegistrationData( Guid.NewGuid(), "Test N2N", @@ -536,17 +524,17 @@ public async Task HandlePartnerRegistration_WithIdpNotSetAndOnlyOneIdp_CallsExpe x.ProcessId == newProcessId && x.ApplicationId == newApplicationId); - A.CallTo(() => _userProvisioningService.CreateOwnCompanyIdpUsersAsync(A._, A>._, A._)) + A.CallTo(() => _userProvisioningService.GetOrCreateCompanyUser(A._, "test-alias", A._, newCompanyId, IdpId, Bpnl)) .MustHaveHappenedOnceExactly(); A.CallTo(() => _identityProviderRepository.CreateCompanyIdentityProviders(A>.That.IsSameSequenceAs(new[] { new ValueTuple(newCompanyId, IdpId) }))) .MustHaveHappenedOnceExactly(); A.CallTo(() => _portalRepositories.SaveAsync()).MustHaveHappenedOnceExactly(); - A.CallTo(() => _mailingService.SendMails(A._, A>._, A>.That.IsSameSequenceAs(new[] { "OspWelcomeMail" }))) - .MustHaveHappenedOnceExactly(); } - [Fact] - public async Task HandlePartnerRegistration_WithValidData_CallsExpected() + [Theory] + [InlineData(Bpnl)] + [InlineData((string?)null)] + public async Task HandlePartnerRegistration_WithValidData_CallsExpected(string? bpnl) { // Arrange var newCompanyId = Guid.NewGuid(); @@ -564,7 +552,7 @@ public async Task HandlePartnerRegistration_WithValidData_CallsExpected() var data = new PartnerRegistrationData( Guid.NewGuid(), "Test N2N", - Bpnl, + bpnl, "Munich", "Street", "DE", @@ -636,8 +624,6 @@ public async Task HandlePartnerRegistration_WithValidData_CallsExpected() { networkRegistrations.Add(new NetworkRegistration(Guid.NewGuid(), externalId, companyId, pId, ospId, companyApplicationId, DateTimeOffset.UtcNow)); }); - A.CallTo(() => _userProvisioningService.CreateOwnCompanyIdpUsersAsync(A._, A>._, A._)) - .Returns(new[] { (Guid.NewGuid(), "ironman", (string?)"testpw", (Exception?)null) }.ToAsyncEnumerable()); // Act await _sut.HandlePartnerRegistration(data).ConfigureAwait(false); @@ -671,13 +657,11 @@ public async Task HandlePartnerRegistration_WithValidData_CallsExpected() x.ProcessId == newProcessId && x.ApplicationId == newApplicationId); - A.CallTo(() => _userProvisioningService.CreateOwnCompanyIdpUsersAsync(A._, A>._, A._)) + A.CallTo(() => _userProvisioningService.GetOrCreateCompanyUser(A._, "test-alias", A._, newCompanyId, IdpId, bpnl)) .MustHaveHappenedOnceExactly(); A.CallTo(() => _identityProviderRepository.CreateCompanyIdentityProviders(A>.That.IsSameSequenceAs(new[] { new ValueTuple(newCompanyId, IdpId) }))) .MustHaveHappenedOnceExactly(); A.CallTo(() => _portalRepositories.SaveAsync()).MustHaveHappenedOnceExactly(); - A.CallTo(() => _mailingService.SendMails(A._, A>._, A>.That.IsSameSequenceAs(new[] { "OspWelcomeMail" }))) - .MustHaveHappenedOnceExactly(); } #endregion @@ -700,240 +684,6 @@ public async Task RetriggerSynchronizeUser_CallsExpected() #endregion - #region Submit - - [Fact] - public async Task Submit_WithNotExistingSubmitData_ThrowsNotFoundException() - { - // Arrange - var data = _fixture.Create(); - A.CallTo(() => _networkRepository.GetSubmitData(_identity.CompanyId, _identity.UserId, A>._)) - .Returns(new ValueTuple>, bool, IEnumerable>>, Guid?>()); - - // Act - async Task Act() => await _sut.Submit(data, CancellationToken.None).ConfigureAwait(false); - - // Assert - var ex = await Assert.ThrowsAsync(Act); - ex.Message.Should().Be($"Company {_identity.CompanyId} not found"); - } - - [Fact] - public async Task Submit_WithUserNotInRole_ThrowsForbiddenException() - { - // Arrange - var data = _fixture.Create(); - A.CallTo(() => _networkRepository.GetSubmitData(_identity.CompanyId, _identity.UserId, A>._)) - .Returns((true, Enumerable.Empty>(), false, Enumerable.Empty>>(), null)); - - // Act - async Task Act() => await _sut.Submit(data, CancellationToken.None).ConfigureAwait(false); - - // Assert - var ex = await Assert.ThrowsAsync(Act); - ex.Message.Should().Be($"User must be in role {string.Join(",", _settings.InitialRoles.SelectMany(x => x.UserRoleNames))}"); - } - - [Fact] - public async Task Submit_WithoutCompanyApplications_ThrowsConflictException() - { - // Arrange - var data = _fixture.Create(); - A.CallTo(() => _networkRepository.GetSubmitData(_identity.CompanyId, _identity.UserId, A>._)) - .Returns((true, Enumerable.Empty>(), true, Enumerable.Empty>>(), null)); - - // Act - async Task Act() => await _sut.Submit(data, CancellationToken.None).ConfigureAwait(false); - - // Assert - var ex = await Assert.ThrowsAsync(Act); - ex.Message.Should().Be($"Company {_identity.CompanyId} has no or more than one application"); - } - - [Fact] - public async Task Submit_WithMultipleCompanyApplications_ThrowsConflictException() - { - // Arrange - var data = _fixture.Create(); - A.CallTo(() => _networkRepository.GetSubmitData(_identity.CompanyId, _identity.UserId, A>._)) - .Returns((true, _fixture.CreateMany>(2), true, Enumerable.Empty>>(), null)); - - // Act - async Task Act() => await _sut.Submit(data, CancellationToken.None).ConfigureAwait(false); - - // Assert - var ex = await Assert.ThrowsAsync(Act); - ex.Message.Should().Be($"Company {_identity.CompanyId} has no or more than one application"); - } - - [Fact] - public async Task Submit_WithWrongApplicationStatus_ThrowsConflictException() - { - // Arrange - var applicationId = Guid.NewGuid(); - var data = _fixture.Create(); - A.CallTo(() => _networkRepository.GetSubmitData(_identity.CompanyId, _identity.UserId, A>._)) - .Returns((true, Enumerable.Repeat>((applicationId, CompanyApplicationStatusId.VERIFY, null), 1), true, Enumerable.Empty>>(), Guid.NewGuid())); - - // Act - async Task Act() => await _sut.Submit(data, CancellationToken.None).ConfigureAwait(false); - - // Assert - var ex = await Assert.ThrowsAsync(Act); - ex.Message.Should().Be($"Application {applicationId} is not in state CREATED"); - } - - [Fact] - public async Task Submit_WithOneMissingAgreement_ThrowsConflictException() - { - // Arrange - var applicationId = Guid.NewGuid(); - var agreementId = Guid.NewGuid(); - var notExistingAgreementId = Guid.NewGuid(); - var data = new PartnerSubmitData( - new[] { CompanyRoleId.APP_PROVIDER }, - new[] { new AgreementConsentData(agreementId, ConsentStatusId.ACTIVE) }); - var companyRoleIds = new ValueTuple>[] - { - (CompanyRoleId.APP_PROVIDER, new [] {agreementId, notExistingAgreementId}) - }; - A.CallTo(() => _networkRepository.GetSubmitData(_identity.CompanyId, _identity.UserId, A>._)) - .Returns((true, Enumerable.Repeat>((applicationId, CompanyApplicationStatusId.CREATED, null), 1), true, companyRoleIds, Guid.NewGuid())); - - // Act - async Task Act() => await _sut.Submit(data, CancellationToken.None).ConfigureAwait(false); - - // Assert - var ex = await Assert.ThrowsAsync(Act); - ex.Message.Should().Be($"All Agreements for the company roles must be agreed to, missing agreementIds: {notExistingAgreementId} (Parameter 'Agreements')"); - } - - [Fact] - public async Task Submit_WithOneInactiveAgreement_ThrowsConflictException() - { - // Arrange - var applicationId = Guid.NewGuid(); - var agreementId = Guid.NewGuid(); - var inactiveAgreementId = Guid.NewGuid(); - var data = new PartnerSubmitData( - new[] { CompanyRoleId.APP_PROVIDER }, - new[] - { - new AgreementConsentData(agreementId, ConsentStatusId.ACTIVE), - new AgreementConsentData(inactiveAgreementId, ConsentStatusId.INACTIVE), - }); - var companyRoleIds = new ValueTuple>[] - { - (CompanyRoleId.APP_PROVIDER, new [] {agreementId, inactiveAgreementId}) - }; - A.CallTo(() => _networkRepository.GetSubmitData(_identity.CompanyId, _identity.UserId, A>._)) - .Returns((true, Enumerable.Repeat>((applicationId, CompanyApplicationStatusId.CREATED, null), 1), true, companyRoleIds, Guid.NewGuid())); - - // Act - async Task Act() => await _sut.Submit(data, CancellationToken.None).ConfigureAwait(false); - - // Assert - var ex = await Assert.ThrowsAsync(Act); - ex.Message.Should().Be($"All agreements must be agreed to. Agreements that are not active: {inactiveAgreementId} (Parameter 'Agreements')"); - } - - [Fact] - public async Task Submit_WithoutProcessId_ThrowsConflictException() - { - // Arrange - var applicationId = Guid.NewGuid(); - var agreementId = Guid.NewGuid(); - var agreementId1 = Guid.NewGuid(); - var data = new PartnerSubmitData( - new[] { CompanyRoleId.APP_PROVIDER }, - new[] - { - new AgreementConsentData(agreementId, ConsentStatusId.ACTIVE), - new AgreementConsentData(agreementId1, ConsentStatusId.ACTIVE), - }); - var companyRoleIds = new ValueTuple>[] - { - (CompanyRoleId.APP_PROVIDER, new [] {agreementId, agreementId1}) - }; - A.CallTo(() => _networkRepository.GetSubmitData(_identity.CompanyId, _identity.UserId, A>._)) - .Returns((true, Enumerable.Repeat>((applicationId, CompanyApplicationStatusId.CREATED, "https://callback.url"), 1), true, companyRoleIds, null)); - // Act - async Task Act() => await _sut.Submit(data, CancellationToken.None).ConfigureAwait(false); - - // Assert - var ex = await Assert.ThrowsAsync(Act); - ex.Message.Should().Be("There must be an process"); - } - - [Fact] - public async Task Submit_WithValidData_CallsExpected() - { - // Arrange - var applicationId = Guid.NewGuid(); - var agreementId = Guid.NewGuid(); - var agreementId1 = Guid.NewGuid(); - var processSteps = new List(); - var application = new CompanyApplication(applicationId, _identity.CompanyId, CompanyApplicationStatusId.CREATED, CompanyApplicationTypeId.EXTERNAL, DateTimeOffset.UtcNow); - - var data = new PartnerSubmitData( - new[] { CompanyRoleId.APP_PROVIDER }, - new[] - { - new AgreementConsentData(agreementId, ConsentStatusId.ACTIVE), - new AgreementConsentData(agreementId1, ConsentStatusId.ACTIVE), - }); - var companyRoleIds = new ValueTuple>[] - { - (CompanyRoleId.APP_PROVIDER, new [] {agreementId, agreementId1}) - }; - A.CallTo(() => _networkRepository.GetSubmitData(_identity.CompanyId, _identity.UserId, A>._)) - .Returns((true, Enumerable.Repeat>((applicationId, CompanyApplicationStatusId.CREATED, "https://callback.url"), 1), true, companyRoleIds, Guid.NewGuid())); - A.CallTo(() => _applicationRepository.AttachAndModifyCompanyApplication(applicationId, A>._)) - .Invokes((Guid _, Action setOptionalFields) => - { - setOptionalFields.Invoke(application); - }); - A.CallTo(() => _processStepRepository.CreateProcessStepRange(A>.That.Matches(x => - x.Count() == 1 && - x.Single().ProcessStepTypeId == ProcessStepTypeId.TRIGGER_CALLBACK_OSP_SUBMITTED))) - .Invokes((IEnumerable<(ProcessStepTypeId ProcessStepTypeId, ProcessStepStatusId ProcessStepStatusId, Guid ProcessId)> steps) => - { - processSteps.AddRange(steps.Select(x => new ProcessStep(Guid.NewGuid(), x.ProcessStepTypeId, x.ProcessStepStatusId, x.ProcessId, DateTimeOffset.UtcNow))); - }); - var consents = new List(); - var now = DateTimeOffset.UtcNow; - A.CallTo(() => _consentRepository.CreateConsents(A>._)) - .Invokes((IEnumerable<(Guid AgreementId, Guid CompanyId, Guid CompanyUserId, ConsentStatusId ConsentStatusId)> agreementConsents) => - { - foreach (var x in agreementConsents) - { - consents.Add(new Consent(Guid.NewGuid(), x.AgreementId, x.CompanyId, x.CompanyUserId, x.ConsentStatusId, now)); - } - }); - // Act - await _sut.Submit(data, CancellationToken.None).ConfigureAwait(false); - - // Assert - application.ApplicationStatusId.Should().Be(CompanyApplicationStatusId.SUBMITTED); - A.CallTo(() => _consentRepository.CreateConsents(A>._)) - .MustHaveHappenedOnceExactly(); - consents.Should().HaveCount(2) - .And.AllSatisfy(x => x.Should().Match(x => - x.CompanyId == _identity.CompanyId && - x.CompanyUserId == _identity.UserId && - x.ConsentStatusId == ConsentStatusId.ACTIVE)) - .And.Satisfy( - x => x.AgreementId == agreementId, - x => x.AgreementId == agreementId1); - A.CallTo(() => _portalRepositories.SaveAsync()) - .MustHaveHappenedOnceExactly(); - processSteps.Should().ContainSingle().Which.Should().Match(x => - x.ProcessStepTypeId == ProcessStepTypeId.TRIGGER_CALLBACK_OSP_SUBMITTED && - x.ProcessStepStatusId == ProcessStepStatusId.TODO); - } - - #endregion - #region Setup private void SetupRepos() diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/PartnerNetworkBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/PartnerNetworkBusinessLogicTests.cs new file mode 100644 index 0000000000..1409fecedf --- /dev/null +++ b/tests/administration/Administration.Service.Tests/BusinessLogic/PartnerNetworkBusinessLogicTests.cs @@ -0,0 +1,64 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 BMW Group AG + * Copyright (c) 2021, 2023 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.PortalBackend.DBAccess; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; + +namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLogic.Tests; + +public class PartnerNetworkBusinessLogicTests +{ + private readonly IPortalRepositories _portalRepositories; + private readonly ICompanyRepository _companyRepository; + private readonly IPartnerNetworkBusinessLogic _sut; + private readonly IFixture _fixture; + + public PartnerNetworkBusinessLogicTests() + { + _fixture = new Fixture().Customize(new AutoFakeItEasyCustomization { ConfigureMembers = true }); + _fixture.Behaviors.OfType().ToList() + .ForEach(b => _fixture.Behaviors.Remove(b)); + _fixture.Behaviors.Add(new OmitOnRecursionBehavior()); + + _portalRepositories = A.Fake(); + _companyRepository = A.Fake(); + + A.CallTo(() => _portalRepositories.GetInstance()).Returns(_companyRepository); + + _sut = new PartnerNetworkBusinessLogic(_portalRepositories); + } + + [Fact] + public async Task GetAllMemberCompaniesBPNAsync_ReturnsExpected() + { + //Arrange + var bpnIds = _fixture.CreateMany(3); + A.CallTo(() => _companyRepository.GetAllMemberCompaniesBPNAsync(A>._)) + .Returns(_fixture.CreateMany(2).ToAsyncEnumerable()); + + // Act + var result = await _sut.GetAllMemberCompaniesBPNAsync(bpnIds).ToListAsync().ConfigureAwait(false); + + // Assert + result.Should().NotBeNull().And.HaveCount(2); + A.CallTo(() => _companyRepository.GetAllMemberCompaniesBPNAsync(A>.That.IsSameAs(bpnIds))).MustHaveHappenedOnceExactly(); + + } +} diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/RegistrationBusinessLogicTest.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/RegistrationBusinessLogicTest.cs index 0445d3a35a..8d3c875bd0 100644 --- a/tests/administration/Administration.Service.Tests/BusinessLogic/RegistrationBusinessLogicTest.cs +++ b/tests/administration/Administration.Service.Tests/BusinessLogic/RegistrationBusinessLogicTest.cs @@ -18,6 +18,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLogic; using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models; @@ -98,7 +99,9 @@ public RegistrationBusinessLogicTest() A.CallTo(() => _portalRepositories.GetInstance()).Returns(_processStepRepository); A.CallTo(() => options.Value).Returns(settings); - _logic = new RegistrationBusinessLogic(_portalRepositories, options, _mailingService, _checklistService, _clearinghouseBusinessLogic, _sdFactoryBusinessLogic); + var logger = A.Fake>(); + + _logic = new RegistrationBusinessLogic(_portalRepositories, options, _mailingService, _checklistService, _clearinghouseBusinessLogic, _sdFactoryBusinessLogic, logger); } #region GetCompanyApplicationDetailsAsync diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/ServiceAccountBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/ServiceAccountBusinessLogicTests.cs index c255a5c163..67f45502c2 100644 --- a/tests/administration/Administration.Service.Tests/BusinessLogic/ServiceAccountBusinessLogicTests.cs +++ b/tests/administration/Administration.Service.Tests/BusinessLogic/ServiceAccountBusinessLogicTests.cs @@ -59,6 +59,7 @@ public class ServiceAccountBusinessLogicTests private readonly IPortalRepositories _portalRepositories; private readonly IFixture _fixture; private readonly IOptions _options; + private readonly IIdentityService _identityService; public ServiceAccountBusinessLogicTests() { @@ -76,6 +77,9 @@ public ServiceAccountBusinessLogicTests() _portalRepositories = A.Fake(); _serviceAccountCreation = A.Fake(); + _identityService = A.Fake(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity); + _options = Options.Create(new ServiceAccountSettings { ClientId = ClientId @@ -90,10 +94,10 @@ public async Task CreateOwnCompanyServiceAccountAsync_WithValidInput_ReturnsCrea // Arrange SetupCreateOwnCompanyServiceAccount(); var serviceAccountCreationInfos = new ServiceAccountCreationInfo("TheName", "Just a short description", IamClientAuthMethod.SECRET, Enumerable.Repeat(UserRoleId1, 1)); - var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, _serviceAccountCreation); + var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, _serviceAccountCreation, _identityService); // Act - var result = await sut.CreateOwnCompanyServiceAccountAsync(serviceAccountCreationInfos, _identity.CompanyId).ConfigureAwait(false); + var result = await sut.CreateOwnCompanyServiceAccountAsync(serviceAccountCreationInfos).ConfigureAwait(false); // Assert result.Should().NotBeNull(); @@ -105,12 +109,13 @@ public async Task CreateOwnCompanyServiceAccountAsync_WithInvalidUser_NotFoundEx { // Arrange var identity = _fixture.Create(); + A.CallTo(() => _identityService.IdentityData).Returns(identity); SetupCreateOwnCompanyServiceAccount(); var serviceAccountCreationInfos = new ServiceAccountCreationInfo("TheName", "Just a short description", IamClientAuthMethod.SECRET, Enumerable.Repeat(UserRoleId1, 1)); - var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, _serviceAccountCreation); + var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, _serviceAccountCreation, _identityService); // Act - async Task Act() => await sut.CreateOwnCompanyServiceAccountAsync(serviceAccountCreationInfos, identity.CompanyId).ConfigureAwait(false); + async Task Act() => await sut.CreateOwnCompanyServiceAccountAsync(serviceAccountCreationInfos).ConfigureAwait(false); // Assert var exception = await Assert.ThrowsAsync(Act); @@ -123,10 +128,10 @@ public async Task CreateOwnCompanyServiceAccountAsync_WithEmptyName_ThrowsContro // Arrange SetupCreateOwnCompanyServiceAccount(); var serviceAccountCreationInfos = new ServiceAccountCreationInfo(string.Empty, "Just a short description", IamClientAuthMethod.SECRET, Enumerable.Repeat(UserRoleId1, 1)); - var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, _serviceAccountCreation); + var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, _serviceAccountCreation, _identityService); // Act - async Task Act() => await sut.CreateOwnCompanyServiceAccountAsync(serviceAccountCreationInfos, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await sut.CreateOwnCompanyServiceAccountAsync(serviceAccountCreationInfos).ConfigureAwait(false); // Assert var exception = await Assert.ThrowsAsync(Act); @@ -140,10 +145,10 @@ public async Task CreateOwnCompanyServiceAccountAsync_WithInvalidIamClientAuthMe // Arrange SetupCreateOwnCompanyServiceAccount(); var serviceAccountCreationInfos = new ServiceAccountCreationInfo("TheName", "Just a short description", IamClientAuthMethod.JWT, Enumerable.Repeat(UserRoleId1, 1)); - var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, _serviceAccountCreation); + var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, _serviceAccountCreation, _identityService); // Act - async Task Act() => await sut.CreateOwnCompanyServiceAccountAsync(serviceAccountCreationInfos, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await sut.CreateOwnCompanyServiceAccountAsync(serviceAccountCreationInfos).ConfigureAwait(false); // Assert var exception = await Assert.ThrowsAsync(Act); @@ -158,10 +163,10 @@ public async Task CreateOwnCompanyServiceAccountAsync_WithInvalidUserRoleId_Thro var wrongUserRoleId = Guid.NewGuid(); SetupCreateOwnCompanyServiceAccount(); var serviceAccountCreationInfos = new ServiceAccountCreationInfo("TheName", "Just a short description", IamClientAuthMethod.SECRET, new[] { UserRoleId1, wrongUserRoleId }); - var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, _serviceAccountCreation); + var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, _serviceAccountCreation, _identityService); // Act - async Task Act() => await sut.CreateOwnCompanyServiceAccountAsync(serviceAccountCreationInfos, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await sut.CreateOwnCompanyServiceAccountAsync(serviceAccountCreationInfos).ConfigureAwait(false); // Assert var exception = await Assert.ThrowsAsync(Act); @@ -178,10 +183,10 @@ public async Task GetOwnCompanyServiceAccountDetailsAsync_WithValidInput_GetsAll { // Arrange SetupGetOwnCompanyServiceAccountDetails(); - var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!); + var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!, _identityService); // Act - var result = await sut.GetOwnCompanyServiceAccountDetailsAsync(ValidServiceAccountId, _identity.CompanyId).ConfigureAwait(false); + var result = await sut.GetOwnCompanyServiceAccountDetailsAsync(ValidServiceAccountId).ConfigureAwait(false); // Assert result.Should().NotBeNull(); @@ -194,10 +199,11 @@ public async Task GetOwnCompanyServiceAccountDetailsAsync_WithInvalidUser_NotFou // Arrange SetupGetOwnCompanyServiceAccountDetails(); var invalidCompanyId = Guid.NewGuid(); - var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { CompanyId = invalidCompanyId }); + var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!, _identityService); // Act - async Task Act() => await sut.GetOwnCompanyServiceAccountDetailsAsync(ValidServiceAccountId, invalidCompanyId).ConfigureAwait(false); + async Task Act() => await sut.GetOwnCompanyServiceAccountDetailsAsync(ValidServiceAccountId).ConfigureAwait(false); // Assert var exception = await Assert.ThrowsAsync(Act); @@ -210,10 +216,10 @@ public async Task GetOwnCompanyServiceAccountDetailsAsync_WithInvalidServiceAcco // Arrange SetupGetOwnCompanyServiceAccountDetails(); var invalidServiceAccountId = Guid.NewGuid(); - var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!); + var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!, _identityService); // Act - async Task Act() => await sut.GetOwnCompanyServiceAccountDetailsAsync(invalidServiceAccountId, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await sut.GetOwnCompanyServiceAccountDetailsAsync(invalidServiceAccountId).ConfigureAwait(false); // Assert var exception = await Assert.ThrowsAsync(Act); @@ -229,10 +235,10 @@ public async Task ResetOwnCompanyServiceAccountSecretAsync_WithValidInput_GetsAl { // Arrange SetupResetOwnCompanyServiceAccountSecret(); - var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!); + var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!, _identityService); // Act - var result = await sut.ResetOwnCompanyServiceAccountSecretAsync(ValidServiceAccountId, _identity.CompanyId).ConfigureAwait(false); + var result = await sut.ResetOwnCompanyServiceAccountSecretAsync(ValidServiceAccountId).ConfigureAwait(false); // Assert result.Should().NotBeNull(); @@ -245,10 +251,11 @@ public async Task ResetOwnCompanyServiceAccountSecretAsync_WithInvalidUser_NotFo // Arrange SetupResetOwnCompanyServiceAccountSecret(); var invalidUser = _fixture.Create(); - var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!); + A.CallTo(() => _identityService.IdentityData).Returns(invalidUser); + var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!, _identityService); // Act - async Task Act() => await sut.ResetOwnCompanyServiceAccountSecretAsync(ValidServiceAccountId, invalidUser.CompanyId).ConfigureAwait(false); + async Task Act() => await sut.ResetOwnCompanyServiceAccountSecretAsync(ValidServiceAccountId).ConfigureAwait(false); // Assert var exception = await Assert.ThrowsAsync(Act); @@ -261,10 +268,10 @@ public async Task ResetOwnCompanyServiceAccountSecretAsync_WithInvalidServiceAcc // Arrange SetupResetOwnCompanyServiceAccountSecret(); var invalidServiceAccountId = Guid.NewGuid(); - var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!); + var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!, _identityService); // Act - async Task Act() => await sut.ResetOwnCompanyServiceAccountSecretAsync(invalidServiceAccountId, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await sut.ResetOwnCompanyServiceAccountSecretAsync(invalidServiceAccountId).ConfigureAwait(false); // Assert var exception = await Assert.ThrowsAsync(Act); @@ -281,10 +288,10 @@ public async Task UpdateOwnCompanyServiceAccountDetailsAsync_WithValidData_Retur // Arrange SetupUpdateOwnCompanyServiceAccountDetails(); var data = new ServiceAccountEditableDetails(ValidServiceAccountId, "new name", "changed description", IamClientAuthMethod.SECRET); - var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!); + var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!, _identityService); // Act - var result = await sut.UpdateOwnCompanyServiceAccountDetailsAsync(ValidServiceAccountId, data, _identity.CompanyId).ConfigureAwait(false); + var result = await sut.UpdateOwnCompanyServiceAccountDetailsAsync(ValidServiceAccountId, data).ConfigureAwait(false); // Assert result.Should().NotBeNull(); @@ -297,10 +304,10 @@ public async Task UpdateOwnCompanyServiceAccountDetailsAsync_WithInvalidAuthMeth // Arrange SetupUpdateOwnCompanyServiceAccountDetails(); var data = new ServiceAccountEditableDetails(ValidServiceAccountId, "new name", "changed description", IamClientAuthMethod.JWT); - var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!); + var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!, _identityService); // Act - async Task Act() => await sut.UpdateOwnCompanyServiceAccountDetailsAsync(ValidServiceAccountId, data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await sut.UpdateOwnCompanyServiceAccountDetailsAsync(ValidServiceAccountId, data).ConfigureAwait(false); // Assert var exception = await Assert.ThrowsAsync(Act); @@ -313,10 +320,10 @@ public async Task UpdateOwnCompanyServiceAccountDetailsAsync_WithDifferentServic // Arrange SetupUpdateOwnCompanyServiceAccountDetails(); var data = new ServiceAccountEditableDetails(ValidServiceAccountId, "new name", "changed description", IamClientAuthMethod.SECRET); - var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!); + var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!, _identityService); // Act - async Task Act() => await sut.UpdateOwnCompanyServiceAccountDetailsAsync(Guid.NewGuid(), data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await sut.UpdateOwnCompanyServiceAccountDetailsAsync(Guid.NewGuid(), data).ConfigureAwait(false); // Assert var exception = await Assert.ThrowsAsync(Act); @@ -332,10 +339,10 @@ public async Task UpdateOwnCompanyServiceAccountDetailsAsync_WithNotExistingServ A.CallTo(() => _serviceAccountRepository.GetOwnCompanyServiceAccountWithIamClientIdAsync(invalidServiceAccountId, _identity.CompanyId)) .Returns((CompanyServiceAccountWithRoleDataClientId?)null); var data = new ServiceAccountEditableDetails(invalidServiceAccountId, "new name", "changed description", IamClientAuthMethod.SECRET); - var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!); + var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!, _identityService); // Act - async Task Act() => await sut.UpdateOwnCompanyServiceAccountDetailsAsync(invalidServiceAccountId, data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await sut.UpdateOwnCompanyServiceAccountDetailsAsync(invalidServiceAccountId, data).ConfigureAwait(false); // Assert var exception = await Assert.ThrowsAsync(Act); @@ -353,10 +360,10 @@ public async Task UpdateOwnCompanyServiceAccountDetailsAsync_WithInactiveService A.CallTo(() => _serviceAccountRepository.GetOwnCompanyServiceAccountWithIamClientIdAsync(InactiveServiceAccount, _identity.CompanyId)) .Returns(inactive); var data = new ServiceAccountEditableDetails(InactiveServiceAccount, "new name", "changed description", IamClientAuthMethod.SECRET); - var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!); + var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!, _identityService); // Act - async Task Act() => await sut.UpdateOwnCompanyServiceAccountDetailsAsync(InactiveServiceAccount, data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await sut.UpdateOwnCompanyServiceAccountDetailsAsync(InactiveServiceAccount, data).ConfigureAwait(false); // Assert var exception = await Assert.ThrowsAsync(Act); @@ -376,10 +383,10 @@ public async Task GetOwnCompanyServiceAccountsDataAsync_GetsExpectedData() .Returns((int skip, int take) => Task.FromResult((Pagination.Source?)new Pagination.Source(data.Count(), data.Skip(skip).Take(take)))); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_serviceAccountRepository); - var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!); + var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!, _identityService); // Act - var result = await sut.GetOwnCompanyServiceAccountsDataAsync(1, 10, _identity.CompanyId, null, null).ConfigureAwait(false); + var result = await sut.GetOwnCompanyServiceAccountsDataAsync(1, 10, null, null).ConfigureAwait(false); // Assert result.Should().NotBeNull(); @@ -397,10 +404,10 @@ public async Task DeleteOwnCompanyServiceAccountAsync_WithNotExistingServiceAcco var serviceAccountId = Guid.NewGuid(); SetupDeleteOwnCompanyServiceAccount(false, false); - var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!); + var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!, _identityService); // Act - async Task Act() => await sut.DeleteOwnCompanyServiceAccountAsync(serviceAccountId, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await sut.DeleteOwnCompanyServiceAccountAsync(serviceAccountId).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -413,10 +420,10 @@ public async Task DeleteOwnCompanyServiceAccountAsync_WithExistingOfferSubscript // Arrange SetupDeleteOwnCompanyServiceAccountForValidOfferSubscription(); - var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!); + var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!, _identityService); // Act - async Task Act() => await sut.DeleteOwnCompanyServiceAccountAsync(ValidServiceAccountId, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await sut.DeleteOwnCompanyServiceAccountAsync(ValidServiceAccountId).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -429,10 +436,10 @@ public async Task DeleteOwnCompanyServiceAccountAsync_WithInvalidConnectorStatus // Arrange SetupDeleteOwnCompanyServiceAccountForInvalidConnectorStatus(); - var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!); + var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!, _identityService); // Act - async Task Act() => await sut.DeleteOwnCompanyServiceAccountAsync(ValidServiceAccountId, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await sut.DeleteOwnCompanyServiceAccountAsync(ValidServiceAccountId).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -455,10 +462,10 @@ public async Task DeleteOwnCompanyServiceAccountAsync_WithoutClient_CallsExpecte .With(x => x.CompanyServiceAccountId, ValidServiceAccountId) .Create(); SetupDeleteOwnCompanyServiceAccount(withServiceAccount, withClient, connector, identity); - var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!); + var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!, _identityService); // Act - await sut.DeleteOwnCompanyServiceAccountAsync(ValidServiceAccountId, _identity.CompanyId).ConfigureAwait(false); + await sut.DeleteOwnCompanyServiceAccountAsync(ValidServiceAccountId).ConfigureAwait(false); // Assert if (withClient) @@ -491,10 +498,10 @@ public async Task GetServiceAccountRolesAsync_GetsExpectedData() A.CallTo(() => _portalRepositories.GetInstance()).Returns(_userRolesRepository); - IServiceAccountBusinessLogic sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!); + IServiceAccountBusinessLogic sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!, _identityService); // Act - var result = await sut.GetServiceAccountRolesAsync(_identity.CompanyId, null).ToListAsync().ConfigureAwait(false); + var result = await sut.GetServiceAccountRolesAsync(null).ToListAsync().ConfigureAwait(false); // Assert A.CallTo(() => _userRolesRepository.GetServiceAccountRolesAsync(_identity.CompanyId, ClientId, A._)).MustHaveHappenedOnceExactly(); diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/SubscriptionConfigurationBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/SubscriptionConfigurationBusinessLogicTests.cs index efd4e2d466..a5deb6ffb6 100644 --- a/tests/administration/Administration.Service.Tests/BusinessLogic/SubscriptionConfigurationBusinessLogicTests.cs +++ b/tests/administration/Administration.Service.Tests/BusinessLogic/SubscriptionConfigurationBusinessLogicTests.cs @@ -47,6 +47,7 @@ public class SubscriptionConfigurationBusinessLogicTests private readonly IPortalRepositories _portalRepositories; private readonly IFixture _fixture; private readonly ISubscriptionConfigurationBusinessLogic _sut; + private readonly IIdentityService _identityService; public SubscriptionConfigurationBusinessLogicTests() { @@ -62,11 +63,14 @@ public SubscriptionConfigurationBusinessLogicTests() _serviceProviderDetails = new HashSet(); + _identityService = A.Fake(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity); + A.CallTo(() => _portalRepositories.GetInstance()).Returns(_companyRepository); A.CallTo(() => _portalRepositories.GetInstance()) .Returns(_offerSubscriptionsRepository); - _sut = new SubscriptionConfigurationBusinessLogic(_offerSubscriptionProcessService, _portalRepositories); + _sut = new SubscriptionConfigurationBusinessLogic(_offerSubscriptionProcessService, _portalRepositories, _identityService); } #region GetProcessStepsForSubscription @@ -189,7 +193,7 @@ public async Task SetProviderCompanyDetailsAsync_EmptyProviderDetailsId_ReturnsE .Returns((Guid.Empty, null!)); // Act - await _sut.SetProviderCompanyDetailsAsync(providerDetailData, _identity.CompanyId).ConfigureAwait(false); + await _sut.SetProviderCompanyDetailsAsync(providerDetailData).ConfigureAwait(false); // Assert A.CallTo(() => _companyRepository.CreateProviderCompanyDetail(A._, A._, A>._)).MustHaveHappened(); @@ -224,7 +228,7 @@ public async Task SetProviderCompanyDetailsAsync_WithServiceProviderDetailsId_Re }); //Act - await _sut.SetProviderCompanyDetailsAsync(providerDetailData, _identity.CompanyId).ConfigureAwait(false); + await _sut.SetProviderCompanyDetailsAsync(providerDetailData).ConfigureAwait(false); //Assert A.CallTo(() => _companyRepository.CreateProviderCompanyDetail(A._, A._, null)).MustNotHaveHappened(); @@ -240,11 +244,12 @@ public async Task SetProviderCompanyDetailsAsync_WithServiceProviderDetailsId_Re public async Task SetServiceProviderCompanyDetailsAsync_WithUnknownUser_ThrowsException() { //Arrange + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { CompanyId = Guid.NewGuid() }); SetupProviderCompanyDetails(); var providerDetailData = new ProviderDetailData("https://www.service-url.com", null); //Act - async Task Action() => await _sut.SetProviderCompanyDetailsAsync(providerDetailData, Guid.NewGuid()).ConfigureAwait(false); + async Task Action() => await _sut.SetProviderCompanyDetailsAsync(providerDetailData).ConfigureAwait(false); //Assert await Assert.ThrowsAsync(Action); @@ -256,11 +261,12 @@ public async Task SetServiceProviderCompanyDetailsAsync_WithUnknownUser_ThrowsEx public async Task SetServiceProviderCompanyDetailsAsync_WithNotServiceProvider_ThrowsException() { //Arrange + A.CallTo(() => _identityService.IdentityData).Returns(_noServiceProviderIdentity); SetupProviderCompanyDetails(); var providerDetailData = new ProviderDetailData("https://www.service-url.com", null); //Act - async Task Action() => await _sut.SetProviderCompanyDetailsAsync(providerDetailData, _noServiceProviderIdentity.CompanyId).ConfigureAwait(false); + async Task Action() => await _sut.SetProviderCompanyDetailsAsync(providerDetailData).ConfigureAwait(false); //Assert var ex = await Assert.ThrowsAsync(Action); @@ -282,7 +288,7 @@ public async Task SetServiceProviderCompanyDetailsAsync_WithInvalidUrl_ThrowsExc var providerDetailData = new ProviderDetailData(url!, null); //Act - async Task Action() => await _sut.SetProviderCompanyDetailsAsync(providerDetailData, _identity.CompanyId).ConfigureAwait(false); + async Task Action() => await _sut.SetProviderCompanyDetailsAsync(providerDetailData).ConfigureAwait(false); //Assert var ex = await Assert.ThrowsAsync(Action); @@ -302,7 +308,7 @@ public async Task GetProviderCompanyDetailsAsync_WithValidUser_ReturnsDetails() SetupProviderCompanyDetails(); //Act - var result = await _sut.GetProviderCompanyDetailsAsync(_identity.CompanyId).ConfigureAwait(false); + var result = await _sut.GetProviderCompanyDetailsAsync().ConfigureAwait(false); //Assert result.Should().NotBeNull(); @@ -312,10 +318,11 @@ public async Task GetProviderCompanyDetailsAsync_WithValidUser_ReturnsDetails() public async Task GetProviderCompanyDetailsAsync_WithInvalidUser_ThrowsException() { //Arrange + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { CompanyId = Guid.NewGuid() }); SetupProviderCompanyDetails(); //Act - async Task Action() => await _sut.GetProviderCompanyDetailsAsync(Guid.NewGuid()).ConfigureAwait(false); + async Task Action() => await _sut.GetProviderCompanyDetailsAsync().ConfigureAwait(false); //Assert await Assert.ThrowsAsync(Action); @@ -330,7 +337,7 @@ public async Task GetProviderCompanyDetailsAsync_WithInvalidServiceProvider_Thro .ReturnsLazily(() => (new ProviderDetailReturnData(Guid.NewGuid(), Guid.NewGuid(), "https://new-test-service.de"), false)); //Act - async Task Action() => await _sut.GetProviderCompanyDetailsAsync(_identity.CompanyId).ConfigureAwait(false); + async Task Action() => await _sut.GetProviderCompanyDetailsAsync().ConfigureAwait(false); //Assert await Assert.ThrowsAsync(Action); diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/UserBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/UserBusinessLogicTests.cs index 41703ae599..31aba10d8f 100644 --- a/tests/administration/Administration.Service.Tests/BusinessLogic/UserBusinessLogicTests.cs +++ b/tests/administration/Administration.Service.Tests/BusinessLogic/UserBusinessLogicTests.cs @@ -73,6 +73,7 @@ public class UserBusinessLogicTests private readonly Func _companyUserSelectFunction; private readonly Exception _error; private readonly UserSettings _settings; + private readonly IIdentityService _identityService; public UserBusinessLogicTests() { @@ -113,6 +114,9 @@ public UserBusinessLogicTests() _processLine = A.Fake>(); _companyUserSelectFunction = A.Fake>(); + _identityService = A.Fake(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity); + _settings = new UserSettings { Portal = new UserSetting @@ -147,11 +151,12 @@ public async Task TestUserCreationAllSuccess() _userProvisioningService, null!, _portalRepositories, + _identityService, _mailingService, _logger, _options); - var result = await sut.CreateOwnCompanyUsersAsync(userList, (_identity.UserId, _identity.CompanyId)).ToListAsync().ConfigureAwait(false); + var result = await sut.CreateOwnCompanyUsersAsync(userList).ToListAsync().ConfigureAwait(false); A.CallTo(() => _mockLogger.Log(A.That.IsEqualTo(LogLevel.Error), A._, A._)).MustNotHaveHappened(); A.CallTo(() => _mailingService.SendMails(A._, A>._, A>._)).MustHaveHappenedANumberOfTimesMatching(times => times == userList.Count()); @@ -185,11 +190,12 @@ public async Task TestUserCreation_NoUserNameAndEmail_Throws() _userProvisioningService, null!, _portalRepositories, + _identityService, _mailingService, _logger, _options); - var Act = async () => await sut.CreateOwnCompanyUsersAsync(userList, (_identity.UserId, _identity.CompanyId)).ToListAsync().ConfigureAwait(false); + var Act = async () => await sut.CreateOwnCompanyUsersAsync(userList).ToListAsync().ConfigureAwait(false); var result = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -217,11 +223,12 @@ public async Task TestUserCreation_NoRoles_Throws() _userProvisioningService, null!, _portalRepositories, + _identityService, _mailingService, _logger, _options); - var Act = async () => await sut.CreateOwnCompanyUsersAsync(userList, (_identity.UserId, _identity.CompanyId)).ToListAsync().ConfigureAwait(false); + var Act = async () => await sut.CreateOwnCompanyUsersAsync(userList).ToListAsync().ConfigureAwait(false); var result = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -260,11 +267,12 @@ public async Task TestUserCreationCreationError() _userProvisioningService, null!, _portalRepositories, + _identityService, _mailingService, _logger, _options); - var result = await sut.CreateOwnCompanyUsersAsync(userList, (_identity.UserId, _identity.CompanyId)).ToListAsync().ConfigureAwait(false); + var result = await sut.CreateOwnCompanyUsersAsync(userList).ToListAsync().ConfigureAwait(false); A.CallTo(() => _processLine(A.That.Matches(u => u.FirstName == userCreationInfo.firstName && @@ -306,11 +314,12 @@ public async Task TestUserCreationCreationThrows() _userProvisioningService, null!, _portalRepositories, + _identityService, _mailingService, _logger, _options); - async Task Act() => await sut.CreateOwnCompanyUsersAsync(userList, (_identity.UserId, _identity.CompanyId)).ToListAsync().ConfigureAwait(false); + async Task Act() => await sut.CreateOwnCompanyUsersAsync(userList).ToListAsync().ConfigureAwait(false); var error = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -350,11 +359,12 @@ public async Task TestUserCreationSendMailError() _userProvisioningService, null!, _portalRepositories, + _identityService, _mailingService, _logger, _options); - var result = await sut.CreateOwnCompanyUsersAsync(userList, (_identity.UserId, _identity.CompanyId)).ToListAsync().ConfigureAwait(false); + var result = await sut.CreateOwnCompanyUsersAsync(userList).ToListAsync().ConfigureAwait(false); A.CallTo(() => _mockLogger.Log(A.That.IsEqualTo(LogLevel.Error), A._, A._)).MustHaveHappenedOnceExactly(); A.CallTo(() => _mailingService.SendMails(A._, A>._, A>._)).MustHaveHappenedANumberOfTimesMatching(times => times == 5); @@ -379,11 +389,12 @@ public async Task TestCreateOwnCompanyIdpUserAsyncSuccess() _userProvisioningService, null!, null!, + _identityService, _mailingService, _logger, _options); - var result = await sut.CreateOwnCompanyIdpUserAsync(_identityProviderId, userCreationInfoIdp, (_identity.UserId, _identity.CompanyId)).ConfigureAwait(false); + var result = await sut.CreateOwnCompanyIdpUserAsync(_identityProviderId, userCreationInfoIdp).ConfigureAwait(false); result.Should().NotBe(Guid.Empty); A.CallTo(() => _mailingService.SendMails(A.That.IsEqualTo(userCreationInfoIdp.Email), A>.That.Matches(x => x["companyName"] == _displayName), A>._)).MustHaveHappened(); A.CallTo(() => _mockLogger.Log(A.That.IsEqualTo(LogLevel.Error), A._, A._)).MustNotHaveHappened(); @@ -406,11 +417,12 @@ public async Task TestCreateOwnCompanyIdpUserNoRolesThrowsArgumentException() _userProvisioningService, null!, null!, + _identityService, _mailingService, _logger, _options); - Task Act() => sut.CreateOwnCompanyIdpUserAsync(_identityProviderId, userCreationInfoIdp, (_identity.UserId, _identity.CompanyId)); + Task Act() => sut.CreateOwnCompanyIdpUserAsync(_identityProviderId, userCreationInfoIdp); var error = await Assert.ThrowsAsync(Act).ConfigureAwait(false); error.Message.Should().Be("at least one role must be specified (Parameter 'Roles')"); @@ -435,11 +447,12 @@ public async Task TestCreateOwnCompanyIdpUserAsyncError() _userProvisioningService, null!, null!, + _identityService, _mailingService, _logger, _options); - Task Act() => sut.CreateOwnCompanyIdpUserAsync(_identityProviderId, userCreationInfoIdp, (_identity.UserId, _identity.CompanyId)); + Task Act() => sut.CreateOwnCompanyIdpUserAsync(_identityProviderId, userCreationInfoIdp); var error = await Assert.ThrowsAsync(Act).ConfigureAwait(false); error.Message.Should().Be(_error.Message); @@ -460,11 +473,12 @@ public async Task TestCreateOwnCompanyIdpUserAsyncThrows() _userProvisioningService, null!, null!, + _identityService, _mailingService, _logger, _options); - Task Act() => sut.CreateOwnCompanyIdpUserAsync(_identityProviderId, userCreationInfoIdp, (_identity.UserId, _identity.CompanyId)); + Task Act() => sut.CreateOwnCompanyIdpUserAsync(_identityProviderId, userCreationInfoIdp); var error = await Assert.ThrowsAsync(Act).ConfigureAwait(false); error.Message.Should().Be(_error.Message); @@ -485,11 +499,12 @@ public async Task TestCreateOwnCompanyIdpUserAsyncMailingErrorLogs() _userProvisioningService, null!, null!, + _identityService, _mailingService, _logger, _options); - var result = await sut.CreateOwnCompanyIdpUserAsync(_identityProviderId, userCreationInfoIdp, (_identity.UserId, _identity.CompanyId)).ConfigureAwait(false); + var result = await sut.CreateOwnCompanyIdpUserAsync(_identityProviderId, userCreationInfoIdp).ConfigureAwait(false); result.Should().NotBe(Guid.Empty); A.CallTo(() => _mailingService.SendMails(A._, A>._, A>._)).MustHaveHappened(); A.CallTo(() => _mockLogger.Log(A.That.IsEqualTo(LogLevel.Error), A._, A._)).MustHaveHappened(); @@ -509,6 +524,7 @@ public async Task TestDeleteOwnUserSuccess() null!, null!, _portalRepositories, + _identityService, null!, _logger, _options @@ -528,7 +544,7 @@ public async Task TestDeleteOwnUserSuccess() modify.Invoke(_companyUser); }); - await sut.DeleteOwnUserAsync(_companyUserId, _identity.UserId).ConfigureAwait(false); + await sut.DeleteOwnUserAsync(_companyUserId).ConfigureAwait(false); A.CallTo(() => _provisioningManager.GetProviderUserIdForCentralUserIdAsync(A._, A._)).MustHaveHappened(); A.CallTo(() => _provisioningManager.DeleteSharedRealmUserAsync(A._, A._)).MustHaveHappened(); @@ -548,6 +564,7 @@ public async Task TestDeleteOwnUserInvalidUserThrows() SetupFakesForUserDeletion(); var identity = _fixture.Create(); + A.CallTo(() => _identityService.IdentityData).Returns(identity); A.CallTo(() => _userRepository.GetSharedIdentityProviderUserAccountDataUntrackedAsync(identity.UserId)) .Returns(((string?, CompanyUserAccountData))default!); @@ -557,12 +574,13 @@ public async Task TestDeleteOwnUserInvalidUserThrows() null!, null!, _portalRepositories, + _identityService, null!, _logger, _options ); - Task Act() => sut.DeleteOwnUserAsync(identity.UserId, identity.UserId); + Task Act() => sut.DeleteOwnUserAsync(identity.UserId); var error = await Assert.ThrowsAsync(Act).ConfigureAwait(false); error.Message.Should().Be($"user {identity.UserId} does not exist"); @@ -579,18 +597,20 @@ public async Task TestDeleteOwnUserInvalidCompanyUserThrows() SetupFakesForUserDeletion(); var identity = _fixture.Create(); + A.CallTo(() => _identityService.IdentityData).Returns(identity); var sut = new UserBusinessLogic( _provisioningManager, null!, null!, _portalRepositories, + _identityService, null!, _logger, _options ); - Task Act() => sut.DeleteOwnUserAsync(_companyUserId, identity.UserId); + Task Act() => sut.DeleteOwnUserAsync(_companyUserId); var error = await Assert.ThrowsAsync(Act).ConfigureAwait(false); error.Message.Should().Be($"companyUser {_companyUserId} is not the id of user {identity.UserId}"); @@ -609,11 +629,13 @@ public async Task TestDeleteOwnUserInvalidCompanyUserThrows() public async Task ModifyUserRoleAsync_WithTwoNewRoles_AddsTwoRolesToTheDatabase() { // Arrange + A.CallTo(() => _identityService.IdentityData).Returns(_createdCentralIdentity); SetupFakesForUserRoleModification(); var sut = new UserRolesBusinessLogic( _portalRepositories, _provisioningManager, + _identityService, Options.Create(_settings) ); @@ -625,7 +647,7 @@ public async Task ModifyUserRoleAsync_WithTwoNewRoles_AddsTwoRolesToTheDatabase( "Buyer", "Supplier" }); - await sut.ModifyUserRoleAsync(_validOfferId, userRoleInfo, _createdCentralIdentity.CompanyId).ConfigureAwait(false); + await sut.ModifyUserRoleAsync(_validOfferId, userRoleInfo).ConfigureAwait(false); // Assert _companyUserAssignedRole.Should().HaveCount(2); @@ -635,11 +657,13 @@ public async Task ModifyUserRoleAsync_WithTwoNewRoles_AddsTwoRolesToTheDatabase( public async Task ModifyUserRoleAsync_WithOneRoleToDelete_DeletesTheRole() { // Arrange + A.CallTo(() => _identityService.IdentityData).Returns(_adminIdentity); SetupFakesForUserRoleModification(); var sut = new UserRolesBusinessLogic( _portalRepositories, _provisioningManager, + _identityService, Options.Create(_settings) ); @@ -648,7 +672,7 @@ public async Task ModifyUserRoleAsync_WithOneRoleToDelete_DeletesTheRole() { "Company Admin" }); - await sut.ModifyUserRoleAsync(_validOfferId, userRoleInfo, _adminIdentity.CompanyId).ConfigureAwait(false); + await sut.ModifyUserRoleAsync(_validOfferId, userRoleInfo).ConfigureAwait(false); // Assert A.CallTo(() => _portalRepositories.RemoveRange(A>.That.Matches(x => x.Count() == 1))).MustHaveHappenedOnceExactly(); @@ -658,11 +682,13 @@ public async Task ModifyUserRoleAsync_WithOneRoleToDelete_DeletesTheRole() public async Task ModifyUserRoleAsync_WithNotExistingRole_ThrowsException() { // Arrange + A.CallTo(() => _identityService.IdentityData).Returns(_adminIdentity); SetupFakesForUserRoleModification(); var sut = new UserRolesBusinessLogic( _portalRepositories, _provisioningManager, + _identityService, Options.Create(_settings) ); @@ -672,7 +698,7 @@ public async Task ModifyUserRoleAsync_WithNotExistingRole_ThrowsException() "NotExisting", "Buyer" }); - async Task Action() => await sut.ModifyUserRoleAsync(_validOfferId, userRoleInfo, _adminIdentity.CompanyId).ConfigureAwait(false); + async Task Action() => await sut.ModifyUserRoleAsync(_validOfferId, userRoleInfo).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Action); @@ -683,11 +709,13 @@ public async Task ModifyUserRoleAsync_WithNotExistingRole_ThrowsException() public async Task ModifyUserRoleAsync_WithNotFoundCompanyUser_ThrowsException() { // Arrange + A.CallTo(() => _identityService.IdentityData).Returns(_adminIdentity); SetupFakesForUserRoleModification(); var sut = new UserRolesBusinessLogic( _portalRepositories, _provisioningManager, + _identityService, Options.Create(_settings) ); @@ -698,7 +726,7 @@ public async Task ModifyUserRoleAsync_WithNotFoundCompanyUser_ThrowsException() "Buyer", "Supplier" }); - async Task Action() => await sut.ModifyUserRoleAsync(_validOfferId, userRoleInfo, _adminIdentity.CompanyId).ConfigureAwait(false); + async Task Action() => await sut.ModifyUserRoleAsync(_validOfferId, userRoleInfo).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Action); @@ -709,11 +737,13 @@ public async Task ModifyUserRoleAsync_WithNotFoundCompanyUser_ThrowsException() public async Task ModifyUserRoleAsync_WithInvalidOfferId_ThrowsException() { // Arrange + A.CallTo(() => _identityService.IdentityData).Returns(_adminIdentity); SetupFakesForUserRoleModification(); var sut = new UserRolesBusinessLogic( _portalRepositories, _provisioningManager, + _identityService, Options.Create(_settings) ); var invalidAppId = Guid.NewGuid(); @@ -725,7 +755,7 @@ public async Task ModifyUserRoleAsync_WithInvalidOfferId_ThrowsException() "Buyer", "Supplier" }); - async Task Action() => await sut.ModifyUserRoleAsync(invalidAppId, userRoleInfo, _adminIdentity.CompanyId).ConfigureAwait(false); + async Task Action() => await sut.ModifyUserRoleAsync(invalidAppId, userRoleInfo).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Action); @@ -741,11 +771,13 @@ public async Task ModifyCoreOfferUserRolesAsync_WithTwoNewRoles_AddsTwoRolesToTh { // Arrange var notifications = new List(); + A.CallTo(() => _identityService.IdentityData).Returns(_createdCentralIdentity); SetupFakesForUserRoleModification(notifications); var sut = new UserRolesBusinessLogic( _portalRepositories, _provisioningManager, + _identityService, Options.Create(_settings) ); @@ -757,7 +789,7 @@ public async Task ModifyCoreOfferUserRolesAsync_WithTwoNewRoles_AddsTwoRolesToTh "Buyer", "Supplier" }; - await sut.ModifyCoreOfferUserRolesAsync(_validOfferId, _companyUserId, userRoles, _createdCentralIdentity.CompanyId).ConfigureAwait(false); + await sut.ModifyCoreOfferUserRolesAsync(_validOfferId, _companyUserId, userRoles).ConfigureAwait(false); // Assert _companyUserAssignedRole.Should().HaveCount(2); @@ -775,11 +807,13 @@ public async Task ModifyAppUserRolesAsync_WithTwoNewRoles_AddsTwoRolesToTheDatab { // Arrange var notifications = new List(); + A.CallTo(() => _identityService.IdentityData).Returns(_createdCentralIdentity); SetupFakesForUserRoleModification(notifications); var sut = new UserRolesBusinessLogic( _portalRepositories, _provisioningManager, + _identityService, Options.Create(_settings) ); @@ -791,7 +825,7 @@ public async Task ModifyAppUserRolesAsync_WithTwoNewRoles_AddsTwoRolesToTheDatab "Buyer", "Supplier" }; - await sut.ModifyAppUserRolesAsync(_validOfferId, _companyUserId, userRoles, _createdCentralIdentity.CompanyId).ConfigureAwait(false); + await sut.ModifyAppUserRolesAsync(_validOfferId, _companyUserId, userRoles).ConfigureAwait(false); // Assert _companyUserAssignedRole.Should().HaveCount(2); @@ -804,12 +838,14 @@ public async Task ModifyAppUserRolesAsync_WithTwoNewRoles_AddsTwoRolesToTheDatab public async Task ModifyAppUserRolesAsync_WithOneRoleToDelete_DeletesTheRole() { // Arrange + A.CallTo(() => _identityService.IdentityData).Returns(_adminIdentity); var notifications = new List(); SetupFakesForUserRoleModification(notifications); var sut = new UserRolesBusinessLogic( _portalRepositories, _provisioningManager, + _identityService, Options.Create(_settings) ); @@ -818,7 +854,7 @@ public async Task ModifyAppUserRolesAsync_WithOneRoleToDelete_DeletesTheRole() { "Company Admin" }; - await sut.ModifyAppUserRolesAsync(_validOfferId, _companyUserId, userRoles, _adminIdentity.CompanyId).ConfigureAwait(false); + await sut.ModifyAppUserRolesAsync(_validOfferId, _companyUserId, userRoles).ConfigureAwait(false); // Assert A.CallTo(() => _portalRepositories.RemoveRange(A>.That.Matches(x => x.Count() == 1))).MustHaveHappenedOnceExactly(); @@ -831,11 +867,13 @@ public async Task ModifyAppUserRolesAsync_WithOneRoleToDelete_DeletesTheRole() public async Task ModifyAppUserRolesAsync_WithNotExistingRole_ThrowsException() { // Arrange + A.CallTo(() => _identityService.IdentityData).Returns(_adminIdentity); SetupFakesForUserRoleModification(); var sut = new UserRolesBusinessLogic( _portalRepositories, _provisioningManager, + _identityService, Options.Create(_settings) ); @@ -845,7 +883,7 @@ public async Task ModifyAppUserRolesAsync_WithNotExistingRole_ThrowsException() "NotExisting", "Buyer" }; - async Task Action() => await sut.ModifyAppUserRolesAsync(_validOfferId, _companyUserId, userRoles, _adminIdentity.CompanyId).ConfigureAwait(false); + async Task Action() => await sut.ModifyAppUserRolesAsync(_validOfferId, _companyUserId, userRoles).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Action); @@ -858,11 +896,13 @@ public async Task ModifyAppUserRolesAsync_WithNotExistingRole_ThrowsException() public async Task ModifyAppUserRolesAsync_WithNotFoundCompanyUser_ThrowsException() { // Arrange + A.CallTo(() => _identityService.IdentityData).Returns(_adminIdentity); SetupFakesForUserRoleModification(); var sut = new UserRolesBusinessLogic( _portalRepositories, _provisioningManager, + _identityService, Options.Create(_settings) ); @@ -874,7 +914,7 @@ public async Task ModifyAppUserRolesAsync_WithNotFoundCompanyUser_ThrowsExceptio "Buyer", "Supplier" }; - async Task Action() => await sut.ModifyAppUserRolesAsync(_validOfferId, companyUserId, userRoles, _adminIdentity.CompanyId).ConfigureAwait(false); + async Task Action() => await sut.ModifyAppUserRolesAsync(_validOfferId, companyUserId, userRoles).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Action); @@ -887,11 +927,13 @@ public async Task ModifyAppUserRolesAsync_WithNotFoundCompanyUser_ThrowsExceptio public async Task ModifyAppUserRolesAsync_WithInvalidOfferId_ThrowsException() { // Arrange + A.CallTo(() => _identityService.IdentityData).Returns(_adminIdentity); SetupFakesForUserRoleModification(); var sut = new UserRolesBusinessLogic( _portalRepositories, _provisioningManager, + _identityService, Options.Create(_settings) ); var invalidAppId = Guid.NewGuid(); @@ -903,7 +945,7 @@ public async Task ModifyAppUserRolesAsync_WithInvalidOfferId_ThrowsException() "Buyer", "Supplier" }; - async Task Action() => await sut.ModifyAppUserRolesAsync(invalidAppId, _companyUserId, userRoles, _adminIdentity.CompanyId).ConfigureAwait(false); + async Task Action() => await sut.ModifyAppUserRolesAsync(invalidAppId, _companyUserId, userRoles).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Action); @@ -916,11 +958,13 @@ public async Task ModifyAppUserRolesAsync_WithInvalidOfferId_ThrowsException() public async Task ModifyAppUserRolesAsync_WithoutOfferName_ThrowsException() { // Arrange + A.CallTo(() => _identityService.IdentityData).Returns(_adminIdentity); SetupFakesForUserRoleModification(); var sut = new UserRolesBusinessLogic( _portalRepositories, _provisioningManager, + _identityService, Options.Create(_settings) ); @@ -931,7 +975,7 @@ public async Task ModifyAppUserRolesAsync_WithoutOfferName_ThrowsException() "Buyer", "Supplier" }; - async Task Action() => await sut.ModifyAppUserRolesAsync(_offerWithoutNameId, _companyUserId, userRoles, _adminIdentity.CompanyId).ConfigureAwait(false); + async Task Action() => await sut.ModifyAppUserRolesAsync(_offerWithoutNameId, _companyUserId, userRoles).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Action); @@ -956,12 +1000,13 @@ public async Task TestDeleteOwnCompanyUsersAsyncSuccess() null!, null!, _portalRepositories, + _identityService, null!, _logger, _options ); - var result = await sut.DeleteOwnCompanyUsersAsync(companyUserIds, _identity.CompanyId).ToListAsync().ConfigureAwait(false); + var result = await sut.DeleteOwnCompanyUsersAsync(companyUserIds).ToListAsync().ConfigureAwait(false); var expectedCount = companyUserIds.Count(); result.Should().HaveCount(expectedCount); @@ -988,12 +1033,13 @@ public async Task TestDeleteOwnCompanyUsersAsyncNoSharedIdpSuccess() null!, null!, _portalRepositories, + _identityService, null!, _logger, _options ); - var result = await sut.DeleteOwnCompanyUsersAsync(companyUserIds, _identity.CompanyId).ToListAsync().ConfigureAwait(false); + var result = await sut.DeleteOwnCompanyUsersAsync(companyUserIds).ToListAsync().ConfigureAwait(false); var expectedCount = companyUserIds.Count(); result.Should().HaveCount(expectedCount); @@ -1046,12 +1092,13 @@ public async Task TestDeleteOwnCompanyUsersAsyncError() null!, null!, _portalRepositories, + _identityService, null!, _logger, _options ); - var result = await sut.DeleteOwnCompanyUsersAsync(companyUserIds, _identity.CompanyId).ToListAsync().ConfigureAwait(false); + var result = await sut.DeleteOwnCompanyUsersAsync(companyUserIds).ToListAsync().ConfigureAwait(false); result.Should().HaveCount(companyUserIds.Length - 1); result.Should().Match(r => Enumerable.SequenceEqual(r, companyUserIds.Take(2).Concat(companyUserIds.Skip(3)))); @@ -1100,12 +1147,13 @@ public async Task TestDeleteOwnCompanyUsersAsyncNoSharedIdpError() null!, null!, _portalRepositories, + _identityService, null!, _logger, _options ); - var result = await sut.DeleteOwnCompanyUsersAsync(companyUserIds, _identity.CompanyId).ToListAsync().ConfigureAwait(false); + var result = await sut.DeleteOwnCompanyUsersAsync(companyUserIds).ToListAsync().ConfigureAwait(false); result.Should().HaveCount(companyUserIds.Length - 1); result.Should().Match(r => Enumerable.SequenceEqual(r, companyUserIds.Take(2).Concat(companyUserIds.Skip(3)))); @@ -1131,16 +1179,16 @@ public async Task GetOwnCompanyAppUsersAsync_ReturnsExpectedResult() var appId = _fixture.Create(); var userId = Guid.NewGuid(); var companyUsers = _fixture.CreateMany(5); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { UserId = userId }); A.CallTo(() => _userRepository.GetOwnCompanyAppUsersPaginationSourceAsync(A._, A._, A>._, A>._, A._)) .Returns((int skip, int take) => Task.FromResult((Pagination.Source?)new Pagination.Source(companyUsers.Count(), companyUsers.Skip(skip).Take(take)))); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_userRepository); - var sut = new UserBusinessLogic(null!, null!, null!, _portalRepositories, null!, null!, A.Fake>()); + var sut = new UserBusinessLogic(null!, null!, null!, _portalRepositories, _identityService, null!, null!, A.Fake>()); // Act var results = await sut.GetOwnCompanyAppUsersAsync( appId, - userId, 0, 10, new CompanyUserFilter(null, null, null, null, null)).ConfigureAwait(false); @@ -1157,16 +1205,16 @@ public async Task GetOwnCompanyAppUsersAsync_SecondPage_ReturnsExpectedResult() var appId = _fixture.Create(); var userId = Guid.NewGuid(); var companyUsers = _fixture.CreateMany(5); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { UserId = userId }); A.CallTo(() => _userRepository.GetOwnCompanyAppUsersPaginationSourceAsync(A._, A._, A>._, A>._, A._)) .Returns((int skip, int take) => Task.FromResult((Pagination.Source?)new Pagination.Source(companyUsers.Count(), companyUsers.Skip(skip).Take(take)))); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_userRepository); - var sut = new UserBusinessLogic(null!, null!, null!, _portalRepositories, null!, null!, A.Fake>()); + var sut = new UserBusinessLogic(null!, null!, null!, _portalRepositories, _identityService, null!, null!, A.Fake>()); // Act var results = await sut.GetOwnCompanyAppUsersAsync( appId, - userId, 1, 3, new CompanyUserFilter(null, null, null, null, null)).ConfigureAwait(false); @@ -1186,14 +1234,14 @@ public async Task GetOwnCompanyAppUsersAsync_WithNonExistingCompanyUser_ThrowsNo // Arrange var companyUserId = _fixture.Create(); var businessPartnerNumber = _fixture.Create(); - var adminUserId = _fixture.Create(); + A.CallTo(() => _identityService.IdentityData).Returns(_adminIdentity); A.CallTo(() => _userBusinessPartnerRepository.GetOwnCompanyUserWithAssignedBusinessPartnerNumbersAsync(companyUserId, _adminIdentity.CompanyId, businessPartnerNumber)) .Returns(((string?, bool, bool))default); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_userBusinessPartnerRepository); - var sut = new UserBusinessLogic(null!, null!, null!, _portalRepositories, null!, null!, A.Fake>()); + var sut = new UserBusinessLogic(null!, null!, null!, _portalRepositories, _identityService, null!, null!, A.Fake>()); // Act - async Task Act() => await sut.DeleteOwnUserBusinessPartnerNumbersAsync(companyUserId, businessPartnerNumber, (_adminIdentity.UserId, _adminIdentity.CompanyId)).ConfigureAwait(false); + async Task Act() => await sut.DeleteOwnUserBusinessPartnerNumbersAsync(companyUserId, businessPartnerNumber).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -1206,14 +1254,14 @@ public async Task GetOwnCompanyAppUsersAsync_WithUnassignedBusinessPartner_Throw // Arrange var companyUserId = _fixture.Create(); var businessPartnerNumber = _fixture.Create(); - var adminUserId = _fixture.Create(); + A.CallTo(() => _identityService.IdentityData).Returns(_adminIdentity); A.CallTo(() => _userBusinessPartnerRepository.GetOwnCompanyUserWithAssignedBusinessPartnerNumbersAsync(companyUserId, _adminIdentity.CompanyId, businessPartnerNumber)) .Returns((string.Empty, false, false)); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_userBusinessPartnerRepository); - var sut = new UserBusinessLogic(null!, null!, null!, _portalRepositories, null!, null!, A.Fake>()); + var sut = new UserBusinessLogic(null!, null!, null!, _portalRepositories, _identityService, null!, null!, A.Fake>()); // Act - async Task Act() => await sut.DeleteOwnUserBusinessPartnerNumbersAsync(companyUserId, businessPartnerNumber, (_adminIdentity.UserId, _adminIdentity.CompanyId)).ConfigureAwait(false); + async Task Act() => await sut.DeleteOwnUserBusinessPartnerNumbersAsync(companyUserId, businessPartnerNumber).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -1226,14 +1274,14 @@ public async Task GetOwnCompanyAppUsersAsync_WithoutUserForBpn_ThrowsArgumentExc // Arrange var companyUserId = _fixture.Create(); var businessPartnerNumber = _fixture.Create(); - var adminUserId = _fixture.Create(); + A.CallTo(() => _identityService.IdentityData).Returns(_adminIdentity); A.CallTo(() => _userBusinessPartnerRepository.GetOwnCompanyUserWithAssignedBusinessPartnerNumbersAsync(companyUserId, _adminIdentity.CompanyId, businessPartnerNumber)) .Returns(((string?)null, true, false)); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_userBusinessPartnerRepository); - var sut = new UserBusinessLogic(null!, null!, null!, _portalRepositories, null!, null!, A.Fake>()); + var sut = new UserBusinessLogic(null!, null!, null!, _portalRepositories, _identityService, null!, null!, A.Fake>()); // Act - async Task Act() => await sut.DeleteOwnUserBusinessPartnerNumbersAsync(companyUserId, businessPartnerNumber, (_adminIdentity.UserId, _adminIdentity.CompanyId)).ConfigureAwait(false); + async Task Act() => await sut.DeleteOwnUserBusinessPartnerNumbersAsync(companyUserId, businessPartnerNumber).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -1246,14 +1294,14 @@ public async Task GetOwnCompanyAppUsersAsync_WithInvalidUser_ThrowsForbiddenExce // Arrange var companyUserId = _fixture.Create(); var businessPartnerNumber = _fixture.Create(); - var adminUserId = _fixture.Create(); + A.CallTo(() => _identityService.IdentityData).Returns(_adminIdentity); A.CallTo(() => _userBusinessPartnerRepository.GetOwnCompanyUserWithAssignedBusinessPartnerNumbersAsync(companyUserId, _adminIdentity.CompanyId, businessPartnerNumber)) .Returns((Guid.NewGuid().ToString(), true, false)); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_userBusinessPartnerRepository); - var sut = new UserBusinessLogic(null!, null!, null!, _portalRepositories, null!, null!, A.Fake>()); + var sut = new UserBusinessLogic(null!, null!, null!, _portalRepositories, _identityService, null!, null!, A.Fake>()); // Act - async Task Act() => await sut.DeleteOwnUserBusinessPartnerNumbersAsync(companyUserId, businessPartnerNumber, (_adminIdentity.UserId, _adminIdentity.CompanyId)).ConfigureAwait(false); + async Task Act() => await sut.DeleteOwnUserBusinessPartnerNumbersAsync(companyUserId, businessPartnerNumber).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -1266,14 +1314,14 @@ public async Task GetOwnCompanyAppUsersAsync_WithValidData_ThrowsForbiddenExcept // Arrange var companyUserId = _fixture.Create(); var businessPartnerNumber = _fixture.Create(); - var adminUserId = _fixture.Create(); + A.CallTo(() => _identityService.IdentityData).Returns(_adminIdentity); A.CallTo(() => _userBusinessPartnerRepository.GetOwnCompanyUserWithAssignedBusinessPartnerNumbersAsync(companyUserId, _adminIdentity.CompanyId, businessPartnerNumber)) .Returns((Guid.NewGuid().ToString(), true, true)); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_userBusinessPartnerRepository); - var sut = new UserBusinessLogic(_provisioningManager, null!, null!, _portalRepositories, null!, null!, A.Fake>()); + var sut = new UserBusinessLogic(_provisioningManager, null!, null!, _portalRepositories, _identityService, null!, null!, A.Fake>()); // Act - await sut.DeleteOwnUserBusinessPartnerNumbersAsync(companyUserId, businessPartnerNumber, (_adminIdentity.UserId, _adminIdentity.CompanyId)).ConfigureAwait(false); + await sut.DeleteOwnUserBusinessPartnerNumbersAsync(companyUserId, businessPartnerNumber).ConfigureAwait(false); // Assert A.CallTo(() => _provisioningManager.DeleteCentralUserBusinessPartnerNumberAsync(A._, A._)).MustHaveHappenedOnceExactly(); @@ -1291,15 +1339,16 @@ public async Task GetOwnUserDetails_ReturnsExpected() var companyOwnUserDetails = _fixture.Create(); var identity = _fixture.Create(); var userRoleIds = new[] { _fixture.Create(), _fixture.Create() }; + A.CallTo(() => _identityService.IdentityData).Returns(identity); A.CallTo(() => _userRolesRepository.GetUserRoleIdsUntrackedAsync(A>._)) .Returns(userRoleIds.ToAsyncEnumerable()); A.CallTo(() => _userRepository.GetUserDetailsUntrackedAsync(A._, A>._)) .Returns(companyOwnUserDetails); - var sut = new UserBusinessLogic(_provisioningManager, null!, null!, _portalRepositories, null!, _logger, _options); + var sut = new UserBusinessLogic(_provisioningManager, null!, null!, _portalRepositories, _identityService, null!, _logger, _options); // Act - var result = await sut.GetOwnUserDetails(identity.UserId).ConfigureAwait(false); + var result = await sut.GetOwnUserDetails().ConfigureAwait(false); // Assert A.CallTo(() => _userRolesRepository.GetUserRoleIdsUntrackedAsync(A> @@ -1313,13 +1362,13 @@ public async Task GetOwnUserDetails_ThrowsNotFoundException() { // Arrange var identity = _fixture.Create(); - + A.CallTo(() => _identityService.IdentityData).Returns(identity); A.CallTo(() => _userRepository.GetUserDetailsUntrackedAsync(identity.UserId, A>._)) .Returns((CompanyOwnUserDetails)default!); - var sut = new UserBusinessLogic(_provisioningManager, null!, null!, _portalRepositories, null!, _logger, _options); + var sut = new UserBusinessLogic(_provisioningManager, null!, null!, _portalRepositories, _identityService, null!, _logger, _options); // Act - async Task Act() => await sut.GetOwnUserDetails(identity.UserId).ConfigureAwait(false); + async Task Act() => await sut.GetOwnUserDetails().ConfigureAwait(false); // Assert var error = await Assert.ThrowsAsync(Act).ConfigureAwait(false); diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/UserUploadBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/UserUploadBusinessLogicTests.cs index 468e09b539..394d62d3df 100644 --- a/tests/administration/Administration.Service.Tests/BusinessLogic/UserUploadBusinessLogicTests.cs +++ b/tests/administration/Administration.Service.Tests/BusinessLogic/UserUploadBusinessLogicTests.cs @@ -39,8 +39,6 @@ public class UserUploadBusinessLogicTests private readonly IOptions _options; private readonly IFormFile _document; private readonly Guid _identityProviderId; - private readonly string _iamUserId; - private readonly string _clientId; private readonly IdentityData _identity; private readonly IMailingService _mailingService; private readonly UserSettings _settings; @@ -48,6 +46,7 @@ public class UserUploadBusinessLogicTests private readonly Func _processLine; private readonly Exception _error; private readonly Random _random; + private readonly IIdentityService _identityService; public UserUploadBusinessLogicTests() { @@ -64,11 +63,13 @@ public UserUploadBusinessLogicTests() _document = A.Fake(); _identityProviderId = _fixture.Create(); - _iamUserId = _fixture.Create(); - _clientId = _fixture.Create(); - _settings = _fixture.Build().With(x => x.Portal, _fixture.Build().With(x => x.KeycloakClientID, _clientId).Create()).Create(); + var clientId = _fixture.Create(); + _settings = _fixture.Build().With(x => x.Portal, _fixture.Build().With(x => x.KeycloakClientID, clientId).Create()).Create(); _encoding = _fixture.Create(); - _identity = new(_iamUserId, Guid.NewGuid(), IdentityTypeId.COMPANY_USER, Guid.NewGuid()); + _identity = new(Guid.NewGuid().ToString(), Guid.NewGuid(), IdentityTypeId.COMPANY_USER, Guid.NewGuid()); + + _identityService = A.Fake(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity); _processLine = A.Fake>(); @@ -81,9 +82,9 @@ public async Task TestSetup() { SetupFakes(new[] { HeaderLine() }); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _identityService, _options); - var result = await sut.UploadOwnCompanyIdpUsersAsync(_identityProviderId, _document, (_identity.UserId, _identity.CompanyId), CancellationToken.None).ConfigureAwait(false); + var result = await sut.UploadOwnCompanyIdpUsersAsync(_identityProviderId, _document, CancellationToken.None).ConfigureAwait(false); A.CallTo(() => _userProvisioningService.GetCompanyNameIdpAliasData(A.That.IsEqualTo(_identityProviderId), _identity.UserId)).MustHaveHappened(); result.Should().NotBeNull(); @@ -106,9 +107,9 @@ public async Task TestUserCreationAllSuccess() NextLine() }); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _identityService, _options); - var result = await sut.UploadOwnCompanyIdpUsersAsync(_identityProviderId, _document, (_identity.UserId, _identity.CompanyId), CancellationToken.None).ConfigureAwait(false); + var result = await sut.UploadOwnCompanyIdpUsersAsync(_identityProviderId, _document, CancellationToken.None).ConfigureAwait(false); result.Should().NotBeNull(); result.Created.Should().Be(5); @@ -132,9 +133,9 @@ public async Task TestUserCreationHeaderParsingThrows() NextLine() }); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _identityService, _options); - async Task Act() => await sut.UploadOwnCompanyIdpUsersAsync(_identityProviderId, _document, (_identity.UserId, _identity.CompanyId), CancellationToken.None).ConfigureAwait(false); + async Task Act() => await sut.UploadOwnCompanyIdpUsersAsync(_identityProviderId, _document, CancellationToken.None).ConfigureAwait(false); var error = await Assert.ThrowsAsync(Act).ConfigureAwait(false); error.Message.Should().Be($"invalid format: expected 'FirstName', got '{invalidHeader}' (Parameter 'document')"); @@ -162,9 +163,9 @@ public async Task TestUserCreationCreationError() .With(x => x.Error, _error) .Create()); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _identityService, _options); - var result = await sut.UploadOwnCompanyIdpUsersAsync(_identityProviderId, _document, (_identity.UserId, _identity.CompanyId), CancellationToken.None).ConfigureAwait(false); + var result = await sut.UploadOwnCompanyIdpUsersAsync(_identityProviderId, _document, CancellationToken.None).ConfigureAwait(false); A.CallTo(() => _processLine(A.That.Matches(info => CreationInfoMatches(info, creationInfo)))).MustHaveHappened(); @@ -193,9 +194,9 @@ public async Task TestUserCreationCreationNoRolesError() NextLine() }); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _identityService, _options); - var result = await sut.UploadOwnCompanyIdpUsersAsync(_identityProviderId, _document, (_identity.UserId, _identity.CompanyId), CancellationToken.None).ConfigureAwait(false); + var result = await sut.UploadOwnCompanyIdpUsersAsync(_identityProviderId, _document, CancellationToken.None).ConfigureAwait(false); A.CallTo(() => _processLine(A.That.Matches(info => CreationInfoMatches(info, creationInfo)))).MustNotHaveHappened(); A.CallTo(() => _processLine(A.That.Not.Matches(info => CreationInfoMatches(info, creationInfo)))).MustHaveHappened(4, Times.Exactly); @@ -226,9 +227,9 @@ public async Task TestUserCreationMailError() A.CallTo(() => _mailingService.SendMails(creationInfo.Email, A>._, A>._)) .ThrowsAsync(_error); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _identityService, _options); - var result = await sut.UploadOwnCompanyIdpUsersAsync(_identityProviderId, _document, (_identity.UserId, _identity.CompanyId), CancellationToken.None).ConfigureAwait(false); + var result = await sut.UploadOwnCompanyIdpUsersAsync(_identityProviderId, _document, CancellationToken.None).ConfigureAwait(false); A.CallTo(() => _processLine(A.That.Matches(info => CreationInfoMatches(info, creationInfo)))).MustHaveHappened(); @@ -253,9 +254,9 @@ public async Task TestUserCreationParsingError() NextLine() }); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _identityService, _options); - var result = await sut.UploadOwnCompanyIdpUsersAsync(_identityProviderId, _document, (_identity.UserId, _identity.CompanyId), CancellationToken.None).ConfigureAwait(false); + var result = await sut.UploadOwnCompanyIdpUsersAsync(_identityProviderId, _document, CancellationToken.None).ConfigureAwait(false); result.Should().NotBeNull(); result.Created.Should().Be(4); @@ -283,9 +284,9 @@ public async Task TestUserCreationCreationThrows() A.CallTo(() => _processLine(A.That.Matches(info => CreationInfoMatches(info, creationInfo)))) .Throws(_error); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _identityService, _options); - var result = await sut.UploadOwnCompanyIdpUsersAsync(_identityProviderId, _document, (_identity.UserId, _identity.CompanyId), CancellationToken.None).ConfigureAwait(false); + var result = await sut.UploadOwnCompanyIdpUsersAsync(_identityProviderId, _document, CancellationToken.None).ConfigureAwait(false); A.CallTo(() => _processLine(A.That.Matches(info => CreationInfoMatches(info, creationInfo)))).MustHaveHappened(); @@ -307,9 +308,9 @@ public async Task TestSetupSharedIdp() { SetupFakes(new[] { HeaderLineSharedIdp() }); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _identityService, _options); - var result = await sut.UploadOwnCompanySharedIdpUsersAsync(_document, (_identity.UserId, _identity.CompanyId), CancellationToken.None).ConfigureAwait(false); + var result = await sut.UploadOwnCompanySharedIdpUsersAsync(_document, CancellationToken.None).ConfigureAwait(false); A.CallTo(() => _userProvisioningService.GetCompanyNameSharedIdpAliasData(_identity.UserId, A._)).MustHaveHappened(); result.Should().NotBeNull(); @@ -331,9 +332,9 @@ public async Task TestUserCreationSharedIdpAllSuccess() NextLineSharedIdp() }); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _identityService, _options); - var result = await sut.UploadOwnCompanySharedIdpUsersAsync(_document, (_identity.UserId, _identity.CompanyId), CancellationToken.None).ConfigureAwait(false); + var result = await sut.UploadOwnCompanySharedIdpUsersAsync(_document, CancellationToken.None).ConfigureAwait(false); result.Should().NotBeNull(); result.Created.Should().Be(5); @@ -357,9 +358,9 @@ public async Task TestUserCreationSharedIdpHeaderParsingThrows() NextLineSharedIdp() }); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _identityService, _options); - async Task Act() => await sut.UploadOwnCompanySharedIdpUsersAsync(_document, (_identity.UserId, _identity.CompanyId), CancellationToken.None).ConfigureAwait(false); + async Task Act() => await sut.UploadOwnCompanySharedIdpUsersAsync(_document, CancellationToken.None).ConfigureAwait(false); var error = await Assert.ThrowsAsync(Act).ConfigureAwait(false); error.Message.Should().Be($"invalid format: expected 'FirstName', got '{invalidHeader}' (Parameter 'document')"); @@ -381,9 +382,9 @@ public async Task TestUserCreationSharedIdpNoRolesError() NextLineSharedIdp(), }); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _identityService, _options); - var result = await sut.UploadOwnCompanySharedIdpUsersAsync(_document, (_identity.UserId, _identity.CompanyId), CancellationToken.None).ConfigureAwait(false); + var result = await sut.UploadOwnCompanySharedIdpUsersAsync(_document, CancellationToken.None).ConfigureAwait(false); A.CallTo(() => _processLine(A.That.Matches(info => CreationInfoMatchesSharedIdp(info, creationInfo)))).MustNotHaveHappened(); A.CallTo(() => _processLine(A.That.Not.Matches(info => CreationInfoMatchesSharedIdp(info, creationInfo)))).MustHaveHappened(4, Times.Exactly); @@ -418,9 +419,9 @@ public async Task TestUserCreationSharedIdpCreationError() .With(x => x.Error, _error) .Create()); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _identityService, _options); - var result = await sut.UploadOwnCompanySharedIdpUsersAsync(_document, (_identity.UserId, _identity.CompanyId), CancellationToken.None).ConfigureAwait(false); + var result = await sut.UploadOwnCompanySharedIdpUsersAsync(_document, CancellationToken.None).ConfigureAwait(false); A.CallTo(() => _processLine(A.That.Matches(info => CreationInfoMatchesSharedIdp(info, creationInfo)))).MustHaveHappened(); @@ -444,9 +445,9 @@ public async Task TestUserCreationSharedIdpParsingError() NextLineSharedIdp() }); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _identityService, _options); - var result = await sut.UploadOwnCompanySharedIdpUsersAsync(_document, (_identity.UserId, _identity.CompanyId), CancellationToken.None).ConfigureAwait(false); + var result = await sut.UploadOwnCompanySharedIdpUsersAsync(_document, CancellationToken.None).ConfigureAwait(false); result.Should().NotBeNull(); result.Created.Should().Be(4); @@ -473,9 +474,9 @@ public async Task TestUserCreationSharedIdpCreationThrows() A.CallTo(() => _processLine(A.That.Matches(info => CreationInfoMatchesSharedIdp(info, creationInfo)))) .Throws(_error); - var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _options); + var sut = new UserUploadBusinessLogic(_userProvisioningService, _mailingService, _identityService, _options); - var result = await sut.UploadOwnCompanySharedIdpUsersAsync(_document, (_identity.UserId, _identity.CompanyId), CancellationToken.None).ConfigureAwait(false); + var result = await sut.UploadOwnCompanySharedIdpUsersAsync(_document, CancellationToken.None).ConfigureAwait(false); A.CallTo(() => _processLine(A.That.Matches(info => CreationInfoMatchesSharedIdp(info, creationInfo)))).MustHaveHappened(); diff --git a/tests/administration/Administration.Service.Tests/Controllers/DocumentsControllerTests.cs b/tests/administration/Administration.Service.Tests/Controllers/DocumentsControllerTests.cs index 41fc8540fa..2429d18f09 100644 --- a/tests/administration/Administration.Service.Tests/Controllers/DocumentsControllerTests.cs +++ b/tests/administration/Administration.Service.Tests/Controllers/DocumentsControllerTests.cs @@ -52,14 +52,14 @@ public async Task GetDocumentContentFileAsync_WithValidData_ReturnsOk() const string contentType = "application/pdf"; var id = Guid.NewGuid(); var content = Encoding.UTF8.GetBytes("This is just test content"); - A.CallTo(() => _logic.GetDocumentAsync(A._, A._)) + A.CallTo(() => _logic.GetDocumentAsync(A._)) .Returns((fileName, content, contentType)); //Act await this._controller.GetDocumentContentFileAsync(id).ConfigureAwait(false); //Assert - A.CallTo(() => _logic.GetDocumentAsync(id, _identity.CompanyId)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _logic.GetDocumentAsync(id)).MustHaveHappenedOnceExactly(); } [Fact] diff --git a/tests/administration/Administration.Service.Tests/Controllers/IdentityProviderControllerTests.cs b/tests/administration/Administration.Service.Tests/Controllers/IdentityProviderControllerTests.cs index b201d1b8f9..406e973d4a 100644 --- a/tests/administration/Administration.Service.Tests/Controllers/IdentityProviderControllerTests.cs +++ b/tests/administration/Administration.Service.Tests/Controllers/IdentityProviderControllerTests.cs @@ -66,4 +66,17 @@ public async Task DeleteOwnCompanyIdentityProvider_WithValidData_ReturnsOk() //Assert A.CallTo(() => _logic.DeleteCompanyIdentityProviderAsync(id)).MustHaveHappenedOnceExactly(); } + + [Fact] + public async Task GetOwnIdentityProviderWithConnectedCompanies_WithValidData_ReturnsOk() + { + //Arrange + var id = Guid.NewGuid(); + + //Act + await this._controller.GetOwnIdentityProviderWithConnectedCompanies(id).ConfigureAwait(false); + + //Assert + A.CallTo(() => _logic.GetOwnIdentityProviderWithConnectedCompanies(id)).MustHaveHappenedOnceExactly(); + } } diff --git a/tests/administration/Administration.Service.Tests/Controllers/NetworkControllerTests.cs b/tests/administration/Administration.Service.Tests/Controllers/NetworkControllerTests.cs index 1e5a216545..e3984f2914 100644 --- a/tests/administration/Administration.Service.Tests/Controllers/NetworkControllerTests.cs +++ b/tests/administration/Administration.Service.Tests/Controllers/NetworkControllerTests.cs @@ -1,5 +1,4 @@ /******************************************************************************** - * Copyright (c) 2021, 2023 BMW Group AG * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional @@ -67,21 +66,6 @@ public async Task RetriggerSynchronizeUser_ReturnsExpected() .MustHaveHappenedOnceExactly(); } - [Fact] - public async Task Submit_ReturnsExpected() - { - // Arrange - var data = _fixture.Create(); - - // Act - var result = await this._controller.Submit(data, CancellationToken.None).ConfigureAwait(false); - - // Assert - result.StatusCode.Should().Be(204); - A.CallTo(() => _logic.Submit(A._, A._)) - .MustHaveHappenedOnceExactly(); - } - [Fact] public async Task RetriggerCallbackOspApprove_ReturnsExpected() { diff --git a/tests/administration/Administration.Service.Tests/Controllers/PartnerNetworkControllerTest.cs b/tests/administration/Administration.Service.Tests/Controllers/PartnerNetworkControllerTest.cs index ba19285fb4..40c09a11b8 100644 --- a/tests/administration/Administration.Service.Tests/Controllers/PartnerNetworkControllerTest.cs +++ b/tests/administration/Administration.Service.Tests/Controllers/PartnerNetworkControllerTest.cs @@ -37,20 +37,22 @@ public PartnerNetworkControllerTest() this._controller = new PartnerNetworkController(_logic); } - [Fact] - public async Task GetAllMemberCompaniesBPN_Test() + [Theory] + [InlineData(null)] + [InlineData("BPNL00000003LLHB", "CAXLBOSCHZZ")] + public async Task GetAllMemberCompaniesBPN_Test(params string[]? bpnIds) { //Arrange - - A.CallTo(() => _logic.GetAllMemberCompaniesBPNAsync()); + var bpn = bpnIds == null ? null : bpnIds.ToList(); + A.CallTo(() => _logic.GetAllMemberCompaniesBPNAsync(A>._)); //Act - var result = this._controller.GetAllMemberCompaniesBPNAsync(); + var result = this._controller.GetAllMemberCompaniesBPNAsync(bpn); //Assert await foreach (var item in result) { - A.CallTo(() => _logic.GetAllMemberCompaniesBPNAsync()).MustHaveHappenedOnceExactly(); + A.CallTo(() => _logic.GetAllMemberCompaniesBPNAsync(A>.That.IsSameAs(bpn!))).MustHaveHappenedOnceExactly(); Assert.IsType(result); } } diff --git a/tests/administration/Administration.Service.Tests/Controllers/ServiceAccountControllerTests.cs b/tests/administration/Administration.Service.Tests/Controllers/ServiceAccountControllerTests.cs index 7575a1d485..74a1ddd582 100644 --- a/tests/administration/Administration.Service.Tests/Controllers/ServiceAccountControllerTests.cs +++ b/tests/administration/Administration.Service.Tests/Controllers/ServiceAccountControllerTests.cs @@ -59,14 +59,14 @@ public async Task ExecuteCompanyUserCreation_CallsExpected() .With(x => x.ServiceAccountId, serviceAccountId) .Create(); var data = _fixture.Create(); - A.CallTo(() => _logic.CreateOwnCompanyServiceAccountAsync(A._, A._)) + A.CallTo(() => _logic.CreateOwnCompanyServiceAccountAsync(A._)) .Returns(responseData); // Act var result = await _controller.ExecuteCompanyUserCreation(data).ConfigureAwait(false); // Assert - A.CallTo(() => _logic.CreateOwnCompanyServiceAccountAsync(data, _identity.CompanyId)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _logic.CreateOwnCompanyServiceAccountAsync(data)).MustHaveHappenedOnceExactly(); result.Should().NotBeNull(); result.Should().BeOfType(); @@ -80,14 +80,14 @@ public async Task GetServiceAccountRolesAsync_CallsExpected() { // Arrange var data = _fixture.CreateMany(5); - A.CallTo(() => _logic.GetServiceAccountRolesAsync(A._, A._)) + A.CallTo(() => _logic.GetServiceAccountRolesAsync(A._)) .Returns(data.ToAsyncEnumerable()); // Act var result = await _controller.GetServiceAccountRolesAsync().ToListAsync().ConfigureAwait(false); // Assert - A.CallTo(() => _logic.GetServiceAccountRolesAsync(_identity.CompanyId, null)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _logic.GetServiceAccountRolesAsync(null)).MustHaveHappenedOnceExactly(); result.Should().NotBeNull(); result.Should().HaveCount(5); diff --git a/tests/administration/Administration.Service.Tests/Controllers/SubscriptionConfigurationControllerTests.cs b/tests/administration/Administration.Service.Tests/Controllers/SubscriptionConfigurationControllerTests.cs index 5a0a7008f6..76a87ae60a 100644 --- a/tests/administration/Administration.Service.Tests/Controllers/SubscriptionConfigurationControllerTests.cs +++ b/tests/administration/Administration.Service.Tests/Controllers/SubscriptionConfigurationControllerTests.cs @@ -114,7 +114,7 @@ public async Task SetCompanyDetail_WithValidData_ReturnsNoContent() var result = await this._controller.SetProviderCompanyDetail(data).ConfigureAwait(false); //Assert - A.CallTo(() => _logic.SetProviderCompanyDetailsAsync(data, _identity.CompanyId)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _logic.SetProviderCompanyDetailsAsync(data)).MustHaveHappenedOnceExactly(); Assert.IsType(result); } @@ -124,14 +124,14 @@ public async Task GetProviderCompanyDetail_WithValidData_ReturnsOk() //Arrange var id = Guid.NewGuid(); var data = new ProviderDetailReturnData(id, CompanyId, "https://this-is-a-test.de"); - A.CallTo(() => _logic.GetProviderCompanyDetailsAsync(_identity.CompanyId)) + A.CallTo(() => _logic.GetProviderCompanyDetailsAsync()) .Returns(data); //Act var result = await this._controller.GetServiceProviderCompanyDetail().ConfigureAwait(false); //Assert - A.CallTo(() => _logic.GetProviderCompanyDetailsAsync(_identity.CompanyId)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _logic.GetProviderCompanyDetailsAsync()).MustHaveHappenedOnceExactly(); result.Should().BeOfType(); result.Id.Should().Be(id); result.CompanyId.Should().Be(CompanyId); diff --git a/tests/administration/Administration.Service.Tests/Controllers/UserControllerTest.cs b/tests/administration/Administration.Service.Tests/Controllers/UserControllerTest.cs index 69876514b5..7d7cdc2146 100644 --- a/tests/administration/Administration.Service.Tests/Controllers/UserControllerTest.cs +++ b/tests/administration/Administration.Service.Tests/Controllers/UserControllerTest.cs @@ -54,14 +54,14 @@ public async Task ModifyUserRolesAsync_WithValidData_ReturnsExpectedResult() //Arrange var appId = new Guid("8d4bfde6-978f-4d82-86ce-8d90d52fbf3f"); var userRoleInfo = new UserRoleInfo(CompanyUserId, new[] { "Company Admin" }); - A.CallTo(() => _rolesLogic.ModifyUserRoleAsync(A._, A._, A._)) + A.CallTo(() => _rolesLogic.ModifyUserRoleAsync(A._, A._)) .Returns(Enumerable.Empty()); //Act var result = await this._controller.ModifyUserRolesAsync(appId, userRoleInfo).ConfigureAwait(false); //Assert - A.CallTo(() => _rolesLogic.ModifyUserRoleAsync(A.That.Matches(x => x == appId), A.That.Matches(x => x.CompanyUserId == CompanyUserId && x.Roles.Count() == 1), _identity.CompanyId)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _rolesLogic.ModifyUserRoleAsync(A.That.Matches(x => x == appId), A.That.Matches(x => x.CompanyUserId == CompanyUserId && x.Roles.Count() == 1))).MustHaveHappenedOnceExactly(); result.Should().BeEmpty(); } @@ -70,14 +70,14 @@ public async Task GetOwnUserDetails_ReturnsExpectedResult() { // Arrange var data = _fixture.Create(); - A.CallTo(() => _logic.GetOwnUserDetails(_identity.UserId)) + A.CallTo(() => _logic.GetOwnUserDetails()) .Returns(data); // Act var result = await this._controller.GetOwnUserDetails().ConfigureAwait(false); // Assert - A.CallTo(() => _logic.GetOwnUserDetails(_identity.UserId)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _logic.GetOwnUserDetails()).MustHaveHappenedOnceExactly(); result.Should().Be(data); } } diff --git a/tests/externalsystems/Bpdm.Library/BpdmBusinessLogicTests.cs b/tests/externalsystems/Bpdm.Library/BpdmBusinessLogicTests.cs index 5b81c02415..701f66a150 100644 --- a/tests/externalsystems/Bpdm.Library/BpdmBusinessLogicTests.cs +++ b/tests/externalsystems/Bpdm.Library/BpdmBusinessLogicTests.cs @@ -38,6 +38,7 @@ public class BpdmBusinessLogicTests private static readonly Guid IdWithBpn = new("c244f79a-7faf-4c59-bb85-fbfdf72ce46f"); private static readonly Guid IdWithSharingPending = new("920AF606-9581-4EAD-A7FD-78480F42D3A1"); private static readonly Guid IdWithSharingError = new("9460ED6B-2DD3-4446-9B9D-9AE3640717F4"); + private static readonly Guid IdWithoutSharingProcessStarted = new("f167835a-9859-4ae4-8f1d-b5d682e2562c"); private static readonly Guid IdWithStateCreated = new("bda6d1b5-042e-493a-894c-11f3a89c12b1"); private static readonly Guid IdWithoutZipCode = new("beaa6de5-d411-4da8-850e-06047d3170be"); private static readonly Guid ValidCompanyId = new("abf990f8-0c27-43dc-bbd0-b1bce964d8f4"); @@ -335,6 +336,38 @@ public async Task HandlePullLegalEntity_WithSharingStateError_ThrowsServiceExcep ex.Message.Should().Be($"ErrorCode: Code 43, ErrorMessage: This is a test sharing state error"); } + [Fact] + public async Task HandlePullLegalEntity_WithSharingProcessStartedNotSet_ReturnsExpected() + { + // Arrange + var company = new Company(Guid.NewGuid(), "Test Company", CompanyStatusId.ACTIVE, DateTimeOffset.UtcNow) + { + BusinessPartnerNumber = "1" + }; + var checklistEntry = _fixture.Build() + .With(x => x.ApplicationChecklistEntryStatusId, ApplicationChecklistEntryStatusId.TO_DO) + .Create(); + var checklist = new Dictionary + { + {ApplicationChecklistEntryTypeId.REGISTRATION_VERIFICATION, ApplicationChecklistEntryStatusId.DONE}, + {ApplicationChecklistEntryTypeId.BUSINESS_PARTNER_NUMBER, ApplicationChecklistEntryStatusId.TO_DO}, + } + .ToImmutableDictionary(); + var context = new IApplicationChecklistService.WorkerChecklistProcessStepData(IdWithoutSharingProcessStarted, default, checklist, Enumerable.Empty()); + SetupForHandlePullLegalEntity(company); + + // Act + var result = await _logic.HandlePullLegalEntity(context, CancellationToken.None).ConfigureAwait(false); + + // Assert + result.ModifyChecklistEntry?.Invoke(checklistEntry); + checklistEntry.ApplicationChecklistEntryStatusId.Should().Be(ApplicationChecklistEntryStatusId.TO_DO); + result.ScheduleStepTypeIds.Should().BeNull(); + result.SkipStepTypeIds.Should().BeNull(); + result.Modified.Should().BeFalse(); + result.ProcessMessage.Should().Be("SharingProcessStarted was not set"); + } + [Fact] public async Task HandlePullLegalEntity_WithSharingTypePending_ReturnsExpected() { @@ -469,13 +502,13 @@ private void SetupForHandlePullLegalEntity(Company? company = null) .With(x => x.BusinessPartnerNumber, (string?)null) .Create(); - A.CallTo(() => _applicationRepository.GetBpdmDataForApplicationAsync(A.That.Matches(x => x == IdWithBpn || x == IdWithSharingError || x == IdWithSharingPending))) + A.CallTo(() => _applicationRepository.GetBpdmDataForApplicationAsync(A.That.Matches(x => x == IdWithBpn || x == IdWithSharingError || x == IdWithSharingPending || x == IdWithoutSharingProcessStarted))) .Returns((ValidCompanyId, validData)); A.CallTo(() => _applicationRepository.GetBpdmDataForApplicationAsync(A.That.Matches(x => x == IdWithStateCreated))) .Returns((ValidCompanyId, new BpdmData(ValidCompanyName, null!, null!, "DE", null!, "Test", "test", null!, null!, new List<(BpdmIdentifierId UniqueIdentifierId, string Value)>()))); A.CallTo(() => _applicationRepository.GetBpdmDataForApplicationAsync(A.That.Matches(x => x == IdWithoutZipCode))) .Returns((ValidCompanyId, new BpdmData(ValidCompanyName, null!, null!, null!, null!, "Test", "test", null!, null!, new List<(BpdmIdentifierId UniqueIdentifierId, string Value)>()))); - A.CallTo(() => _applicationRepository.GetBpdmDataForApplicationAsync(A.That.Not.Matches(x => x == IdWithStateCreated || x == IdWithBpn || x == IdWithoutZipCode || x == IdWithSharingError || x == IdWithSharingPending))) + A.CallTo(() => _applicationRepository.GetBpdmDataForApplicationAsync(A.That.Not.Matches(x => x == IdWithStateCreated || x == IdWithBpn || x == IdWithoutZipCode || x == IdWithSharingError || x == IdWithSharingPending || x == IdWithoutSharingProcessStarted))) .Returns(new ValueTuple()); A.CallTo(() => _bpdmService.FetchInputLegalEntity(A.That.Matches(x => x == IdWithStateCreated.ToString()), A._)) @@ -484,15 +517,26 @@ private void SetupForHandlePullLegalEntity(Company? company = null) .Returns(_fixture.Build().With(x => x.Bpn, (string?)null).Create()); A.CallTo(() => _bpdmService.FetchInputLegalEntity(A.That.Matches(x => x == IdWithBpn.ToString()), A._)) .Returns(_fixture.Build().With(x => x.Bpn, "CAXSDUMMYCATENAZZ").Create()); - A.CallTo(() => _bpdmService.GetSharingState(A.That.Matches(x => x == IdWithBpn || x == IdWithStateCreated || x == IdWithoutZipCode), A._)) - .Returns(_fixture.Build().With(x => x.SharingStateType, BpdmSharingStateType.Success).Create()); + A.CallTo(() => _bpdmService.GetSharingState(A.That.Matches(x => x == IdWithBpn || x == IdWithStateCreated || x == IdWithoutZipCode || x == IdWithoutSharingProcessStarted), A._)) + .Returns(_fixture.Build() + .With(x => x.SharingStateType, BpdmSharingStateType.Success) + .With(x => x.SharingProcessStarted, DateTimeOffset.UtcNow) + .Create()); A.CallTo(() => _bpdmService.GetSharingState(IdWithSharingPending, A._)) - .Returns(_fixture.Build().With(x => x.SharingStateType, BpdmSharingStateType.Pending).Create()); + .Returns(_fixture.Build() + .With(x => x.SharingStateType, BpdmSharingStateType.Pending) + .With(x => x.SharingProcessStarted, DateTimeOffset.UtcNow) + .Create()); A.CallTo(() => _bpdmService.GetSharingState(IdWithSharingError, A._)) .Returns(_fixture.Build() .With(x => x.SharingStateType, BpdmSharingStateType.Error) .With(x => x.SharingErrorMessage, "This is a test sharing state error") .With(x => x.SharingErrorCode, "Code 43") + .With(x => x.SharingProcessStarted, DateTimeOffset.UtcNow) + .Create()); + A.CallTo(() => _bpdmService.GetSharingState(IdWithoutSharingProcessStarted, A._)) + .Returns(_fixture.Build() + .With(x => x.SharingProcessStarted, (DateTimeOffset?)null) .Create()); if (company != null) diff --git a/tests/externalsystems/OfferProvider.Library/BusinessLogic/OfferProviderBusinessLogicTests.cs b/tests/externalsystems/OfferProvider.Library/BusinessLogic/OfferProviderBusinessLogicTests.cs index db8cae93ef..54226de3ee 100644 --- a/tests/externalsystems/OfferProvider.Library/BusinessLogic/OfferProviderBusinessLogicTests.cs +++ b/tests/externalsystems/OfferProvider.Library/BusinessLogic/OfferProviderBusinessLogicTests.cs @@ -44,54 +44,38 @@ public class OfferProviderBusinessLogicTests private readonly Guid _salesManagerId = Guid.NewGuid(); private readonly Guid _receiverId = Guid.NewGuid(); - private readonly IFixture _fixture; - private readonly IPortalRepositories _portalRepositories; - private readonly INotificationRepository _notificationRepository; private readonly IOfferSubscriptionsRepository _offerSubscriptionRepository; private readonly IUserRolesRepository _userRolesRepository; private readonly IUserRepository _userRepository; private readonly IOfferProviderService _offerProviderService; private readonly IProvisioningManager _provisioningManager; - private readonly OfferProviderSettings _settings; private readonly OfferProviderBusinessLogic _sut; public OfferProviderBusinessLogicTests() { - _fixture = new Fixture().Customize(new AutoFakeItEasyCustomization { ConfigureMembers = true }); - _fixture.Behaviors.OfType().ToList() - .ForEach(b => _fixture.Behaviors.Remove(b)); - _fixture.Behaviors.Add(new OmitOnRecursionBehavior()); - _portalRepositories = A.Fake(); - _notificationRepository = A.Fake(); + var fixture = new Fixture().Customize(new AutoFakeItEasyCustomization { ConfigureMembers = true }); + fixture.Behaviors.OfType().ToList() + .ForEach(b => fixture.Behaviors.Remove(b)); + fixture.Behaviors.Add(new OmitOnRecursionBehavior()); + var portalRepositories = A.Fake(); _offerSubscriptionRepository = A.Fake(); _userRolesRepository = A.Fake(); _userRepository = A.Fake(); - A.CallTo(() => _portalRepositories.GetInstance()) + A.CallTo(() => portalRepositories.GetInstance()) .Returns(_offerSubscriptionRepository); - A.CallTo(() => _portalRepositories.GetInstance()) - .Returns(_notificationRepository); - A.CallTo(() => _portalRepositories.GetInstance()) + A.CallTo(() => portalRepositories.GetInstance()) .Returns(_userRolesRepository); - A.CallTo(() => _portalRepositories.GetInstance()) + A.CallTo(() => portalRepositories.GetInstance()) .Returns(_userRepository); _offerProviderService = A.Fake(); _provisioningManager = A.Fake(); - _settings = new OfferProviderSettings - { - Password = "test", - ClientId = "123", - ClientSecret = "test", - ServiceManagerRoles = Enumerable.Repeat(new UserRoleConfig("Portal", new[] { "Manager" }), 1) - }; - _sut = new OfferProviderBusinessLogic( - _portalRepositories, + portalRepositories, _offerProviderService, - _provisioningManager, - Options.Create(_settings)); + _provisioningManager); } #region TriggerProvider @@ -130,16 +114,6 @@ public async Task TriggerProvider_ValidMultiInstanceApp_ReturnsExpected(OfferTyp _offerProviderService.TriggerOfferProvider(A._, A._, A._)) .MustHaveHappenedOnceExactly(); - A.CallTo(() => _notificationRepository.CreateNotification(_salesManagerId, - offerTypeId == OfferTypeId.APP - ? NotificationTypeId.APP_SUBSCRIPTION_REQUEST - : NotificationTypeId.SERVICE_REQUEST, false, A>._)) - .MustHaveHappenedOnceExactly(); - A.CallTo(() => _notificationRepository.CreateNotification(_receiverId, - offerTypeId == OfferTypeId.APP - ? NotificationTypeId.APP_SUBSCRIPTION_REQUEST - : NotificationTypeId.SERVICE_REQUEST, false, A>._)) - .MustHaveHappenedOnceExactly(); } [Theory] @@ -161,16 +135,6 @@ public async Task TriggerProvider_ValidSingleInstanceApp_ReturnsExpected(OfferTy _offerProviderService.TriggerOfferProvider(A._, A._, A._)) .MustNotHaveHappened(); - A.CallTo(() => _notificationRepository.CreateNotification(_salesManagerId, - offerTypeId == OfferTypeId.APP - ? NotificationTypeId.APP_SUBSCRIPTION_REQUEST - : NotificationTypeId.SERVICE_REQUEST, false, A>._)) - .MustHaveHappenedOnceExactly(); - A.CallTo(() => _notificationRepository.CreateNotification(_receiverId, - offerTypeId == OfferTypeId.APP - ? NotificationTypeId.APP_SUBSCRIPTION_REQUEST - : NotificationTypeId.SERVICE_REQUEST, false, A>._)) - .MustHaveHappenedOnceExactly(); } #endregion @@ -319,8 +283,7 @@ private void SetupTriggerProvider(OfferTypeId offerTypeId = OfferTypeId.APP) _offerId, "Test App", "https://www.test.com", - new CompanyInformationData(Guid.NewGuid(), "Stark", "DE", "BPNL0000123TEST"), - "test@email.com", + new CompanyInformationData(Guid.NewGuid(), "Stark", "DE", "BPNL0000123TEST", "test@email.com"), offerTypeId, _salesManagerId, _companyUserId, @@ -332,8 +295,8 @@ private void SetupTriggerProvider(OfferTypeId offerTypeId = OfferTypeId.APP) _offerId, "Single Test App", "https://www.test.com", - new CompanyInformationData(Guid.NewGuid(), "Stark", "DE", "BPNL0000123TEST"), - "test@email.com", + new CompanyInformationData(Guid.NewGuid(), "Stark", "DE", "BPNL0000123TEST", + "test@email.com"), offerTypeId, _salesManagerId, _companyUserId, diff --git a/tests/externalsystems/OnboardingServiceProvider.Library.Tests/OnboardingServiceProviderBusinessLogicTests.cs b/tests/externalsystems/OnboardingServiceProvider.Library.Tests/OnboardingServiceProviderBusinessLogicTests.cs index 1b55d31651..5603cf8fc9 100644 --- a/tests/externalsystems/OnboardingServiceProvider.Library.Tests/OnboardingServiceProviderBusinessLogicTests.cs +++ b/tests/externalsystems/OnboardingServiceProvider.Library.Tests/OnboardingServiceProviderBusinessLogicTests.cs @@ -96,24 +96,6 @@ public async Task TriggerProviderCallback_WithoutExternalId_ThrowsUnexpectedCond ex.Message.Should().Be("No external registration found"); } - [Fact] - public async Task TriggerProviderCallback_WithoutBpn_ThrowsUnexpectedConditionException() - { - // Arrange - var networkRegistrationId = Guid.NewGuid(); - var secret = Encoding.UTF8.GetBytes(_fixture.Create()); - var details = new OspDetails("https://callback.url", "https://auth.url", "test1", secret); - A.CallTo(() => _networkRepository.GetCallbackData(networkRegistrationId, ProcessStepTypeId.TRIGGER_CALLBACK_OSP_APPROVED)) - .Returns((details, Guid.NewGuid(), null, Guid.NewGuid(), Enumerable.Empty())); - - // Act - async Task Act() => await _sut.TriggerProviderCallback(networkRegistrationId, ProcessStepTypeId.TRIGGER_CALLBACK_OSP_APPROVED, CancellationToken.None).ConfigureAwait(false); - - // Assert - var ex = await Assert.ThrowsAsync(Act); - ex.Message.Should().Be("Bpn must be set"); - } - [Fact] public async Task TriggerProviderCallback_WithMultipleDeclineMessages_ThrowsUnexpectedConditionException() { diff --git a/tests/framework/Framework.Logging.Tests/Framework.Logging.Tests.csproj b/tests/framework/Framework.Logging.Tests/Framework.Logging.Tests.csproj new file mode 100644 index 0000000000..e48e34ad11 --- /dev/null +++ b/tests/framework/Framework.Logging.Tests/Framework.Logging.Tests.csproj @@ -0,0 +1,48 @@ + + + + + Org.Eclipse.TractusX.Portal.Backend.Framework.Logging.Tests + Org.Eclipse.TractusX.Portal.Backend.Framework.Logging.Tests + net7.0 + enable + enable + false + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + diff --git a/tests/framework/Framework.Logging.Tests/SecretOperatorTests.cs b/tests/framework/Framework.Logging.Tests/SecretOperatorTests.cs new file mode 100644 index 0000000000..f23dcd06a3 --- /dev/null +++ b/tests/framework/Framework.Logging.Tests/SecretOperatorTests.cs @@ -0,0 +1,46 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 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.Logging.MaskingOperator; +using Serilog.Enrichers.Sensitive; + +namespace Org.Eclipse.TractusX.Portal.Backend.Framework.Logging.Tests; + +public class SecretOperatorTests +{ + [Theory] + [InlineData("foobarsecret=1234&deadbeef", "foobarsecret=****&deadbeef", true)] + [InlineData("foobarpassword=1234&deadbeef", "foobarpassword=****&deadbeef", true)] + [InlineData("foobarSecret=1234&deadbeefPassword=5678&", "foobarSecret=****&deadbeefPassword=****&", true)] + [InlineData("foobarpasssword=1234&deadbeef", null, false)] + public void Mask_ReturnsExpected(string input, string matchResult, bool match) + { + //Arrange + var sut = new SecretOperator(); + + //Act + var result = sut.Mask(input, "****"); + + //Assert + result.Should().Match(x => + x.Match == match && + x.Result == matchResult + ); + } +} diff --git a/tests/framework/Framework.Logging.Tests/Usings.cs b/tests/framework/Framework.Logging.Tests/Usings.cs new file mode 100644 index 0000000000..65016aec51 --- /dev/null +++ b/tests/framework/Framework.Logging.Tests/Usings.cs @@ -0,0 +1,24 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 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 + ********************************************************************************/ + +global using AutoFixture; +global using AutoFixture.AutoFakeItEasy; +global using FakeItEasy; +global using FluentAssertions; +global using Xunit; diff --git a/tests/framework/Framework.Web.Tests/IdentityServiceTests.cs b/tests/framework/Framework.Web.Tests/IdentityServiceTests.cs new file mode 100644 index 0000000000..16c8efd86f --- /dev/null +++ b/tests/framework/Framework.Web.Tests/IdentityServiceTests.cs @@ -0,0 +1,217 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 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 Microsoft.AspNetCore.Http; +using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Models; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities; +using System.Security.Claims; + +namespace Org.Eclipse.TractusX.Portal.Backend.Framework.Web.Tests; + +public class IdentityServiceTests +{ + private readonly IFixture _fixture; + + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly HttpContext _httpContext; + private readonly ClaimsPrincipal _user; + + public IdentityServiceTests() + { + _fixture = new Fixture().Customize(new AutoFakeItEasyCustomization { ConfigureMembers = true }); + _fixture.Behaviors.OfType().ToList() + .ForEach(b => _fixture.Behaviors.Remove(b)); + _fixture.Behaviors.Add(new OmitOnRecursionBehavior()); + + _httpContextAccessor = A.Fake(); + _httpContext = A.Fake(); + _user = A.Fake(); + A.CallTo(() => _httpContextAccessor.HttpContext).Returns(_httpContext); + } + + [Fact] + public void IdentityData_ReturnsExpected() + { + // Arrange + var sub = _fixture.Create(); + var identityId = Guid.NewGuid(); + var identityType = _fixture.Create(); + var companyId = Guid.NewGuid(); + + var sut = CreateSut(sub, identityId.ToString(), identityType.ToString(), companyId.ToString()); + + // Act + var first = sut.IdentityData; + var second = sut.IdentityData; + + // Assert + first.Should().NotBeNull() + .And.BeSameAs(second) + .And.Match(x => + x.UserEntityId == sub && + x.UserId == identityId && + x.IdentityType == identityType && + x.CompanyId == companyId); + + A.CallTo(() => _httpContext.User).MustHaveHappenedOnceExactly(); + } + + [Fact] + public void IdentityData_EmptySub_Throws() + { + // Arrange + var identityId = Guid.NewGuid(); + var identityType = _fixture.Create(); + var companyId = Guid.NewGuid(); + + var sut = CreateSut("", identityId.ToString(), identityType.ToString(), companyId.ToString()); + + // Act + var error = Assert.Throws(() => sut.IdentityData); + + // Assert + error.Message.Should().Be("Claim sub must not be null or empty (Parameter 'claims')"); + A.CallTo(() => _httpContext.User).MustHaveHappenedOnceExactly(); + } + + [Fact] + public void IdentityData_EmptyIdentityId_Throws() + { + // Arrange + var sub = _fixture.Create(); + var identityType = _fixture.Create(); + var companyId = Guid.NewGuid(); + + var sut = CreateSut(sub, "", identityType.ToString(), companyId.ToString()); + + // Act + var error = Assert.Throws(() => sut.IdentityData); + + // Assert + error.Message.Should().Be("Claim https://catena-x.net//schema/2023/05/identity/claims/identity_id must not be null or empty (Parameter 'claims')"); + A.CallTo(() => _httpContext.User).MustHaveHappenedOnceExactly(); + } + + [Fact] + public void IdentityData_NonGuidIdentityId_Throws() + { + // Arrange + var sub = _fixture.Create(); + var identityType = _fixture.Create(); + var companyId = Guid.NewGuid(); + + var sut = CreateSut(sub, "deadbeef", identityType.ToString(), companyId.ToString()); + + // Act + var error = Assert.Throws(() => sut.IdentityData); + + // Assert + error.Message.Should().Be("Claim https://catena-x.net//schema/2023/05/identity/claims/identity_id must contain a Guid (Parameter 'claims')"); + A.CallTo(() => _httpContext.User).MustHaveHappenedOnceExactly(); + } + + [Fact] + public void IdentityData_EmptyIdentityType_Throws() + { + // Arrange + var sub = _fixture.Create(); + var identityId = Guid.NewGuid(); + var companyId = Guid.NewGuid(); + + var sut = CreateSut(sub, identityId.ToString(), "", companyId.ToString()); + + // Act + var error = Assert.Throws(() => sut.IdentityData); + + // Assert + error.Message.Should().Be("Claim https://catena-x.net//schema/2023/05/identity/claims/identity_type must not be null or empty (Parameter 'claims')"); + A.CallTo(() => _httpContext.User).MustHaveHappenedOnceExactly(); + } + + [Fact] + public void IdentityData_NonEnumIdentityType_Throws() + { + // Arrange + var sub = _fixture.Create(); + var identityId = Guid.NewGuid(); + var companyId = Guid.NewGuid(); + + var sut = CreateSut(sub, identityId.ToString(), "deadbeef", companyId.ToString()); + + // Act + var error = Assert.Throws(() => sut.IdentityData); + + // Assert + error.Message.Should().Be("Claim https://catena-x.net//schema/2023/05/identity/claims/identity_type must contain a Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums.IdentityTypeId (Parameter 'claims')"); + A.CallTo(() => _httpContext.User).MustHaveHappenedOnceExactly(); + } + + [Fact] + public void IdentityData_EmptyCompanyId_Throws() + { + // Arrange + var sub = _fixture.Create(); + var identityId = Guid.NewGuid(); + var identityType = _fixture.Create(); + + var sut = CreateSut(sub, identityId.ToString(), identityType.ToString(), ""); + + // Act + var error = Assert.Throws(() => sut.IdentityData); + + // Assert + error.Message.Should().Be("Claim https://catena-x.net//schema/2023/05/identity/claims/company_id must not be null or empty (Parameter 'claims')"); + A.CallTo(() => _httpContext.User).MustHaveHappenedOnceExactly(); + } + + [Fact] + public void IdentityData_NonGuidCompanyId_Throws() + { + // Arrange + var sub = _fixture.Create(); + var identityId = Guid.NewGuid(); + var identityType = _fixture.Create(); + + var sut = CreateSut(sub, identityId.ToString(), identityType.ToString(), "deadbeef"); + + // Act + var error = Assert.Throws(() => sut.IdentityData); + + // Assert + error.Message.Should().Be("Claim https://catena-x.net//schema/2023/05/identity/claims/company_id must contain a Guid (Parameter 'claims')"); + A.CallTo(() => _httpContext.User).MustHaveHappenedOnceExactly(); + } + + private IIdentityService CreateSut(string sub, string identityId, string identityType, string companyId) + { + var claims = new Claim[] { + new(PortalClaimTypes.Sub, sub), + new(PortalClaimTypes.IdentityId, identityId), + new(PortalClaimTypes.IdentityType, identityType), + new(PortalClaimTypes.CompanyId, companyId) + }; + + A.CallTo(() => _user.Claims).Returns(claims); + A.CallTo(() => _httpContext.User).Returns(_user); + + return new IdentityService(_httpContextAccessor); + } +} diff --git a/tests/marketplace/Apps.Service.Tests/BusinessLogic/AppBusinessLogicTests.cs b/tests/marketplace/Apps.Service.Tests/BusinessLogic/AppBusinessLogicTests.cs index e62c9636fd..4ffbc0138b 100644 --- a/tests/marketplace/Apps.Service.Tests/BusinessLogic/AppBusinessLogicTests.cs +++ b/tests/marketplace/Apps.Service.Tests/BusinessLogic/AppBusinessLogicTests.cs @@ -187,7 +187,7 @@ public async Task AddServiceSubscription_ReturnsCorrectId() var offerSubscriptionId = Guid.NewGuid(); var offerSubscriptionService = A.Fake(); var consentData = _fixture.CreateMany(2); - A.CallTo(() => offerSubscriptionService.AddOfferSubscriptionAsync(A._, A>._, A._, A._, A>._)) + A.CallTo(() => offerSubscriptionService.AddOfferSubscriptionAsync(A._, A>._, A._, A._, A>._, A>._)) .Returns(offerSubscriptionId); var sut = new AppsBusinessLogic(null!, offerSubscriptionService, null!, null!, Options.Create(new AppsSettings()), _identityService); @@ -201,6 +201,7 @@ public async Task AddServiceSubscription_ReturnsCorrectId() A>._, A.That.Matches(x => x == OfferTypeId.APP), A._, + A>._, A>._)) .MustHaveHappenedOnceExactly(); } @@ -297,11 +298,11 @@ public async Task GetCompanyProvidedAppSubscriptionStatusesForUserAsync_ReturnsE // Assert result.Meta.NumberOfElements.Should().Be(5); result.Content.Should().HaveCount(5).And.Satisfy( - x => x.OfferId == data[0].OfferId && x.OfferName == data[0].ServiceName && x.CompanySubscriptionStatuses.SequenceEqual(data[0].CompanySubscriptionStatuses) && x.Image == data[0].Image, - x => x.OfferId == data[1].OfferId && x.OfferName == data[1].ServiceName && x.CompanySubscriptionStatuses.SequenceEqual(data[1].CompanySubscriptionStatuses) && x.Image == data[1].Image, - x => x.OfferId == data[2].OfferId && x.OfferName == data[2].ServiceName && x.CompanySubscriptionStatuses.SequenceEqual(data[2].CompanySubscriptionStatuses) && x.Image == data[2].Image, - x => x.OfferId == data[3].OfferId && x.OfferName == data[3].ServiceName && x.CompanySubscriptionStatuses.SequenceEqual(data[3].CompanySubscriptionStatuses) && x.Image == data[3].Image, - x => x.OfferId == data[4].OfferId && x.OfferName == data[4].ServiceName && x.CompanySubscriptionStatuses.SequenceEqual(data[4].CompanySubscriptionStatuses) && x.Image == data[4].Image + x => x.OfferId == data[0].OfferId && x.OfferName == data[0].ServiceName && x.CompanySubscriptionStatuses.SequenceEqual(data[0].CompanySubscriptionStatuses) && x.Image == data[0].Image && x.ProcessStepTypeId == data[0].ProcessStepTypeId, + x => x.OfferId == data[1].OfferId && x.OfferName == data[1].ServiceName && x.CompanySubscriptionStatuses.SequenceEqual(data[1].CompanySubscriptionStatuses) && x.Image == data[1].Image && x.ProcessStepTypeId == data[1].ProcessStepTypeId, + x => x.OfferId == data[2].OfferId && x.OfferName == data[2].ServiceName && x.CompanySubscriptionStatuses.SequenceEqual(data[2].CompanySubscriptionStatuses) && x.Image == data[2].Image && x.ProcessStepTypeId == data[2].ProcessStepTypeId, + x => x.OfferId == data[3].OfferId && x.OfferName == data[3].ServiceName && x.CompanySubscriptionStatuses.SequenceEqual(data[3].CompanySubscriptionStatuses) && x.Image == data[3].Image && x.ProcessStepTypeId == data[3].ProcessStepTypeId, + x => x.OfferId == data[4].OfferId && x.OfferName == data[4].ServiceName && x.CompanySubscriptionStatuses.SequenceEqual(data[4].CompanySubscriptionStatuses) && x.Image == data[4].Image && x.ProcessStepTypeId == data[4].ProcessStepTypeId ); A.CallTo(() => _offerSubscriptionRepository.GetOwnCompanyProvidedOfferSubscriptionStatusesUntrackedAsync(_identity.CompanyId, OfferTypeId.APP, default, A>.That.IsSameSequenceAs(new[] { OfferSubscriptionStatusId.PENDING, OfferSubscriptionStatusId.ACTIVE, OfferSubscriptionStatusId.INACTIVE }), offerId)) .MustHaveHappenedOnceExactly(); diff --git a/tests/marketplace/Apps.Service.Tests/BusinessLogic/AppChangeBusinessLogicTest.cs b/tests/marketplace/Apps.Service.Tests/BusinessLogic/AppChangeBusinessLogicTest.cs index d52fc9011b..9cadbab93e 100644 --- a/tests/marketplace/Apps.Service.Tests/BusinessLogic/AppChangeBusinessLogicTest.cs +++ b/tests/marketplace/Apps.Service.Tests/BusinessLogic/AppChangeBusinessLogicTest.cs @@ -22,7 +22,10 @@ using AutoFixture.AutoFakeItEasy; using FakeItEasy; using FluentAssertions; +using Flurl.Util; using Microsoft.Extensions.Options; +using MimeKit.Encodings; +using Org.BouncyCastle.Utilities.Collections; using Org.Eclipse.TractusX.Portal.Backend.Apps.Service.ViewModels; using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Configuration; @@ -60,6 +63,7 @@ public class AppChangeBusinessLogicTest private readonly IDocumentRepository _documentRepository; private readonly INotificationService _notificationService; private readonly IOfferService _offerService; + private readonly IIdentityService _identityService; private readonly AppChangeBusinessLogic _sut; public AppChangeBusinessLogicTest() @@ -78,6 +82,8 @@ public AppChangeBusinessLogicTest() _documentRepository = A.Fake(); _notificationService = A.Fake(); _offerService = A.Fake(); + _identityService = A.Fake(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity); var settings = new AppsSettings { @@ -92,6 +98,13 @@ public AppChangeBusinessLogicTest() CompanyAdminRoles = new[] { new UserRoleConfig(ClientId, new [] { "Company Admin" }) + }, + ActiveAppDocumentTypeIds = new[] + { + DocumentTypeId.APP_IMAGE, + DocumentTypeId.APP_TECHNICAL_INFORMATION, + DocumentTypeId.APP_CONTRACT, + DocumentTypeId.ADDITIONAL_DETAILS } }; A.CallTo(() => _portalRepositories.GetInstance()).Returns(_notificationRepository); @@ -99,7 +112,7 @@ public AppChangeBusinessLogicTest() A.CallTo(() => _portalRepositories.GetInstance()).Returns(_offerSubscriptionsRepository); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_userRolesRepository); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_documentRepository); - _sut = new AppChangeBusinessLogic(_portalRepositories, _notificationService, _provisioningManager, _offerService, Options.Create(settings)); + _sut = new AppChangeBusinessLogic(_portalRepositories, _notificationService, _provisioningManager, _offerService, _identityService, Options.Create(settings)); } #region AddActiveAppUserRole @@ -145,7 +158,7 @@ public async Task AddActiveAppUserRoleAsync_ExecutesSuccessfully() .Returns(_fixture.CreateMany(4).AsFakeIAsyncEnumerable(out var createNotificationsResultAsyncEnumerator)); //Act - var result = await _sut.AddActiveAppUserRoleAsync(appId, appAssignedRoleDesc, (_identity.UserId, _identity.CompanyId)).ConfigureAwait(false); + var result = await _sut.AddActiveAppUserRoleAsync(appId, appAssignedRoleDesc).ConfigureAwait(false); //Assert A.CallTo(() => _offerRepository.GetInsertActiveAppUserRoleDataAsync(appId, OfferTypeId.APP)).MustHaveHappened(); @@ -211,7 +224,7 @@ public async Task AddActiveAppUserRoleAsync_WithCompanyUserIdNotSet_ThrowsForbid .Returns((true, appName, Guid.NewGuid(), clientIds)); var existingOffer = _fixture.Create(); //Act - async Task Act() => await _sut.AddActiveAppUserRoleAsync(appId, appAssignedRoleDesc, (_identity.UserId, _identity.CompanyId)).ConfigureAwait(false); + async Task Act() => await _sut.AddActiveAppUserRoleAsync(appId, appAssignedRoleDesc).ConfigureAwait(false); //Assert var ex = await Assert.ThrowsAsync(Act); @@ -235,7 +248,7 @@ public async Task AddActiveAppUserRoleAsync_WithProviderCompanyNotSet_ThrowsConf .Returns((true, appName, null, clientIds)); //Act - async Task Act() => await _sut.AddActiveAppUserRoleAsync(appId, appAssignedRoleDesc, (_identity.UserId, _identity.CompanyId)).ConfigureAwait(false); + async Task Act() => await _sut.AddActiveAppUserRoleAsync(appId, appAssignedRoleDesc).ConfigureAwait(false); //Assert var ex = await Assert.ThrowsAsync(Act); @@ -258,7 +271,7 @@ public async Task GetAppUpdateDescriptionByIdAsync_ReturnsExpected() .Returns(appDescriptionData); // Act - var result = await _sut.GetAppUpdateDescriptionByIdAsync(appId, _identity.CompanyId).ConfigureAwait(false); + var result = await _sut.GetAppUpdateDescriptionByIdAsync(appId).ConfigureAwait(false); // Assert result.Should().NotBeNull(); @@ -275,7 +288,7 @@ public async Task GetAppUpdateDescriptionByIdAsync_ThrowsNotFoundException() .Returns(((bool IsStatusActive, bool IsProviderCompanyUser, IEnumerable OfferDescriptionDatas))default); // Act - async Task Act() => await _sut.GetAppUpdateDescriptionByIdAsync(appId, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.GetAppUpdateDescriptionByIdAsync(appId).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -294,7 +307,7 @@ public async Task GetAppUpdateDescriptionByIdAsync_ThrowsConflictException() .Returns(appDescriptionData); // Act - async Task Act() => await _sut.GetAppUpdateDescriptionByIdAsync(appId, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.GetAppUpdateDescriptionByIdAsync(appId).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -313,7 +326,7 @@ public async Task GetAppUpdateDescriptionByIdAsync_ThrowsForbiddenException() .Returns(appDescriptionData); // Act - async Task Act() => await _sut.GetAppUpdateDescriptionByIdAsync(appId, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.GetAppUpdateDescriptionByIdAsync(appId).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -330,7 +343,7 @@ public async Task GetAppUpdateDescriptionByIdAsync_withNullDescriptionData_Throw .Returns(appDescriptionData); // Act - var Act = () => _sut.GetAppUpdateDescriptionByIdAsync(appId, _identity.CompanyId); + var Act = () => _sut.GetAppUpdateDescriptionByIdAsync(appId); // Assert var result = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -364,7 +377,7 @@ public async Task CreateOrUpdateAppDescriptionByIdAsync_withEmptyExistingDescrip setOptionalParameters(existingOffer); }); // Act - await _sut.CreateOrUpdateAppDescriptionByIdAsync(appId, _identity.CompanyId, updateDescriptionData).ConfigureAwait(false); + await _sut.CreateOrUpdateAppDescriptionByIdAsync(appId, updateDescriptionData).ConfigureAwait(false); // Assert A.CallTo(() => _offerRepository.CreateUpdateDeleteOfferDescriptions(appId, A>._, A>.That.IsSameSequenceAs(updateDescriptionData.Select(x => new ValueTuple(x.LanguageCode, x.LongDescription, x.ShortDescription))))) @@ -387,7 +400,7 @@ public async Task CreateOrUpdateAppDescriptionByIdAsync_withNullDescriptionData_ .Returns(appDescriptionData); // Act - var Act = () => _sut.CreateOrUpdateAppDescriptionByIdAsync(appId, _identity.CompanyId, updateDescriptionData); + var Act = () => _sut.CreateOrUpdateAppDescriptionByIdAsync(appId, updateDescriptionData); // Assert var result = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -410,7 +423,7 @@ public async Task CreateOrUpdateAppDescriptionByIdAsync_ThrowsForbiddenException .Returns(appDescriptionData); // Act - var Act = () => _sut.CreateOrUpdateAppDescriptionByIdAsync(appId, _identity.CompanyId, updateDescriptionData); + var Act = () => _sut.CreateOrUpdateAppDescriptionByIdAsync(appId, updateDescriptionData); // Assert var result = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -433,7 +446,7 @@ public async Task CreateOrUpdateAppDescriptionByIdAsync_ThrowsConflictException( .Returns(appDescriptionData); // Act - var Act = () => _sut.CreateOrUpdateAppDescriptionByIdAsync(appId, _identity.CompanyId, updateDescriptionData); + var Act = () => _sut.CreateOrUpdateAppDescriptionByIdAsync(appId, updateDescriptionData); // Assert var result = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -455,7 +468,7 @@ public async Task CreateOrUpdateAppDescriptionByIdAsync_ThrowsNotFoundException( .Returns(((bool IsStatusActive, bool IsProviderCompanyUser, IEnumerable OfferDescriptionDatas))default); // Act - var Act = () => _sut.CreateOrUpdateAppDescriptionByIdAsync(appId, _identity.CompanyId, updateDescriptionData); + var Act = () => _sut.CreateOrUpdateAppDescriptionByIdAsync(appId, updateDescriptionData); // Assert var result = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -505,7 +518,7 @@ public async Task UploadOfferAssignedAppLeadImageDocumentById_ExpectedCalls() setOptionalParameters(existingOffer); }); // Act - await _sut.UploadOfferAssignedAppLeadImageDocumentByIdAsync(appId, (_identity.UserId, _identity.CompanyId), file, CancellationToken.None); + await _sut.UploadOfferAssignedAppLeadImageDocumentByIdAsync(appId, file, CancellationToken.None); // Assert A.CallTo(() => _offerRepository.GetOfferAssignedAppLeadImageDocumentsByIdAsync(appId, _identity.CompanyId, OfferTypeId.APP)).MustHaveHappenedOnceExactly(); @@ -525,11 +538,12 @@ public async Task UploadOfferAssignedAppLeadImageDocumentById_ThrowsUnsupportedM // Arrange var appId = _fixture.Create(); var identity = _fixture.Create(); + A.CallTo(() => _identityService.IdentityData).Returns(identity); var appLeadImageContentTypes = new[] { MediaTypeId.JPEG, MediaTypeId.PNG }; var file = FormFileHelper.GetFormFile("Test File", "TestImage.pdf", "application/pdf"); // Act - var Act = () => _sut.UploadOfferAssignedAppLeadImageDocumentByIdAsync(appId, (identity.UserId, identity.CompanyId), file, CancellationToken.None); + var Act = () => _sut.UploadOfferAssignedAppLeadImageDocumentByIdAsync(appId, file, CancellationToken.None); // Assert var result = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -542,13 +556,14 @@ public async Task UploadOfferAssignedAppLeadImageDocumentById_ThrowsConflictExce // Arrange var appId = _fixture.Create(); var identity = _fixture.Create(); + A.CallTo(() => _identityService.IdentityData).Returns(identity); var file = FormFileHelper.GetFormFile("Test Image", "TestImage.jpeg", "image/jpeg"); A.CallTo(() => _offerRepository.GetOfferAssignedAppLeadImageDocumentsByIdAsync(appId, identity.CompanyId, OfferTypeId.APP)) .ReturnsLazily(() => (false, true, null!)); // Act - var Act = () => _sut.UploadOfferAssignedAppLeadImageDocumentByIdAsync(appId, (identity.UserId, identity.CompanyId), file, CancellationToken.None); + var Act = () => _sut.UploadOfferAssignedAppLeadImageDocumentByIdAsync(appId, file, CancellationToken.None); // Assert var result = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -561,13 +576,14 @@ public async Task UploadOfferAssignedAppLeadImageDocumentById_ThrowsForbiddenExc // Arrange var appId = _fixture.Create(); var identity = _fixture.Create(); + A.CallTo(() => _identityService.IdentityData).Returns(identity); var file = FormFileHelper.GetFormFile("Test Image", "TestImage.jpeg", "image/jpeg"); A.CallTo(() => _offerRepository.GetOfferAssignedAppLeadImageDocumentsByIdAsync(appId, identity.CompanyId, OfferTypeId.APP)) .ReturnsLazily(() => (true, false, null!)); // Act - async Task Act() => await _sut.UploadOfferAssignedAppLeadImageDocumentByIdAsync(appId, (identity.UserId, identity.CompanyId), file, CancellationToken.None); + async Task Act() => await _sut.UploadOfferAssignedAppLeadImageDocumentByIdAsync(appId, file, CancellationToken.None); // Assert var result = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -580,13 +596,14 @@ public async Task UploadOfferAssignedAppLeadImageDocumentById_ThrowsNotFoundExce // Arrange var appId = _fixture.Create(); var identity = _fixture.Create(); + A.CallTo(() => _identityService.IdentityData).Returns(identity); var file = FormFileHelper.GetFormFile("Test Image", "TestImage.jpeg", "image/jpeg"); A.CallTo(() => _offerRepository.GetOfferAssignedAppLeadImageDocumentsByIdAsync(appId, identity.CompanyId, OfferTypeId.APP)) .ReturnsLazily(() => new ValueTuple>()); // Act - async Task Act() => await _sut.UploadOfferAssignedAppLeadImageDocumentByIdAsync(appId, (identity.UserId, identity.CompanyId), file, CancellationToken.None); + async Task Act() => await _sut.UploadOfferAssignedAppLeadImageDocumentByIdAsync(appId, file, CancellationToken.None); // Assert var result = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -655,7 +672,7 @@ public async Task UpdateTenantUrlAsync_WithValidData_CallsExpected() setOptionalParameters(existingOffer); }); // Act - await _sut.UpdateTenantUrlAsync(appId, subscriptionId, data, _identity.CompanyId).ConfigureAwait(false); + await _sut.UpdateTenantUrlAsync(appId, subscriptionId, data).ConfigureAwait(false); // Assert A.CallTo(() => _provisioningManager.UpdateClient(clientClientId, data.Url, A._)).MustHaveHappenedOnceExactly(); @@ -709,7 +726,7 @@ public async Task UpdateTenantUrlAsync_WithoutRequesterButValidData_CallsExpecte setOptionalParameters(existingOffer); }); // Act - await _sut.UpdateTenantUrlAsync(appId, subscriptionId, data, _identity.CompanyId).ConfigureAwait(false); + await _sut.UpdateTenantUrlAsync(appId, subscriptionId, data).ConfigureAwait(false); // Assert A.CallTo(() => _provisioningManager.UpdateClient(clientClientId, data.Url, A._)).MustHaveHappenedOnceExactly(); @@ -760,7 +777,7 @@ public async Task UpdateTenantUrlAsync_WithoutClientId_CallsExpected() setOptionalParameters(existingOffer); }); // Act - await _sut.UpdateTenantUrlAsync(appId, subscriptionId, data, _identity.CompanyId).ConfigureAwait(false); + await _sut.UpdateTenantUrlAsync(appId, subscriptionId, data).ConfigureAwait(false); // Assert A.CallTo(() => _provisioningManager.UpdateClient(clientClientId, data.Url, A._)).MustNotHaveHappened(); @@ -784,7 +801,7 @@ public async Task UpdateTenantUrlAsync_WithSameUrl_CallsNothing() A.CallTo(() => _offerSubscriptionsRepository.GetUpdateUrlDataAsync(appId, subscriptionId, _identity.CompanyId)) .Returns(new OfferUpdateUrlData("testApp", false, true, Guid.Empty, subscribingCompany, OfferSubscriptionStatusId.ACTIVE, new OfferUpdateUrlSubscriptionDetailData(detailId, clientClientId, oldUrl))); // Act - await _sut.UpdateTenantUrlAsync(appId, subscriptionId, data, _identity.CompanyId).ConfigureAwait(false); + await _sut.UpdateTenantUrlAsync(appId, subscriptionId, data).ConfigureAwait(false); // Assert A.CallTo(() => _provisioningManager.UpdateClient(clientClientId, oldUrl, A._)).MustNotHaveHappened(); @@ -803,7 +820,7 @@ public async Task UpdateTenantUrlAsync_WithInvalidUrl_ThrowsControllerArgumentEx var subscriptionId = _fixture.Create(); // Act - async Task Act() => await _sut.UpdateTenantUrlAsync(appId, subscriptionId, data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.UpdateTenantUrlAsync(appId, subscriptionId, data).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -827,7 +844,7 @@ public async Task UpdateTenantUrlAsync_WithoutApp_ThrowsNotFoundException() .Returns((OfferUpdateUrlData?)null); // Act - async Task Act() => await _sut.UpdateTenantUrlAsync(appId, subscriptionId, data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.UpdateTenantUrlAsync(appId, subscriptionId, data).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -853,7 +870,7 @@ public async Task UpdateTenantUrlAsync_WithSingleInstanceApp_ThrowsConflictExcep .Returns(new OfferUpdateUrlData("testApp", true, true, Guid.Empty, subscribingCompany, OfferSubscriptionStatusId.ACTIVE, new OfferUpdateUrlSubscriptionDetailData(detailId, clientClientId, oldUrl))); // Act - async Task Act() => await _sut.UpdateTenantUrlAsync(appId, subscriptionId, data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.UpdateTenantUrlAsync(appId, subscriptionId, data).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -879,7 +896,7 @@ public async Task UpdateTenantUrlAsync_WithUserNotFromProvidingCompany_ThrowsFor .Returns(new OfferUpdateUrlData("testApp", false, false, Guid.Empty, subscribingCompany, OfferSubscriptionStatusId.ACTIVE, new OfferUpdateUrlSubscriptionDetailData(detailId, clientClientId, oldUrl))); // Act - async Task Act() => await _sut.UpdateTenantUrlAsync(appId, subscriptionId, data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.UpdateTenantUrlAsync(appId, subscriptionId, data).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -905,7 +922,7 @@ public async Task UpdateTenantUrlAsync_WithInActiveApp_ThrowsConflictException() .Returns(new OfferUpdateUrlData("testApp", false, true, Guid.Empty, subscribingCompany, OfferSubscriptionStatusId.PENDING, new OfferUpdateUrlSubscriptionDetailData(detailId, clientClientId, oldUrl))); // Act - async Task Act() => await _sut.UpdateTenantUrlAsync(appId, subscriptionId, data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.UpdateTenantUrlAsync(appId, subscriptionId, data).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -929,7 +946,7 @@ public async Task UpdateTenantUrlAsync_WithoutSubscriptionDetails_ThrowsConflict .Returns(new OfferUpdateUrlData("testApp", false, true, Guid.Empty, subscribingCompany, OfferSubscriptionStatusId.ACTIVE, null)); // Act - async Task Act() => await _sut.UpdateTenantUrlAsync(appId, subscriptionId, data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.UpdateTenantUrlAsync(appId, subscriptionId, data).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -941,4 +958,42 @@ public async Task UpdateTenantUrlAsync_WithoutSubscriptionDetails_ThrowsConflict } #endregion + + #region GetActiveAppDocumentTypeDataAsync + + [Fact] + public async Task GetActiveAppDocumentTypeDataAsync_ReturnsExpected() + { + // Arrange + var appId = _fixture.Create(); + var documentId1 = _fixture.Create(); + var documentId2 = _fixture.Create(); + var documentId3 = _fixture.Create(); + var documentId4 = _fixture.Create(); + var documentId5 = _fixture.Create(); + var documentData = new[] { + new DocumentTypeData(DocumentTypeId.ADDITIONAL_DETAILS, documentId1, "TestDoc1"), + new DocumentTypeData(DocumentTypeId.ADDITIONAL_DETAILS, documentId2, "TestDoc2"), + new DocumentTypeData(DocumentTypeId.APP_IMAGE, documentId3, "TestDoc3"), + new DocumentTypeData(DocumentTypeId.APP_IMAGE, documentId4, "TestDoc4"), + new DocumentTypeData(DocumentTypeId.APP_TECHNICAL_INFORMATION, documentId5, "TestDoc5"), + }.ToAsyncEnumerable(); + + A.CallTo(() => _offerRepository.GetActiveOfferDocumentTypeDataOrderedAsync(A._, A._, OfferTypeId.APP, A>._)) + .Returns(documentData); + + // Act + var result = await _sut.GetActiveAppDocumentTypeDataAsync(appId).ConfigureAwait(false); + + // Assert + A.CallTo(() => _offerRepository.GetActiveOfferDocumentTypeDataOrderedAsync(A._, A._, OfferTypeId.APP, A>._)).MustHaveHappened(); + result.Documents.Should().NotBeNull().And.HaveCount(4).And.Satisfy( + x => x.Key == DocumentTypeId.APP_IMAGE && x.Value.SequenceEqual(new DocumentData[] { new(documentId3, "TestDoc3"), new(documentId4, "TestDoc4") }), + x => x.Key == DocumentTypeId.APP_TECHNICAL_INFORMATION && x.Value.SequenceEqual(new DocumentData[] { new(documentId5, "TestDoc5") }), + x => x.Key == DocumentTypeId.APP_CONTRACT && !x.Value.Any(), + x => x.Key == DocumentTypeId.ADDITIONAL_DETAILS && x.Value.SequenceEqual(new DocumentData[] { new(documentId1, "TestDoc1"), new(documentId2, "TestDoc2") }) + ); + } + + #endregion } diff --git a/tests/marketplace/Apps.Service.Tests/BusinessLogic/AppReleaseBusinessLogicTest.cs b/tests/marketplace/Apps.Service.Tests/BusinessLogic/AppReleaseBusinessLogicTest.cs index b834c0543f..bd561d8319 100644 --- a/tests/marketplace/Apps.Service.Tests/BusinessLogic/AppReleaseBusinessLogicTest.cs +++ b/tests/marketplace/Apps.Service.Tests/BusinessLogic/AppReleaseBusinessLogicTest.cs @@ -68,6 +68,7 @@ public class AppReleaseBusinessLogicTest private readonly IOfferSetupService _offerSetupService; private readonly AppReleaseBusinessLogic _sut; private readonly IOfferDocumentService _offerDocumentService; + private readonly IIdentityService _identityService; public AppReleaseBusinessLogicTest() { @@ -96,6 +97,9 @@ public AppReleaseBusinessLogicTest() .Create(); _identity = new(IamUserId, _companyUser.Id, IdentityTypeId.COMPANY_USER, Guid.NewGuid()); + _identityService = A.Fake(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity); + _settings = new AppsSettings { BasePortalAddress = "https://test.com/", @@ -131,7 +135,7 @@ public AppReleaseBusinessLogicTest() .With(x => x.Languages, _languageCodes.Select(x => (x, true))) .Create(); - _sut = new AppReleaseBusinessLogic(_portalRepositories, _options, _offerService, _offerDocumentService, _offerSetupService); + _sut = new AppReleaseBusinessLogic(_portalRepositories, _options, _offerService, _offerDocumentService, _offerSetupService, _identityService); } [Fact] @@ -169,7 +173,7 @@ public async Task CreateServiceOffering_WithValidDataAndEmptyDescriptions_Return setOptionalParameters(existingOffer); }); // Act - var result = await _sut.AddAppUserRoleAsync(appId, appUserRoles, _identity.CompanyId).ConfigureAwait(false); + var result = await _sut.AddAppUserRoleAsync(appId, appUserRoles).ConfigureAwait(false); // Assert A.CallTo(() => _offerRepository.IsProviderCompanyUserAsync(A._, A._, A._)).MustHaveHappened(); @@ -224,7 +228,7 @@ public async Task AddAppAsync_WithoutEmptyLanguageCodes_ThrowsException() .Create(); // Act - async Task Act() => await _sut.AddAppAsync(data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.AddAppAsync(data).ConfigureAwait(false); // Assert var error = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -240,7 +244,7 @@ public async Task AddAppAsync_WithEmptyUseCaseIds_ThrowsException() .Create(); // Act - async Task Act() => await _sut.AddAppAsync(data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.AddAppAsync(data).ConfigureAwait(false); // Assert var error = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -275,7 +279,7 @@ public async Task AddAppAsync_WithSalesManagerValidData_ReturnsExpected() }); // Act - await _sut.AddAppAsync(data, _identity.CompanyId).ConfigureAwait(false); + await _sut.AddAppAsync(data).ConfigureAwait(false); // Assert A.CallTo(() => _offerService.ValidateSalesManager(_companyUser.Id, A>._)).MustHaveHappenedOnceExactly(); @@ -328,7 +332,7 @@ public async Task AddAppAsync_WithNullSalesMangerValidData_ReturnsExpected() }); // Act - await _sut.AddAppAsync(data, _identity.CompanyId).ConfigureAwait(false); + await _sut.AddAppAsync(data).ConfigureAwait(false); // Assert A.CallTo(() => _offerService.ValidateSalesManager(A._, A>._)).MustNotHaveHappened(); @@ -370,7 +374,7 @@ public async Task UpdateAppReleaseAsync_WithoutApp_ThrowsException() var data = _fixture.Create(); // Act - async Task Act() => await _sut.UpdateAppReleaseAsync(_notExistingAppId, data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.UpdateAppReleaseAsync(_notExistingAppId, data).ConfigureAwait(false); // Assert var error = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -385,7 +389,7 @@ public async Task UpdateAppReleaseAsync_WithActiveApp_ThrowsException() var data = _fixture.Create(); // Act - async Task Act() => await _sut.UpdateAppReleaseAsync(_activeAppId, data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.UpdateAppReleaseAsync(_activeAppId, data).ConfigureAwait(false); // Assert var error = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -400,7 +404,7 @@ public async Task UpdateAppReleaseAsync_WithInvalidUser_ThrowsException() var data = _fixture.Create(); // Act - async Task Act() => await _sut.UpdateAppReleaseAsync(_differentCompanyAppId, data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.UpdateAppReleaseAsync(_differentCompanyAppId, data).ConfigureAwait(false); // Assert var error = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -417,7 +421,7 @@ public async Task UpdateAppReleaseAsync_WithInvalidLanguage_ThrowsException() .Create(); // Act - async Task Act() => await _sut.UpdateAppReleaseAsync(_existingAppId, data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.UpdateAppReleaseAsync(_existingAppId, data).ConfigureAwait(false); // Assert var error = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -445,7 +449,7 @@ public async Task UpdateAppReleaseAsync_WithValidData_ReturnsExpected() }); // Act - await _sut.UpdateAppReleaseAsync(_existingAppId, data, _identity.CompanyId).ConfigureAwait(false); + await _sut.UpdateAppReleaseAsync(_existingAppId, data).ConfigureAwait(false); // Assert A.CallTo(() => _offerRepository.AttachAndModifyOffer(A._, A>._, A>._)) @@ -497,10 +501,10 @@ public async Task CreateAppDocumentAsync_ExecutesSuccessfully() }; // Act - await _sut.CreateAppDocumentAsync(appId, DocumentTypeId.APP_CONTRACT, file, (_identity.UserId, _identity.CompanyId), CancellationToken.None).ConfigureAwait(false); + await _sut.CreateAppDocumentAsync(appId, DocumentTypeId.APP_CONTRACT, file, CancellationToken.None).ConfigureAwait(false); // Assert - A.CallTo(() => _offerDocumentService.UploadDocumentAsync(appId, DocumentTypeId.APP_CONTRACT, file, A>.That.Matches(x => x.Item1 == _identity.UserId && x.Item2 == _identity.CompanyId), OfferTypeId.APP, _settings.UploadAppDocumentTypeIds, CancellationToken.None)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _offerDocumentService.UploadDocumentAsync(appId, DocumentTypeId.APP_CONTRACT, file, OfferTypeId.APP, _settings.UploadAppDocumentTypeIds, CancellationToken.None)).MustHaveHappenedOnceExactly(); } #endregion @@ -731,7 +735,7 @@ public async Task DeleteAppAsync_ReturnsExpectedResult() .Returns((true, true, true, true, appDeleteData)); //Act - await _sut.DeleteAppAsync(appId, _identity.CompanyId).ConfigureAwait(false); + await _sut.DeleteAppAsync(appId).ConfigureAwait(false); // Assert A.CallTo(() => _offerRepository.GetAppDeleteDataAsync(appId, OfferTypeId.APP, _identity.CompanyId, OfferStatusId.CREATED)) @@ -766,7 +770,7 @@ public async Task DeleteAppAsync_WithNoProviderCompanyUser_ThrowsForbiddenExcept .Returns((true, true, true, false, appDeleteData)); //Act - async Task Act() => await _sut.DeleteAppAsync(appId, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.DeleteAppAsync(appId).ConfigureAwait(false); // Assert // Assert @@ -785,7 +789,7 @@ public async Task DeleteAppAsync_WithInvalidOfferStatus_ThrowsConflictException( .Returns((true, true, false, true, appDeleteData)); //Act - async Task Act() => await _sut.DeleteAppAsync(appId, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.DeleteAppAsync(appId).ConfigureAwait(false); // Assert // Assert @@ -828,7 +832,7 @@ public async Task SetInstanceType_WithSingleInstanceWithoutUrl_ThrowsControllerA var data = new AppInstanceSetupData(true, null); //Act - async Task Act() => await _sut.SetInstanceType(appId, data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.SetInstanceType(appId, data).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -843,7 +847,7 @@ public async Task SetInstanceType_WithMultiInstanceWithUrl_ThrowsControllerArgum var data = new AppInstanceSetupData(false, "https://test.de"); //Act - async Task Act() => await _sut.SetInstanceType(appId, data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.SetInstanceType(appId, data).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -860,7 +864,7 @@ public async Task SetInstanceType_WithNotExistingApp_NotFoundException() .ReturnsLazily(() => new ValueTuple>()); //Act - async Task Act() => await _sut.SetInstanceType(appId, data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.SetInstanceType(appId, data).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -877,7 +881,7 @@ public async Task SetInstanceType_WithInvalidUser_ThrowsForbiddenException() .ReturnsLazily(() => new ValueTuple>(OfferStatusId.ACTIVE, false, null, new List<(Guid, Guid, string)>())); //Act - async Task Act() => await _sut.SetInstanceType(appId, data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.SetInstanceType(appId, data).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -894,7 +898,7 @@ public async Task SetInstanceType_WithWrongOfferState_ThrowsConflictException() .ReturnsLazily(() => new ValueTuple>(OfferStatusId.ACTIVE, true, null, new List<(Guid, Guid, string)>())); //Act - async Task Act() => await _sut.SetInstanceType(appId, data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.SetInstanceType(appId, data).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -913,7 +917,7 @@ public async Task SetInstanceType_FromSingleToMultiWithoutAppInstance_ThrowsConf .ReturnsLazily(() => new ValueTuple>(OfferStatusId.CREATED, true, instanceSetupTransferData, new List<(Guid, Guid, string)>())); //Act - async Task Act() => await _sut.SetInstanceType(appId, data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.SetInstanceType(appId, data).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -939,7 +943,7 @@ public async Task SetInstanceType_WithNewEntry_CreatesEntry() }); //Act - await _sut.SetInstanceType(appId, data, _identity.CompanyId).ConfigureAwait(false); + await _sut.SetInstanceType(appId, data).ConfigureAwait(false); // Assert instanceSetupData.Should().NotBeNull(); @@ -974,7 +978,7 @@ public async Task SetInstanceType_WithUrlUpdate_CreatesEntry() }); //Act - await _sut.SetInstanceType(appId, data, _identity.CompanyId).ConfigureAwait(false); + await _sut.SetInstanceType(appId, data).ConfigureAwait(false); // Assert instanceSetupData.InstanceUrl.Should().Be("https://new-url.de"); @@ -1003,7 +1007,7 @@ public async Task SetInstanceType_WithExistingEntryButNoAppInstance_ThrowsConfli }); //Act - await _sut.SetInstanceType(appId, data, _identity.CompanyId).ConfigureAwait(false); + await _sut.SetInstanceType(appId, data).ConfigureAwait(false); // Assert instanceSetupData.InstanceUrl.Should().Be(data.InstanceUrl); @@ -1036,7 +1040,7 @@ public async Task SetInstanceType_WithExistingEntry_UpdatesEntry() }); //Act - await _sut.SetInstanceType(appId, data, _identity.CompanyId).ConfigureAwait(false); + await _sut.SetInstanceType(appId, data).ConfigureAwait(false); // Assert instanceSetupData.InstanceUrl.Should().Be(data.InstanceUrl); @@ -1069,7 +1073,7 @@ public async Task SetInstanceType_FromSingleToMulti_UpdatesEntry() }); //Act - await _sut.SetInstanceType(appId, data, _identity.CompanyId).ConfigureAwait(false); + await _sut.SetInstanceType(appId, data).ConfigureAwait(false); // Assert instanceSetupData.InstanceUrl.Should().BeNull(); @@ -1137,7 +1141,7 @@ public async Task UpdateTechnicalUserProfiles_ReturnsExpected() const string clientProfile = "cl"; var appId = Guid.NewGuid(); var data = _fixture.CreateMany(5); - var sut = new AppReleaseBusinessLogic(null!, Options.Create(new AppsSettings { TechnicalUserProfileClient = clientProfile }), _offerService, _offerDocumentService, null!); + var sut = new AppReleaseBusinessLogic(null!, Options.Create(new AppsSettings { TechnicalUserProfileClient = clientProfile }), _offerService, _offerDocumentService, null!, _identityService); // Act await sut @@ -1160,7 +1164,7 @@ public async Task GetTechnicalUserProfilesForOffer_ReturnsExpected() var appId = Guid.NewGuid(); A.CallTo(() => _offerService.GetTechnicalUserProfilesForOffer(appId, OfferTypeId.APP)) .Returns(_fixture.CreateMany(5)); - var sut = new AppReleaseBusinessLogic(null!, Options.Create(new AppsSettings()), _offerService, _offerDocumentService, null!); + var sut = new AppReleaseBusinessLogic(null!, Options.Create(new AppsSettings()), _offerService, _offerDocumentService, null!, _identityService); // Act var result = await sut.GetTechnicalUserProfilesForOffer(appId) diff --git a/tests/marketplace/Apps.Service.Tests/Controllers/AppChangeControllerTest.cs b/tests/marketplace/Apps.Service.Tests/Controllers/AppChangeControllerTest.cs index b79514e4ec..20eff11019 100644 --- a/tests/marketplace/Apps.Service.Tests/Controllers/AppChangeControllerTest.cs +++ b/tests/marketplace/Apps.Service.Tests/Controllers/AppChangeControllerTest.cs @@ -46,7 +46,7 @@ public AppChangeControllerTest() { _fixture = new Fixture(); _logic = A.Fake(); - this._controller = new AppChangeController(_logic); + _controller = new AppChangeController(_logic); _controller.AddControllerContextWithClaim(IamUserId, _identity); } @@ -56,15 +56,15 @@ public async Task AddActiveAppUserRole_ReturnsExpectedCount() var appId = _fixture.Create(); var appUserRoles = _fixture.CreateMany(3); var appRoleData = _fixture.CreateMany(3); - A.CallTo(() => _logic.AddActiveAppUserRoleAsync(appId, appUserRoles, A>.That.Matches(x => x.Item1 == _identity.UserId && x.Item2 == _identity.CompanyId))) + A.CallTo(() => _logic.AddActiveAppUserRoleAsync(appId, appUserRoles)) .Returns(appRoleData); //Act - var result = await this._controller.AddActiveAppUserRole(appId, appUserRoles).ConfigureAwait(false); + var result = await _controller.AddActiveAppUserRole(appId, appUserRoles).ConfigureAwait(false); foreach (var item in result) { //Assert - A.CallTo(() => _logic.AddActiveAppUserRoleAsync(appId, appUserRoles, A>.That.Matches(x => x.Item1 == _identity.UserId && x.Item2 == _identity.CompanyId))).MustHaveHappenedOnceExactly(); + A.CallTo(() => _logic.AddActiveAppUserRoleAsync(appId, appUserRoles)).MustHaveHappenedOnceExactly(); Assert.NotNull(item); Assert.IsType(item); } @@ -77,14 +77,14 @@ public async Task GetAppUpdateDescriptionsAsync_ReturnsExpected() var appId = _fixture.Create(); var offerDescriptionData = _fixture.CreateMany(3); - A.CallTo(() => _logic.GetAppUpdateDescriptionByIdAsync(A._, A._)) + A.CallTo(() => _logic.GetAppUpdateDescriptionByIdAsync(A._)) .Returns(offerDescriptionData); //Act - var result = await this._controller.GetAppUpdateDescriptionsAsync(appId).ConfigureAwait(false); + var result = await _controller.GetAppUpdateDescriptionsAsync(appId).ConfigureAwait(false); //Assert - A.CallTo(() => _logic.GetAppUpdateDescriptionByIdAsync(A._, A._)).MustHaveHappened(); + A.CallTo(() => _logic.GetAppUpdateDescriptionByIdAsync(A._)).MustHaveHappened(); } [Fact] @@ -95,10 +95,10 @@ public async Task CreateOrUpdateAppDescriptionsAsync_ReturnsExpected() var offerDescriptionData = _fixture.CreateMany(3); //Act - var result = await this._controller.CreateOrUpdateAppDescriptionsByIdAsync(appId, offerDescriptionData).ConfigureAwait(false); + var result = await _controller.CreateOrUpdateAppDescriptionsByIdAsync(appId, offerDescriptionData).ConfigureAwait(false); //Assert - A.CallTo(() => _logic.CreateOrUpdateAppDescriptionByIdAsync(A._, A._, A>._)).MustHaveHappened(); + A.CallTo(() => _logic.CreateOrUpdateAppDescriptionByIdAsync(A._, A>._)).MustHaveHappened(); result.Should().BeOfType(); } @@ -108,14 +108,14 @@ public async Task UploadOfferAssignedAppLeadImageDocumentByIdAsync_ReturnsExpect // Arrange var appId = _fixture.Create(); var file = FormFileHelper.GetFormFile("Test Image", "TestImage.jpeg", "image/jpeg"); - A.CallTo(() => _logic.UploadOfferAssignedAppLeadImageDocumentByIdAsync(A._, A>.That.Matches(x => x.Item1 == _identity.UserId && x.Item2 == _identity.CompanyId), A._, CancellationToken.None)) + A.CallTo(() => _logic.UploadOfferAssignedAppLeadImageDocumentByIdAsync(A._, A._, CancellationToken.None)) .ReturnsLazily(() => Task.CompletedTask); // Act - var result = await this._controller.UploadOfferAssignedAppLeadImageDocumentByIdAsync(appId, file, CancellationToken.None).ConfigureAwait(false); + var result = await _controller.UploadOfferAssignedAppLeadImageDocumentByIdAsync(appId, file, CancellationToken.None).ConfigureAwait(false); // Assert - A.CallTo(() => _logic.UploadOfferAssignedAppLeadImageDocumentByIdAsync(appId, A>.That.Matches(x => x.Item1 == _identity.UserId && x.Item2 == _identity.CompanyId), file, CancellationToken.None)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _logic.UploadOfferAssignedAppLeadImageDocumentByIdAsync(appId, file, CancellationToken.None)).MustHaveHappenedOnceExactly(); result.Should().BeOfType(); } @@ -126,7 +126,7 @@ public async Task DeactivateApp_ReturnsNoContent() var appId = _fixture.Create(); //Act - var result = await this._controller.DeactivateApp(appId).ConfigureAwait(false); + var result = await _controller.DeactivateApp(appId).ConfigureAwait(false); //Assert A.CallTo(() => _logic.DeactivateOfferByAppIdAsync(appId)).MustHaveHappenedOnceExactly(); @@ -141,10 +141,23 @@ public async Task UpdateTenantUrl_ReturnsExpected() var data = new UpdateTenantData("http://test.com"); //Act - var result = await this._controller.UpdateTenantUrl(appId, subscriptionId, data).ConfigureAwait(false); + var result = await _controller.UpdateTenantUrl(appId, subscriptionId, data).ConfigureAwait(false); //Assert - A.CallTo(() => _logic.UpdateTenantUrlAsync(appId, subscriptionId, data, _identity.CompanyId)).MustHaveHappened(); + A.CallTo(() => _logic.UpdateTenantUrlAsync(appId, subscriptionId, data)).MustHaveHappened(); result.Should().BeOfType(); } + + [Fact] + public async Task GetActiveAppDocuments_ReturnsExpected() + { + //Arrange + var appId = _fixture.Create(); + + //Act + await _controller.GetActiveAppDocuments(appId).ConfigureAwait(false); + + //Assert + A.CallTo(() => _logic.GetActiveAppDocumentTypeDataAsync(appId)).MustHaveHappened(); + } } diff --git a/tests/marketplace/Apps.Service.Tests/Controllers/AppReleaseProcessControllerTest.cs b/tests/marketplace/Apps.Service.Tests/Controllers/AppReleaseProcessControllerTest.cs index 3a0f2187bd..37f578a039 100644 --- a/tests/marketplace/Apps.Service.Tests/Controllers/AppReleaseProcessControllerTest.cs +++ b/tests/marketplace/Apps.Service.Tests/Controllers/AppReleaseProcessControllerTest.cs @@ -63,7 +63,7 @@ public async Task UpdateAppDocument_ReturnsExpectedResult() await this._controller.UpdateAppDocumentAsync(appId, documentTypeId, file, CancellationToken.None).ConfigureAwait(false); // Assert - A.CallTo(() => _logic.CreateAppDocumentAsync(appId, documentTypeId, file, A>.That.Matches(x => x.Item1 == _identity.UserId && x.Item2 == _identity.CompanyId), CancellationToken.None)) + A.CallTo(() => _logic.CreateAppDocumentAsync(appId, documentTypeId, file, CancellationToken.None)) .MustHaveHappenedOnceExactly(); } @@ -74,7 +74,7 @@ public async Task AddAppUserRole_AndUserRoleDescriptionWith201StatusCode() var appId = new Guid("5cf74ef8-e0b7-4984-a872-474828beb5d2"); var appUserRoles = _fixture.CreateMany(3); var appRoleData = _fixture.CreateMany(3); - A.CallTo(() => _logic.AddAppUserRoleAsync(appId, appUserRoles, _identity.CompanyId)) + A.CallTo(() => _logic.AddAppUserRoleAsync(appId, appUserRoles)) .Returns(appRoleData); //Act @@ -82,7 +82,7 @@ public async Task AddAppUserRole_AndUserRoleDescriptionWith201StatusCode() foreach (var item in result) { //Assert - A.CallTo(() => _logic.AddAppUserRoleAsync(appId, appUserRoles, _identity.CompanyId)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _logic.AddAppUserRoleAsync(appId, appUserRoles)).MustHaveHappenedOnceExactly(); Assert.NotNull(item); Assert.IsType(item); } @@ -170,7 +170,7 @@ public async Task DeleteAppRoleAsync_ReturnsExpectedResult() // Assert Assert.IsType(result); - A.CallTo(() => _logic.DeleteAppRoleAsync(appId, roleId, _identity.CompanyId)) + A.CallTo(() => _logic.DeleteAppRoleAsync(appId, roleId)) .MustHaveHappenedOnceExactly(); } @@ -179,7 +179,7 @@ public async Task GetAppProviderSalesManagerAsync_ReturnsExpectedResult() { //Arrange var data = _fixture.CreateMany(5).ToAsyncEnumerable(); - A.CallTo(() => _logic.GetAppProviderSalesManagersAsync(A._)) + A.CallTo(() => _logic.GetAppProviderSalesManagersAsync()) .Returns(data); //Act @@ -187,7 +187,7 @@ public async Task GetAppProviderSalesManagerAsync_ReturnsExpectedResult() // Assert result.Should().HaveCount(5); - A.CallTo(() => _logic.GetAppProviderSalesManagersAsync(_identity.CompanyId)) + A.CallTo(() => _logic.GetAppProviderSalesManagersAsync()) .MustHaveHappenedOnceExactly(); } @@ -197,14 +197,14 @@ public async Task ExecuteAppCreation_ReturnsExpectedId() //Arrange var appId = _fixture.Create(); var data = _fixture.Create(); - A.CallTo(() => _logic.AddAppAsync(A._, _identity.CompanyId)) + A.CallTo(() => _logic.AddAppAsync(A._)) .Returns(appId); //Act var result = await this._controller.ExecuteAppCreation(data).ConfigureAwait(false); //Assert - A.CallTo(() => _logic.AddAppAsync(data, _identity.CompanyId)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _logic.AddAppAsync(data)).MustHaveHappenedOnceExactly(); Assert.IsType(result); result.Value.Should().Be(appId); } @@ -245,7 +245,7 @@ public async Task UpdateAppRelease_ReturnsNoContent() // Assert Assert.IsType(result); - A.CallTo(() => _logic.UpdateAppReleaseAsync(appId, data, _identity.CompanyId)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _logic.UpdateAppReleaseAsync(appId, data)).MustHaveHappenedOnceExactly(); } [Fact] @@ -352,7 +352,7 @@ public async Task DeleteAppAsync_ReturnsExpectedResult() // Assert Assert.IsType(result); - A.CallTo(() => _logic.DeleteAppAsync(appId, _identity.CompanyId)) + A.CallTo(() => _logic.DeleteAppAsync(appId)) .MustHaveHappenedOnceExactly(); } @@ -365,7 +365,7 @@ public async Task SetInstanceType_ReturnsExpectedResult() var result = await _controller.SetInstanceType(appId, data).ConfigureAwait(false); Assert.IsType(result); - A.CallTo(() => _logic.SetInstanceType(appId, data, _identity.CompanyId)) + A.CallTo(() => _logic.SetInstanceType(appId, data)) .MustHaveHappenedOnceExactly(); } diff --git a/tests/marketplace/Apps.Service.Tests/appsettings.IntegrationTests.json b/tests/marketplace/Apps.Service.Tests/appsettings.IntegrationTests.json index e53d209bf6..0b7c41cb08 100644 --- a/tests/marketplace/Apps.Service.Tests/appsettings.IntegrationTests.json +++ b/tests/marketplace/Apps.Service.Tests/appsettings.IntegrationTests.json @@ -121,6 +121,12 @@ "APP_TECHNICAL_INFORMATION", "CONFORMITY_APPROVAL_BUSINESS_APPS" ], + "ActiveAppDocumentTypeIds": [ + "APP_IMAGE", + "APP_TECHNICAL_INFORMATION", + "APP_CONTRACT", + "ADDITIONAL_DETAILS" + ], "ITAdminRoles": [ { "ClientId": "Cl2-CX-Portal", diff --git a/tests/marketplace/Offer.Library.Web.Tests/OfferDocumentServiceTests.cs b/tests/marketplace/Offer.Library.Web.Tests/OfferDocumentServiceTests.cs index 71ed7deae2..99abdf91b8 100644 --- a/tests/marketplace/Offer.Library.Web.Tests/OfferDocumentServiceTests.cs +++ b/tests/marketplace/Offer.Library.Web.Tests/OfferDocumentServiceTests.cs @@ -41,6 +41,7 @@ public class OfferDocumentServiceTests private readonly IOfferRepository _offerRepository; private readonly IDocumentRepository _documentRepository; private readonly OfferDocumentService _sut; + private readonly IIdentityService _identityService; public OfferDocumentServiceTests() { @@ -49,12 +50,15 @@ public OfferDocumentServiceTests() .ForEach(b => _fixture.Behaviors.Remove(b)); _fixture.Behaviors.Add(new OmitOnRecursionBehavior()); + _identityService = A.Fake(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity); + _portalRepositories = A.Fake(); _offerRepository = A.Fake(); _documentRepository = A.Fake(); SetupCreateDocument(); - _sut = new OfferDocumentService(_portalRepositories); + _sut = new OfferDocumentService(_portalRepositories, _identityService); } #region UploadDocument @@ -94,7 +98,7 @@ public async Task UploadDocumentAsync_WithValidData_CallsExpected(OfferTypeId of setOptionalParameters(existingOffer); }); // Act - await _sut.UploadDocumentAsync(_validAppId, documentTypeId, file, (_identity.UserId, _identity.CompanyId), offerTypeId, uploadDocumentTypeIdSettings, CancellationToken.None).ConfigureAwait(false); + await _sut.UploadDocumentAsync(_validAppId, documentTypeId, file, offerTypeId, uploadDocumentTypeIdSettings, CancellationToken.None).ConfigureAwait(false); // Assert A.CallTo(() => _offerRepository.AttachAndModifyOffer(_validAppId, A>._, A?>._)).MustHaveHappenedOnceExactly(); @@ -118,7 +122,7 @@ public async Task UploadDocumentAsync_InValidData_ThrowsNotFoundException(OfferT .Returns(((bool, bool, bool))default); // Act - async Task Act() => await _sut.UploadDocumentAsync(id, documentTypeId, file, (_identity.UserId, _identity.CompanyId), offerTypeId, uploadDocumentTypeIdSettings, CancellationToken.None).ConfigureAwait(false); + async Task Act() => await _sut.UploadDocumentAsync(id, documentTypeId, file, offerTypeId, uploadDocumentTypeIdSettings, CancellationToken.None).ConfigureAwait(false); // Arrange var ex = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -137,7 +141,7 @@ public async Task UploadDocumentAsync_EmptyId_ThrowsControllerArgumentException( var file = FormFileHelper.GetFormFile("this is just a test", "superFile.pdf", "application/pdf"); // Act - async Task Act() => await _sut.UploadDocumentAsync(Guid.Empty, documentTypeId, file, (_identity.UserId, _identity.CompanyId), offerTypeId, uploadDocumentTypeIdSettings, CancellationToken.None).ConfigureAwait(false); + async Task Act() => await _sut.UploadDocumentAsync(Guid.Empty, documentTypeId, file, offerTypeId, uploadDocumentTypeIdSettings, CancellationToken.None).ConfigureAwait(false); // Arrange var ex = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -157,7 +161,7 @@ public async Task UploadDocumentAsync_EmptyFileName_ThrowsControllerArgumentExce var file = FormFileHelper.GetFormFile("this is just a test", "", "application/pdf"); // Act - async Task Act() => await _sut.UploadDocumentAsync(id, documentTypeId, file, (_identity.UserId, _identity.CompanyId), offerTypeId, uploadDocumentTypeIdSettings, CancellationToken.None).ConfigureAwait(false); + async Task Act() => await _sut.UploadDocumentAsync(id, documentTypeId, file, offerTypeId, uploadDocumentTypeIdSettings, CancellationToken.None).ConfigureAwait(false); // Arrange var ex = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -177,7 +181,7 @@ public async Task UploadDocumentAsync_contentType_ThrowsUnsupportedMediaTypeExce var file = FormFileHelper.GetFormFile("this is just a test", "TestFile.txt", "image/svg+xml"); // Act - async Task Act() => await _sut.UploadDocumentAsync(id, documentTypeId, file, (_identity.UserId, _identity.CompanyId), offerTypeId, uploadDocumentTypeIdSettings, CancellationToken.None).ConfigureAwait(false); + async Task Act() => await _sut.UploadDocumentAsync(id, documentTypeId, file, offerTypeId, uploadDocumentTypeIdSettings, CancellationToken.None).ConfigureAwait(false); // Arrange var ex = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -197,7 +201,7 @@ public async Task UploadDocumentAsync_contentType_ThrowsUnsupportedMediaTypeExce var file = FormFileHelper.GetFormFile("this is just a test", "TestFile.txt", "foo/bar"); // Act - async Task Act() => await _sut.UploadDocumentAsync(id, documentTypeId, file, (_identity.UserId, _identity.CompanyId), offerTypeId, uploadDocumentTypeIdSettings, CancellationToken.None).ConfigureAwait(false); + async Task Act() => await _sut.UploadDocumentAsync(id, documentTypeId, file, offerTypeId, uploadDocumentTypeIdSettings, CancellationToken.None).ConfigureAwait(false); // Arrange var ex = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -217,7 +221,7 @@ public async Task UploadDocumentAsync_documentType_ThrowsControllerArgumentExcep var file = FormFileHelper.GetFormFile("this is just a test", "superFile.pdf", "application/pdf"); // Act - async Task Act() => await _sut.UploadDocumentAsync(id, documentTypeId, file, (_identity.UserId, _identity.CompanyId), offerTypeId, uploadDocumentTypeIdSettings, CancellationToken.None).ConfigureAwait(false); + async Task Act() => await _sut.UploadDocumentAsync(id, documentTypeId, file, offerTypeId, uploadDocumentTypeIdSettings, CancellationToken.None).ConfigureAwait(false); // Arrange var ex = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -232,6 +236,7 @@ public async Task UploadDocumentAsync_isStatusCreated_ThrowsConflictException(Of // Arrange var id = _fixture.Create(); var identity = _fixture.Create(); + A.CallTo(() => _identityService.IdentityData).Returns(identity); var uploadDocumentTypeIdSettings = offerTypeId == OfferTypeId.APP ? new UploadDocumentConfig[] { new(DocumentTypeId.APP_CONTRACT, new[] { MediaTypeId.PDF }) } : new UploadDocumentConfig[] { new(DocumentTypeId.ADDITIONAL_DETAILS, new[] { MediaTypeId.PDF }) }; @@ -240,7 +245,7 @@ public async Task UploadDocumentAsync_isStatusCreated_ThrowsConflictException(Of .Returns((true, false, true)); // Act - async Task Act() => await _sut.UploadDocumentAsync(id, documentTypeId, file, (identity.UserId, identity.CompanyId), offerTypeId, uploadDocumentTypeIdSettings, CancellationToken.None).ConfigureAwait(false); + async Task Act() => await _sut.UploadDocumentAsync(id, documentTypeId, file, offerTypeId, uploadDocumentTypeIdSettings, CancellationToken.None).ConfigureAwait(false); // Arrange var ex = await Assert.ThrowsAsync(Act).ConfigureAwait(false); diff --git a/tests/marketplace/Offers.Library.Tests/Service/OfferSetupServiceTests.cs b/tests/marketplace/Offers.Library.Tests/Service/OfferSetupServiceTests.cs index 4897a0fa39..20f7edd633 100644 --- a/tests/marketplace/Offers.Library.Tests/Service/OfferSetupServiceTests.cs +++ b/tests/marketplace/Offers.Library.Tests/Service/OfferSetupServiceTests.cs @@ -122,7 +122,7 @@ public OfferSetupServiceTests() public async Task AutoSetup_WithValidData_ReturnsExpectedNotificationAndSecret(OfferTypeId offerTypeId, bool technicalUserRequired, bool isSingleInstance) { // Arrange - var offerSubscription = new OfferSubscription(Guid.NewGuid(), Guid.Empty, Guid.Empty, OfferSubscriptionStatusId.PENDING, Guid.Empty); + var offerSubscription = new OfferSubscription(Guid.NewGuid(), Guid.Empty, Guid.Empty, OfferSubscriptionStatusId.PENDING, Guid.Empty, default); var companyServiceAccount = new CompanyServiceAccount(Guid.NewGuid(), "test", "test", CompanyServiceAccountTypeId.OWN); var createNotificationsEnumerator = SetupAutoSetup(offerTypeId, offerSubscription, isSingleInstance, companyServiceAccount); var clientId = Guid.NewGuid(); @@ -247,7 +247,7 @@ public async Task AutoSetup_WithValidData_ReturnsExpectedNotificationAndSecret(O public async Task AutoSetup_WithMultipleTechnicalUsers_ThrowsException() { // Arrange - var offerSubscription = new OfferSubscription(Guid.NewGuid(), Guid.Empty, Guid.Empty, OfferSubscriptionStatusId.PENDING, Guid.Empty); + var offerSubscription = new OfferSubscription(Guid.NewGuid(), Guid.Empty, Guid.Empty, OfferSubscriptionStatusId.PENDING, Guid.Empty, default); var companyServiceAccount = new CompanyServiceAccount(Guid.NewGuid(), "test", "test", CompanyServiceAccountTypeId.OWN); SetupAutoSetup(OfferTypeId.APP, offerSubscription, false, companyServiceAccount); var clientId = Guid.NewGuid(); @@ -1134,7 +1134,7 @@ public async Task CreateTechnicalUser_WithTechnicalUserNeeded_ReturnsExpected(st public async Task ActivateSubscription_WithValidData_ReturnsExpected() { // Arrange - var offerSubscription = new OfferSubscription(Guid.NewGuid(), _validOfferId, CompanyUserCompanyId, OfferSubscriptionStatusId.PENDING, _identity.UserId); + var offerSubscription = new OfferSubscription(Guid.NewGuid(), _validOfferId, CompanyUserCompanyId, OfferSubscriptionStatusId.PENDING, _identity.UserId, default); var processStep = new ProcessStep(Guid.NewGuid(), ProcessStepTypeId.ACTIVATE_SUBSCRIPTION, ProcessStepStatusId.TODO, Guid.NewGuid(), DateTimeOffset.Now); A.CallTo(() => _offerSubscriptionsRepository.CheckOfferSubscriptionForProvider(offerSubscription.Id, _identity.CompanyId)) @@ -1178,7 +1178,7 @@ public async Task ActivateSingleInstanceSubscription_WithNotExistingOfferSubscri public async Task ActivateSingleInstanceSubscription_WithValidData_ReturnsExpected(string? requesterEmail) { // Arrange - var offerSubscription = new OfferSubscription(Guid.NewGuid(), _validOfferId, CompanyUserCompanyId, OfferSubscriptionStatusId.PENDING, _identity.UserId); + var offerSubscription = new OfferSubscription(Guid.NewGuid(), _validOfferId, CompanyUserCompanyId, OfferSubscriptionStatusId.PENDING, _identity.UserId, default); var subscriptionProcessData = new List { new(offerSubscription.Id, "https://www.test.de") @@ -1243,7 +1243,7 @@ public async Task ActivateSingleInstanceSubscription_WithValidData_ReturnsExpect public async Task ActivateMultipleInstancesSubscription_WithValidData_ReturnsExpected(string? requesterEmail) { // Arrange - var offerSubscription = new OfferSubscription(Guid.NewGuid(), _validOfferId, CompanyUserCompanyId, OfferSubscriptionStatusId.PENDING, _identity.UserId); + var offerSubscription = new OfferSubscription(Guid.NewGuid(), _validOfferId, CompanyUserCompanyId, OfferSubscriptionStatusId.PENDING, _identity.UserId, default); var subscriptionProcessData = new List { new(offerSubscription.Id, "https://www.test.de") diff --git a/tests/marketplace/Offers.Library.Tests/Service/OfferSubscriptionServiceTests.cs b/tests/marketplace/Offers.Library.Tests/Service/OfferSubscriptionServiceTests.cs index e49b9e320b..6d3d6d888f 100644 --- a/tests/marketplace/Offers.Library.Tests/Service/OfferSubscriptionServiceTests.cs +++ b/tests/marketplace/Offers.Library.Tests/Service/OfferSubscriptionServiceTests.cs @@ -131,13 +131,15 @@ public async Task AddOfferSubscription_WithExistingId_CreatesServiceSubscription { new UserRoleConfig(ClientId, new[] { "Service Manager", "Sales Manager" }) }; + var serviceManagerRoles = new[] { new UserRoleConfig("portal", new[] { "Service Manager" }) }; A.CallTo(() => _offerSubscriptionsRepository.CheckPendingOrActiveSubscriptionExists(A._, A._, A._)) .Returns(false); var companyAssignedApps = new List(); + var now = DateTimeOffset.UtcNow; A.CallTo(() => _offerSubscriptionsRepository.CreateOfferSubscription(A._, A._, A._, A._)) .Invokes((Guid offerId, Guid companyId, OfferSubscriptionStatusId offerSubscriptionStatusId, Guid requesterId) => { - var companyAssignedApp = new OfferSubscription(_newOfferSubscriptionId, offerId, companyId, offerSubscriptionStatusId, requesterId); + var companyAssignedApp = new OfferSubscription(_newOfferSubscriptionId, offerId, companyId, offerSubscriptionStatusId, requesterId, now); companyAssignedApps.Add(companyAssignedApp); }); @@ -153,7 +155,7 @@ public async Task AddOfferSubscription_WithExistingId_CreatesServiceSubscription }; // Act - await _sut.AddOfferSubscriptionAsync(_existingOfferId, _validConsentData, offerTypeId, BasePortalUrl, subscriptionManagerRoles).ConfigureAwait(false); + await _sut.AddOfferSubscriptionAsync(_existingOfferId, _validConsentData, offerTypeId, BasePortalUrl, subscriptionManagerRoles, serviceManagerRoles).ConfigureAwait(false); // Assert companyAssignedApps.Should().HaveCount(1); @@ -168,6 +170,13 @@ public async Task AddOfferSubscription_WithExistingId_CreatesServiceSubscription userParameter, A>.That.IsSameSequenceAs(template), _companyId)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _notificationRepository.CreateNotification(_salesManagerId, + offerTypeId == OfferTypeId.APP + ? NotificationTypeId.APP_SUBSCRIPTION_REQUEST + : NotificationTypeId.SERVICE_REQUEST, false, A>._)) + .MustHaveHappenedOnceExactly(); + A.CallTo(() => _offerSubscriptionsRepository.CreateOfferSubscription(A._, A._, A._, A._)).MustHaveHappenedOnceExactly(); + companyAssignedApps.Should().NotBeNull().And.HaveCount(1).And.Satisfy(x => x.DateCreated == now && x.OfferId == _existingOfferId && x.Id == _newOfferSubscriptionId); } [Theory] @@ -185,14 +194,15 @@ public async Task AddOfferSubscription_WithSalesManagerEqualsReceiver_CreatesSer { new UserRoleConfig("portal", new[] { "Service Manager", "Sales Manager" }) }; - var offerProviderDetails = _fixture.Create(); + var serviceManagerRoles = new[] { new UserRoleConfig("portal", new[] { "Service Manager" }) }; A.CallTo(() => _offerSubscriptionsRepository.CheckPendingOrActiveSubscriptionExists(A._, A._, A._)) .Returns(false); var companyAssignedApps = new List(); + var now = DateTimeOffset.UtcNow; A.CallTo(() => _offerSubscriptionsRepository.CreateOfferSubscription(A._, A._, A._, A._)) .Invokes((Guid offerId, Guid companyId, OfferSubscriptionStatusId offerSubscriptionStatusId, Guid requesterId) => { - var companyAssignedApp = new OfferSubscription(_newOfferSubscriptionId, offerId, companyId, offerSubscriptionStatusId, requesterId); + var companyAssignedApp = new OfferSubscription(_newOfferSubscriptionId, offerId, companyId, offerSubscriptionStatusId, requesterId, now); companyAssignedApps.Add(companyAssignedApp); }); var mailParameters = new[] @@ -207,7 +217,7 @@ public async Task AddOfferSubscription_WithSalesManagerEqualsReceiver_CreatesSer }; // Act - await _sut.AddOfferSubscriptionAsync(_existingOfferId, _validConsentData, offerTypeId, BasePortalUrl, subscriptionManagerRoles).ConfigureAwait(false); + await _sut.AddOfferSubscriptionAsync(_existingOfferId, _validConsentData, offerTypeId, BasePortalUrl, subscriptionManagerRoles, serviceManagerRoles).ConfigureAwait(false); // Assert companyAssignedApps.Should().HaveCount(1); @@ -217,6 +227,8 @@ public async Task AddOfferSubscription_WithSalesManagerEqualsReceiver_CreatesSer userParameter, A>.That.IsSameSequenceAs(template), _companyId)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _offerSubscriptionsRepository.CreateOfferSubscription(A._, A._, A._, A._)).MustHaveHappenedOnceExactly(); + companyAssignedApps.Should().NotBeNull().And.HaveCount(1).And.Satisfy(x => x.DateCreated == now && x.OfferId == _existingOfferId && x.Id == _newOfferSubscriptionId); } [Theory] @@ -228,18 +240,20 @@ public async Task AddOfferSubscription_WithExistingIdWithoutProviderEmail_Create var subscriptionManagerRoles = offerTypeId == OfferTypeId.APP ? new[]{ new UserRoleConfig("portal", new [] { "App Manager", "Sales Manager" })} : new[]{ new UserRoleConfig("Client1", new [] { "Service Manager", "Sales Manager" })}; + var serviceManagerRoles = new[] { new UserRoleConfig("portal", new[] { "Service Manager" }) }; A.CallTo(() => _offerSubscriptionsRepository.CheckPendingOrActiveSubscriptionExists(A._, A._, A._)) .Returns(false); var companyAssignedApps = new List(); + var now = DateTimeOffset.UtcNow; A.CallTo(() => _offerSubscriptionsRepository.CreateOfferSubscription(A._, A._, A._, A._)) .Invokes((Guid offerId, Guid companyId, OfferSubscriptionStatusId offerSubscriptionStatusId, Guid requesterId) => { - var companyAssignedApp = new OfferSubscription(_newOfferSubscriptionId, offerId, companyId, offerSubscriptionStatusId, requesterId); + var companyAssignedApp = new OfferSubscription(_newOfferSubscriptionId, offerId, companyId, offerSubscriptionStatusId, requesterId, now); companyAssignedApps.Add(companyAssignedApp); }); // Act - await _sut.AddOfferSubscriptionAsync(_existingOfferIdWithoutProviderEmail, _validConsentData, offerTypeId, BasePortalUrl, subscriptionManagerRoles).ConfigureAwait(false); + await _sut.AddOfferSubscriptionAsync(_existingOfferIdWithoutProviderEmail, _validConsentData, offerTypeId, BasePortalUrl, subscriptionManagerRoles, serviceManagerRoles).ConfigureAwait(false); // Assert companyAssignedApps.Should().HaveCount(1); @@ -252,12 +266,13 @@ public async Task AddOfferSubscription_WithExistingAppSubscriptionAndProcessStep // Arrange var subscriptionManagerRoles = new[]{ new UserRoleConfig("portal", new [] { "App Manager", "Sales Manager" })}; + var serviceManagerRoles = new[] { new UserRoleConfig("portal", new[] { "Service Manager" }) }; var subscriptionId = Guid.NewGuid(); A.CallTo(() => _offerSubscriptionsRepository.CheckPendingOrActiveSubscriptionExists(A._, A._, A._)) .Returns(false); // Act - await _sut.AddOfferSubscriptionAsync(_existingOfferId, _validConsentData, OfferTypeId.APP, BasePortalUrl, subscriptionManagerRoles).ConfigureAwait(false); + await _sut.AddOfferSubscriptionAsync(_existingOfferId, _validConsentData, OfferTypeId.APP, BasePortalUrl, subscriptionManagerRoles, serviceManagerRoles).ConfigureAwait(false); // Assert A.CallTo(() => _offerSubscriptionsRepository.CheckPendingOrActiveSubscriptionExists(_existingOfferId, _companyId, OfferTypeId.APP)).MustHaveHappenedOnceExactly(); @@ -273,11 +288,12 @@ public async Task AddOfferSubscription_WithExistingActiveAppSubscription_Throws( // Arrange var subscriptionManagerRoles = new[]{ new UserRoleConfig("portal", new [] { "App Manager", "Sales Manager" })}; + var serviceManagerRoles = new[] { new UserRoleConfig("portal", new[] { "Service Manager" }) }; var subscriptionId = Guid.NewGuid(); A.CallTo(() => _offerSubscriptionsRepository.CheckPendingOrActiveSubscriptionExists(A._, A._, A._)) .Returns(true); - var Act = () => _sut.AddOfferSubscriptionAsync(_existingOfferId, _validConsentData, OfferTypeId.APP, BasePortalUrl, subscriptionManagerRoles); + var Act = () => _sut.AddOfferSubscriptionAsync(_existingOfferId, _validConsentData, OfferTypeId.APP, BasePortalUrl, subscriptionManagerRoles, serviceManagerRoles); // Act var result = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -300,18 +316,16 @@ public async Task AddOfferSubscription_NotAssignedCompany_ThrowsException(OfferT var subscriptionManagerRoles = offerTypeId == OfferTypeId.APP ? new[]{ new UserRoleConfig("portal", new [] { "App Manager", "Sales Manager" })} : new[]{ new UserRoleConfig("portal", new [] { "Service Manager", "Sales Manager" })}; - var identity = _fixture.Build() - .With(x => x.CompanyId, _notAssignedCompanyId) - .Create(); - A.CallTo(() => _identityService.IdentityData).Returns(identity); + var serviceManagerRoles = new[] { new UserRoleConfig("portal", new[] { "Service Manager" }) }; + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { CompanyId = _notAssignedCompanyId }); // Act - async Task Action() => await _sut.AddOfferSubscriptionAsync(_existingOfferId, Enumerable.Empty(), offerTypeId, BasePortalUrl, subscriptionManagerRoles).ConfigureAwait(false); + async Task Action() => await _sut.AddOfferSubscriptionAsync(_existingOfferId, Enumerable.Empty(), offerTypeId, BasePortalUrl, subscriptionManagerRoles, serviceManagerRoles).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Action); ex.ParamName.Should().Be("companyId"); - ex.Message.Should().Be($"Company {identity.CompanyId} does not exist (Parameter 'companyId')"); + ex.Message.Should().Be($"Company {_notAssignedCompanyId} does not exist (Parameter 'companyId')"); } [Theory] @@ -323,10 +337,11 @@ public async Task AddOfferSubscription_WithNotExistingId_ThrowsException(OfferTy var subscriptionManagerRoles = offerTypeId == OfferTypeId.APP ? new[]{ new UserRoleConfig("portal", new [] { "App Manager", "Sales Manager" })} : new[]{ new UserRoleConfig("portal", new [] { "Service Manager", "Sales Manager" })}; + var serviceManagerRoles = new[] { new UserRoleConfig("portal", new[] { "Service Manager" }) }; var notExistingServiceId = Guid.NewGuid(); // Act - async Task Action() => await _sut.AddOfferSubscriptionAsync(notExistingServiceId, Enumerable.Empty(), offerTypeId, BasePortalUrl, subscriptionManagerRoles).ConfigureAwait(false); + async Task Action() => await _sut.AddOfferSubscriptionAsync(notExistingServiceId, Enumerable.Empty(), offerTypeId, BasePortalUrl, subscriptionManagerRoles, serviceManagerRoles).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Action); @@ -342,9 +357,10 @@ public async Task AddOfferSubscription_WithoutOfferProviderDetails_ThrowsExcepti var subscriptionManagerRoles = offerTypeId == OfferTypeId.APP ? new[]{ new UserRoleConfig("portal", new [] { "App Manager", "Sales Manager" })} : new[]{ new UserRoleConfig("portal", new [] { "Service Manager", "Sales Manager" })}; + var serviceManagerRoles = new[] { new UserRoleConfig("portal", new[] { "Service Manager" }) }; // Act - async Task Action() => await _sut.AddOfferSubscriptionAsync(_existingOfferWithoutDetailsFilled, Enumerable.Empty(), offerTypeId, BasePortalUrl, subscriptionManagerRoles).ConfigureAwait(false); + async Task Action() => await _sut.AddOfferSubscriptionAsync(_existingOfferWithoutDetailsFilled, Enumerable.Empty(), offerTypeId, BasePortalUrl, subscriptionManagerRoles, serviceManagerRoles).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Action); @@ -360,10 +376,11 @@ public async Task AddOfferSubscription_WithMissingConsentData_ThrowsControllerAr var subscriptionManagerRoles = offerTypeId == OfferTypeId.APP ? new[]{ new UserRoleConfig("portal", new [] { "App Manager", "Sales Manager" })} : new[]{ new UserRoleConfig("portal", new [] { "Service Manager", "Sales Manager" })}; + var serviceManagerRoles = new[] { new UserRoleConfig("portal", new[] { "Service Manager" }) }; var consentData = Enumerable.Empty(); // Act - async Task Action() => await _sut.AddOfferSubscriptionAsync(_existingOfferId, consentData, offerTypeId, BasePortalUrl, subscriptionManagerRoles).ConfigureAwait(false); + async Task Action() => await _sut.AddOfferSubscriptionAsync(_existingOfferId, consentData, offerTypeId, BasePortalUrl, subscriptionManagerRoles, serviceManagerRoles).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Action); @@ -381,11 +398,12 @@ public async Task AddOfferSubscription_WithAdditionalConsentData_ThrowsControlle var subscriptionManagerRoles = offerTypeId == OfferTypeId.APP ? new[]{ new UserRoleConfig("portal", new [] { "App Manager", "Sales Manager" })} : new[]{ new UserRoleConfig("portal", new [] { "Service Manager", "Sales Manager" })}; + var serviceManagerRoles = new[] { new UserRoleConfig("portal", new[] { "Service Manager" }) }; var additional = _fixture.CreateMany().ToImmutableArray(); var consentData = _validConsentData.Concat(additional).ToImmutableArray(); // Act - async Task Action() => await _sut.AddOfferSubscriptionAsync(_existingOfferId, consentData, offerTypeId, BasePortalUrl, subscriptionManagerRoles).ConfigureAwait(false); + async Task Action() => await _sut.AddOfferSubscriptionAsync(_existingOfferId, consentData, offerTypeId, BasePortalUrl, subscriptionManagerRoles, serviceManagerRoles).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Action); @@ -403,10 +421,11 @@ public async Task AddOfferSubscription_WithInactiveConsentData_ThrowsControllerA var subscriptionManagerRoles = offerTypeId == OfferTypeId.APP ? new[]{ new UserRoleConfig("portal", new [] { "App Manager", "Sales Manager" })} : new[]{ new UserRoleConfig("portal", new [] { "Service Manager", "Sales Manager" })}; + var serviceManagerRoles = new[] { new UserRoleConfig("portal", new[] { "Service Manager" }) }; var consentData = _offerAgreementIds.Select(id => new OfferAgreementConsentData(id, ConsentStatusId.INACTIVE)).ToImmutableArray(); // Act - async Task Action() => await _sut.AddOfferSubscriptionAsync(_existingOfferId, consentData, offerTypeId, BasePortalUrl, subscriptionManagerRoles).ConfigureAwait(false); + async Task Action() => await _sut.AddOfferSubscriptionAsync(_existingOfferId, consentData, offerTypeId, BasePortalUrl, subscriptionManagerRoles, serviceManagerRoles).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Action); @@ -424,11 +443,9 @@ public async Task AddOfferSubscription_WithoutBuisnessPartnerNumber_ThrowsConfli var subscriptionManagerRoles = offerTypeId == OfferTypeId.APP ? new[]{ new UserRoleConfig("portal", new [] { "App Manager", "Sales Manager" })} : new[]{ new UserRoleConfig("portal", new [] { "Service Manager", "Sales Manager" })}; - var identity = _fixture.Build() - .With(x => x.CompanyId, _noBpnSetCompanyId) - .Create(); - A.CallTo(() => _identityService.IdentityData).Returns(identity); - async Task Action() => await _sut.AddOfferSubscriptionAsync(_existingOfferId, Enumerable.Empty(), offerTypeId, BasePortalUrl, subscriptionManagerRoles).ConfigureAwait(false); + var serviceManagerRoles = new[] { new UserRoleConfig("portal", new[] { "Service Manager" }) }; + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { CompanyId = _noBpnSetCompanyId }); + async Task Action() => await _sut.AddOfferSubscriptionAsync(_existingOfferId, Enumerable.Empty(), offerTypeId, BasePortalUrl, subscriptionManagerRoles, serviceManagerRoles).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Action); @@ -444,12 +461,13 @@ public async Task AddOfferSubscription_EmptyProviderCompanyId_ThrowsConflictExce var subscriptionManagerRoles = offerTypeId == OfferTypeId.APP ? new[]{ new UserRoleConfig(ClientId, new [] { "App Manager", "Sales Manager" })} : new[]{ new UserRoleConfig(ClientId, new [] { "Service Manager", "Sales Manager" })}; + var serviceManagerRoles = new[] { new UserRoleConfig("portal", new[] { "Service Manager" }) }; A.CallTo(() => _offerRepository.GetOfferProviderDetailsAsync(A.That.Matches(x => x == _existingOfferId), A._)) .Returns(new OfferProviderDetailsData("Test Offer", "Test Company", "provider@mail.de", _salesManagerId, "https://www.testurl.com", false, null)); // Act - async Task Action() => await _sut.AddOfferSubscriptionAsync(_existingOfferId, _validConsentData, offerTypeId, BasePortalUrl, subscriptionManagerRoles).ConfigureAwait(false); + async Task Action() => await _sut.AddOfferSubscriptionAsync(_existingOfferId, _validConsentData, offerTypeId, BasePortalUrl, subscriptionManagerRoles, serviceManagerRoles).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Action); @@ -466,15 +484,13 @@ public async Task AddOfferSubscription_WithExistingActiveSubscription_ThrowsConf // Arrange var subscriptionManagerRoles = new[]{ new UserRoleConfig("portal", new [] { "App Manager", "Sales Manager" })}; - var identity = _fixture.Build() - .With(x => x.CompanyId, _existingActiveSubscriptionCompanyId) - .Create(); - A.CallTo(() => _identityService.IdentityData).Returns(identity); - A.CallTo(() => _offerSubscriptionsRepository.CheckPendingOrActiveSubscriptionExists(_existingOfferId, identity.CompanyId, A._)) + var serviceManagerRoles = new[] { new UserRoleConfig("portal", new[] { "Service Manager" }) }; + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { CompanyId = _existingActiveSubscriptionCompanyId }); + A.CallTo(() => _offerSubscriptionsRepository.CheckPendingOrActiveSubscriptionExists(_existingOfferId, _existingActiveSubscriptionCompanyId, A._)) .Returns(true); // Act - async Task Act() => await _sut.AddOfferSubscriptionAsync(_existingOfferId, _validConsentData, OfferTypeId.APP, BasePortalUrl, subscriptionManagerRoles).ConfigureAwait(false); + async Task Act() => await _sut.AddOfferSubscriptionAsync(_existingOfferId, _validConsentData, OfferTypeId.APP, BasePortalUrl, subscriptionManagerRoles, serviceManagerRoles).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -511,16 +527,16 @@ private void SetupRepositories() .With(x => x.Id, _existingOfferId) .Create(); - A.CallTo(() => _companyRepository.GetOwnCompanyInformationAsync(_identity.CompanyId)) - .Returns(new CompanyInformationData(_companyId, "The Company", "DE", "BPM00000001")); - A.CallTo(() => _companyRepository.GetOwnCompanyInformationAsync(_notAssignedCompanyId)) + A.CallTo(() => _companyRepository.GetOwnCompanyInformationAsync(_identity.CompanyId, _identity.UserId)) + .Returns(new CompanyInformationData(_companyId, "The Company", "DE", "BPM00000001", "test@mail.com")); + A.CallTo(() => _companyRepository.GetOwnCompanyInformationAsync(_notAssignedCompanyId, _identity.UserId)) .Returns((CompanyInformationData?)null); - A.CallTo(() => _companyRepository.GetOwnCompanyInformationAsync(_noBpnSetCompanyId)) - .Returns(new CompanyInformationData(_companyId, "The Company", "DE", null)); - A.CallTo(() => _companyRepository.GetOwnCompanyInformationAsync(_existingActiveSubscriptionCompanyId)) - .Returns(new CompanyInformationData(_existingActiveSubscriptionCompanyId, "The Company", "DE", "BPM00000001")); - A.CallTo(() => _companyRepository.GetOwnCompanyInformationAsync(_existingInactiveSubscriptionCompanyId)) - .Returns(new CompanyInformationData(_existingInactiveSubscriptionCompanyId, "The Company", "DE", "BPM00000001")); + A.CallTo(() => _companyRepository.GetOwnCompanyInformationAsync(_noBpnSetCompanyId, _identity.UserId)) + .Returns(new CompanyInformationData(_companyId, "The Company", "DE", null, "test@mail.com")); + A.CallTo(() => _companyRepository.GetOwnCompanyInformationAsync(_existingActiveSubscriptionCompanyId, _identity.UserId)) + .Returns(new CompanyInformationData(_existingActiveSubscriptionCompanyId, "The Company", "DE", "BPM00000001", "test@mail.com")); + A.CallTo(() => _companyRepository.GetOwnCompanyInformationAsync(_existingInactiveSubscriptionCompanyId, _identity.UserId)) + .Returns(new CompanyInformationData(_existingInactiveSubscriptionCompanyId, "The Company", "DE", "BPM00000001", "test@mail.com")); A.CallTo(() => _userRepository.GetServiceProviderCompanyUserWithRoleIdAsync(A.That.Matches(x => x == _existingOfferId), A>.That.IsSameSequenceAs(new[] { _userRoleId }))) .Returns(new[] { _companyUserId, _salesManagerId }.ToAsyncEnumerable()); A.CallTo(() => _userRolesRepository.GetUserRoleIdsUntrackedAsync(A>.That.Matches(x => x.First(y => y.ClientId == ClientId).ClientId == "Service Manager"))) @@ -580,6 +596,9 @@ private void SetupRepositories() A.CallTo(() => _agreementRepository.GetAgreementIdsForOfferAsync(A.That.Not.Matches(id => id == _existingOfferId || id == _existingOfferWithFailingAutoSetupId || id == _existingOfferWithoutDetailsFilled || id == _existingOfferIdWithoutProviderEmail))) .Returns(_fixture.CreateMany().ToAsyncEnumerable()); + A.CallTo(() => _userRolesRepository.GetUserRoleIdsUntrackedAsync(A>._)) + .Returns(new[] { Guid.NewGuid() }.ToAsyncEnumerable()); + A.CallTo(() => _portalRepositories.GetInstance()).Returns(_agreementRepository); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_consentRepository); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_companyRepository); diff --git a/tests/marketplace/Services.Service.Tests/BusinessLogic/ServiceBusinessLogicTests.cs b/tests/marketplace/Services.Service.Tests/BusinessLogic/ServiceBusinessLogicTests.cs index 502d47494e..a459314780 100644 --- a/tests/marketplace/Services.Service.Tests/BusinessLogic/ServiceBusinessLogicTests.cs +++ b/tests/marketplace/Services.Service.Tests/BusinessLogic/ServiceBusinessLogicTests.cs @@ -156,7 +156,7 @@ public async Task AddServiceSubscription_ReturnsCorrectId() // Arrange var offerSubscriptionId = Guid.NewGuid(); var consentData = _fixture.CreateMany(2); - A.CallTo(() => _offerSubscriptionService.AddOfferSubscriptionAsync(A._, A>._, A._, A._, A>._)) + A.CallTo(() => _offerSubscriptionService.AddOfferSubscriptionAsync(A._, A>._, A._, A._, A>._, A>._)) .Returns(offerSubscriptionId); var serviceSettings = new ServiceSettings { @@ -178,6 +178,7 @@ public async Task AddServiceSubscription_ReturnsCorrectId() A>._, A.That.Matches(x => x == OfferTypeId.SERVICE), A._, + A>._, A>._)) .MustHaveHappenedOnceExactly(); } @@ -209,11 +210,11 @@ public async Task GetCompanyProvidedServiceSubscriptionStatusesForUserAsync_Retu // Assert result.Meta.NumberOfElements.Should().Be(5); result.Content.Should().HaveCount(5).And.Satisfy( - x => x.OfferId == data[0].OfferId && x.OfferName == data[0].ServiceName && x.CompanySubscriptionStatuses.SequenceEqual(data[0].CompanySubscriptionStatuses) && x.Image == data[0].Image, - x => x.OfferId == data[1].OfferId && x.OfferName == data[1].ServiceName && x.CompanySubscriptionStatuses.SequenceEqual(data[1].CompanySubscriptionStatuses) && x.Image == data[1].Image, - x => x.OfferId == data[2].OfferId && x.OfferName == data[2].ServiceName && x.CompanySubscriptionStatuses.SequenceEqual(data[2].CompanySubscriptionStatuses) && x.Image == data[2].Image, - x => x.OfferId == data[3].OfferId && x.OfferName == data[3].ServiceName && x.CompanySubscriptionStatuses.SequenceEqual(data[3].CompanySubscriptionStatuses) && x.Image == data[3].Image, - x => x.OfferId == data[4].OfferId && x.OfferName == data[4].ServiceName && x.CompanySubscriptionStatuses.SequenceEqual(data[4].CompanySubscriptionStatuses) && x.Image == data[4].Image + x => x.OfferId == data[0].OfferId && x.OfferName == data[0].ServiceName && x.CompanySubscriptionStatuses.SequenceEqual(data[0].CompanySubscriptionStatuses) && x.Image == data[0].Image && x.ProcessStepTypeId == data[0].ProcessStepTypeId, + x => x.OfferId == data[1].OfferId && x.OfferName == data[1].ServiceName && x.CompanySubscriptionStatuses.SequenceEqual(data[1].CompanySubscriptionStatuses) && x.Image == data[1].Image && x.ProcessStepTypeId == data[1].ProcessStepTypeId, + x => x.OfferId == data[2].OfferId && x.OfferName == data[2].ServiceName && x.CompanySubscriptionStatuses.SequenceEqual(data[2].CompanySubscriptionStatuses) && x.Image == data[2].Image && x.ProcessStepTypeId == data[2].ProcessStepTypeId, + x => x.OfferId == data[3].OfferId && x.OfferName == data[3].ServiceName && x.CompanySubscriptionStatuses.SequenceEqual(data[3].CompanySubscriptionStatuses) && x.Image == data[3].Image && x.ProcessStepTypeId == data[3].ProcessStepTypeId, + x => x.OfferId == data[4].OfferId && x.OfferName == data[4].ServiceName && x.CompanySubscriptionStatuses.SequenceEqual(data[4].CompanySubscriptionStatuses) && x.Image == data[4].Image && x.ProcessStepTypeId == data[4].ProcessStepTypeId ); A.CallTo(() => _offerSubscriptionsRepository.GetOwnCompanyProvidedOfferSubscriptionStatusesUntrackedAsync(_identity.CompanyId, OfferTypeId.SERVICE, null, A>.That.IsSameSequenceAs(new[] { OfferSubscriptionStatusId.PENDING, OfferSubscriptionStatusId.ACTIVE, OfferSubscriptionStatusId.INACTIVE }), offerId)) .MustHaveHappenedOnceExactly(); diff --git a/tests/marketplace/Services.Service.Tests/BusinessLogic/ServiceReleaseBusinessLogicTest.cs b/tests/marketplace/Services.Service.Tests/BusinessLogic/ServiceReleaseBusinessLogicTest.cs index 8284c4a5f0..99b9c56e38 100644 --- a/tests/marketplace/Services.Service.Tests/BusinessLogic/ServiceReleaseBusinessLogicTest.cs +++ b/tests/marketplace/Services.Service.Tests/BusinessLogic/ServiceReleaseBusinessLogicTest.cs @@ -63,6 +63,7 @@ public class ServiceReleaseBusinessLogicTest private readonly ServiceReleaseBusinessLogic _sut; private readonly IOptions _options; private readonly IOfferDocumentService _offerDocumentService; + private readonly IIdentityService _identityService; public ServiceReleaseBusinessLogicTest() { @@ -78,6 +79,9 @@ public ServiceReleaseBusinessLogicTest() _staticDataRepository = A.Fake(); _technicalUserProfileRepository = A.Fake(); + _identityService = A.Fake(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity); + SetupRepositories(); var serviceSettings = new ServiceSettings { @@ -99,7 +103,7 @@ public ServiceReleaseBusinessLogicTest() }; _options = Options.Create(serviceSettings); _fixture.Inject(_options); - _sut = new ServiceReleaseBusinessLogic(_portalRepositories, _offerService, _offerDocumentService, _options); + _sut = new ServiceReleaseBusinessLogic(_portalRepositories, _offerService, _offerDocumentService, _identityService, _options); } [Fact] @@ -384,10 +388,9 @@ public async Task UpdateServiceAsync_WithoutService_ThrowsException() // Arrange SetupUpdateService(); var data = new ServiceUpdateRequestData("test", new List(), new List(), "123", "test@email.com", Guid.NewGuid(), null); - var sut = new ServiceReleaseBusinessLogic(_portalRepositories, _offerService, _offerDocumentService, Options.Create(new ServiceSettings())); // Act - async Task Act() => await sut.UpdateServiceAsync(_notExistingServiceId, data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.UpdateServiceAsync(_notExistingServiceId, data).ConfigureAwait(false); // Assert var error = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -400,10 +403,9 @@ public async Task UpdateServiceAsync_WithActiveService_ThrowsException() // Arrange SetupUpdateService(); var data = new ServiceUpdateRequestData("test", new List(), new List(), "123", "test@email.com", Guid.NewGuid(), null); - var sut = new ServiceReleaseBusinessLogic(_portalRepositories, _offerService, _offerDocumentService, Options.Create(new ServiceSettings())); // Act - async Task Act() => await sut.UpdateServiceAsync(_activeServiceId, data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.UpdateServiceAsync(_activeServiceId, data).ConfigureAwait(false); // Assert var error = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -416,10 +418,9 @@ public async Task UpdateServiceAsync_WithInvalidUser_ThrowsException() // Arrange SetupUpdateService(); var data = new ServiceUpdateRequestData("test", new List(), new List(), "123", "test@email.com", Guid.NewGuid(), null); - var sut = new ServiceReleaseBusinessLogic(_portalRepositories, _offerService, _offerDocumentService, Options.Create(new ServiceSettings())); // Act - async Task Act() => await sut.UpdateServiceAsync(_differentCompanyServiceId, data, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await _sut.UpdateServiceAsync(_differentCompanyServiceId, data).ConfigureAwait(false); // Assert var error = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -459,10 +460,10 @@ public async Task UpdateServiceAsync_WithValidData_ReturnsExpected() initializeParameters?.Invoke(existingOffer); setOptionalParameters(existingOffer); }); - var sut = new ServiceReleaseBusinessLogic(_portalRepositories, _offerService, _offerDocumentService, Options.Create(settings)); + var sut = new ServiceReleaseBusinessLogic(_portalRepositories, _offerService, _offerDocumentService, _identityService, Options.Create(settings)); // Act - await sut.UpdateServiceAsync(_existingServiceId, data, _identity.CompanyId).ConfigureAwait(false); + await sut.UpdateServiceAsync(_existingServiceId, data).ConfigureAwait(false); // Assert A.CallTo(() => _offerRepository.AttachAndModifyOffer(A._, A>._, A>._)) @@ -487,10 +488,9 @@ public async Task UpdateServiceAsync_WithValidData_ReturnsExpected() public async Task SubmitServiceAsync_CallsOfferService() { // Arrange - var sut = new ServiceReleaseBusinessLogic(null!, _offerService, _offerDocumentService, _options); // Act - await sut.SubmitServiceAsync(_existingServiceId).ConfigureAwait(false); + await _sut.SubmitServiceAsync(_existingServiceId).ConfigureAwait(false); // Assert A.CallTo(() => @@ -516,7 +516,7 @@ public async Task DeclineServiceRequestAsync_CallsExpected() ServiceManagerRoles = _fixture.CreateMany(), BasePortalAddress = "test" }; - var sut = new ServiceReleaseBusinessLogic(null!, _offerService, _offerDocumentService, Options.Create(settings)); + var sut = new ServiceReleaseBusinessLogic(null!, _offerService, _offerDocumentService, _identityService, Options.Create(settings)); // Act await sut.DeclineServiceRequestAsync(_existingServiceId, data).ConfigureAwait(false); @@ -544,13 +544,13 @@ public async Task CreateServiceDocument_ExecutesSuccessfully() new UploadDocumentConfig(DocumentTypeId.ADDITIONAL_DETAILS, new []{ MediaTypeId.PDF }) } }; - var sut = new ServiceReleaseBusinessLogic(_portalRepositories, _offerService, _offerDocumentService, Options.Create(settings)); + var sut = new ServiceReleaseBusinessLogic(_portalRepositories, _offerService, _offerDocumentService, _identityService, Options.Create(settings)); // Act - await sut.CreateServiceDocumentAsync(serviceId, DocumentTypeId.ADDITIONAL_DETAILS, file, (_identity.UserId, _identity.CompanyId), CancellationToken.None).ConfigureAwait(false); + await sut.CreateServiceDocumentAsync(serviceId, DocumentTypeId.ADDITIONAL_DETAILS, file, CancellationToken.None).ConfigureAwait(false); // Assert - A.CallTo(() => _offerDocumentService.UploadDocumentAsync(serviceId, DocumentTypeId.ADDITIONAL_DETAILS, file, A<(Guid, Guid)>.That.Matches(x => x.Item1 == _identity.UserId && x.Item2 == _identity.CompanyId), OfferTypeId.SERVICE, settings.UploadServiceDocumentTypeIds, CancellationToken.None)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _offerDocumentService.UploadDocumentAsync(serviceId, DocumentTypeId.ADDITIONAL_DETAILS, file, OfferTypeId.SERVICE, settings.UploadServiceDocumentTypeIds, CancellationToken.None)).MustHaveHappenedOnceExactly(); } #endregion @@ -562,7 +562,7 @@ public async Task ApproveServiceRequestAsync_WithValid_CallsExpected() { // Arrange var appId = Guid.NewGuid(); - var sut = new ServiceReleaseBusinessLogic(_portalRepositories, _offerService, _offerDocumentService, _options); + var sut = new ServiceReleaseBusinessLogic(_portalRepositories, _offerService, _offerDocumentService, _identityService, _options); // Act await sut.ApproveServiceRequestAsync(appId).ConfigureAwait(false); @@ -585,7 +585,7 @@ public async Task GetTechnicalUserProfilesForOffer_ReturnsExpected() // Arrange A.CallTo(() => _offerService.GetTechnicalUserProfilesForOffer(_existingServiceId, OfferTypeId.SERVICE)) .Returns(_fixture.CreateMany(5)); - var sut = new ServiceReleaseBusinessLogic(null!, _offerService, _offerDocumentService, Options.Create(new ServiceSettings())); + var sut = new ServiceReleaseBusinessLogic(null!, _offerService, _offerDocumentService, _identityService, Options.Create(new ServiceSettings())); // Act var result = await sut.GetTechnicalUserProfilesForOffer(_existingServiceId) @@ -604,7 +604,7 @@ public async Task UpdateTechnicalUserProfiles_ReturnsExpected() // Arrange const string clientProfile = "cl"; var data = _fixture.CreateMany(5); - var sut = new ServiceReleaseBusinessLogic(null!, _offerService, _offerDocumentService, Options.Create(new ServiceSettings { TechnicalUserProfileClient = clientProfile })); + var sut = new ServiceReleaseBusinessLogic(null!, _offerService, _offerDocumentService, _identityService, Options.Create(new ServiceSettings { TechnicalUserProfileClient = clientProfile })); // Act await sut diff --git a/tests/marketplace/Services.Service.Tests/Controllers/ServiceReleaseControllerTest.cs b/tests/marketplace/Services.Service.Tests/Controllers/ServiceReleaseControllerTest.cs index 0d3c5bcbbe..c3125ca193 100644 --- a/tests/marketplace/Services.Service.Tests/Controllers/ServiceReleaseControllerTest.cs +++ b/tests/marketplace/Services.Service.Tests/Controllers/ServiceReleaseControllerTest.cs @@ -212,14 +212,14 @@ public async Task UpdateService_ReturnsExpected() //Arrange var serviceId = _fixture.Create(); var data = _fixture.Create(); - A.CallTo(() => _logic.UpdateServiceAsync(A._, A._, _identity.CompanyId)) + A.CallTo(() => _logic.UpdateServiceAsync(A._, A._)) .Returns(Task.CompletedTask); //Act var result = await this._controller.UpdateService(serviceId, data).ConfigureAwait(false); //Assert - A.CallTo(() => _logic.UpdateServiceAsync(serviceId, data, _identity.CompanyId)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _logic.UpdateServiceAsync(serviceId, data)).MustHaveHappenedOnceExactly(); Assert.IsType(result); } @@ -273,8 +273,7 @@ public async Task UpdateServiceDocumentAsync_CallExpected() await this._controller.UpdateServiceDocumentAsync(serviceId, DocumentTypeId.ADDITIONAL_DETAILS, file, CancellationToken.None).ConfigureAwait(false); // Assert - A.CallTo(() => _logic.CreateServiceDocumentAsync(serviceId, - DocumentTypeId.ADDITIONAL_DETAILS, file, A>.That.Matches(x => x.Item1 == _identity.UserId && x.Item2 == _identity.CompanyId), CancellationToken.None)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _logic.CreateServiceDocumentAsync(serviceId, DocumentTypeId.ADDITIONAL_DETAILS, file, CancellationToken.None)).MustHaveHappenedOnceExactly(); } [Fact] diff --git a/tests/notifications/Notifications.Service.Tests/BusinessLogic/NotificationBusinessLogicTests.cs b/tests/notifications/Notifications.Service.Tests/BusinessLogic/NotificationBusinessLogicTests.cs index 21f83bf999..eb621c4c12 100644 --- a/tests/notifications/Notifications.Service.Tests/BusinessLogic/NotificationBusinessLogicTests.cs +++ b/tests/notifications/Notifications.Service.Tests/BusinessLogic/NotificationBusinessLogicTests.cs @@ -51,6 +51,7 @@ public class NotificationBusinessLogicTests private readonly IEnumerable _readNotificationDetails; private readonly IEnumerable _unreadNotificationDetails; private readonly IUserRepository _userRepository; + private readonly IIdentityService _identityService; public NotificationBusinessLogicTests() { @@ -65,6 +66,9 @@ public NotificationBusinessLogicTests() _notificationRepository = A.Fake(); _userRepository = A.Fake(); + _identityService = A.Fake(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity); + _readNotificationDetails = _fixture.Build() .CreateMany(1); _unreadNotificationDetails = _fixture.Build() @@ -81,13 +85,13 @@ public NotificationBusinessLogicTests() public async Task GetNotifications_WithStatus_ReturnsList(bool status) { // Arrange - var sut = new NotificationBusinessLogic(_portalRepositories, Options.Create(new NotificationSettings + var sut = new NotificationBusinessLogic(_portalRepositories, _identityService, Options.Create(new NotificationSettings { MaxPageSize = 15 })); // Act - var result = await sut.GetNotificationsAsync(0, 15, _identity.UserId, new NotificationFilters(status, null, null, false, null, null, Enumerable.Empty(), null)).ConfigureAwait(false); + var result = await sut.GetNotificationsAsync(0, 15, new NotificationFilters(status, null, null, false, null, null, Enumerable.Empty(), null)).ConfigureAwait(false); // Assert var expectedCount = status ? @@ -104,13 +108,13 @@ public async Task GetNotifications_WithStatus_ReturnsList(bool status) public async Task GetNotifications_WithoutStatus_ReturnsList(NotificationSorting sorting) { // Arrange - var sut = new NotificationBusinessLogic(_portalRepositories, Options.Create(new NotificationSettings + var sut = new NotificationBusinessLogic(_portalRepositories, _identityService, Options.Create(new NotificationSettings { MaxPageSize = 15 })); // Act - var result = await sut.GetNotificationsAsync(0, 15, _identity.UserId, new NotificationFilters(null, null, null, false, sorting, null, Enumerable.Empty(), null)).ConfigureAwait(false); + var result = await sut.GetNotificationsAsync(0, 15, new NotificationFilters(null, null, null, false, sorting, null, Enumerable.Empty(), null)).ConfigureAwait(false); // Assert result.Meta.NumberOfElements.Should().Be(_notificationDetails.Count()); @@ -124,13 +128,13 @@ public async Task GetNotifications_WithoutStatus_ReturnsList(NotificationSorting public async Task GetNotifications_SecondPage_ReturnsExpectedNotificationDetailData() { // Arrange - var sut = new NotificationBusinessLogic(_portalRepositories, Options.Create(new NotificationSettings + var sut = new NotificationBusinessLogic(_portalRepositories, _identityService, Options.Create(new NotificationSettings { MaxPageSize = 15 })); // Act - var results = await sut.GetNotificationsAsync(1, 3, _identity.UserId, new NotificationFilters(null, null, null, false, null, null, Enumerable.Empty(), null)).ConfigureAwait(false); + var results = await sut.GetNotificationsAsync(1, 3, new NotificationFilters(null, null, null, false, null, null, Enumerable.Empty(), null)).ConfigureAwait(false); // Assert results.Should().NotBeNull(); @@ -145,12 +149,12 @@ public async Task GetNotifications_SecondPage_ReturnsExpectedNotificationDetailD public async Task GetNotifications_ExceedMaxPageSize_Throws() { // Arrange - var sut = new NotificationBusinessLogic(_portalRepositories, Options.Create(new NotificationSettings + var sut = new NotificationBusinessLogic(_portalRepositories, _identityService, Options.Create(new NotificationSettings { MaxPageSize = 15 })); - var Act = () => sut.GetNotificationsAsync(0, 20, _identity.UserId, new NotificationFilters(null, null, null, false, null, null, Enumerable.Empty(), null)); + var Act = () => sut.GetNotificationsAsync(0, 20, new NotificationFilters(null, null, null, false, null, null, Enumerable.Empty(), null)); // Act & Assert await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -160,12 +164,12 @@ public async Task GetNotifications_ExceedMaxPageSize_Throws() public async Task GetNotifications_NegativePage_Throws() { // Arrange - var sut = new NotificationBusinessLogic(_portalRepositories, Options.Create(new NotificationSettings + var sut = new NotificationBusinessLogic(_portalRepositories, _identityService, Options.Create(new NotificationSettings { MaxPageSize = 15 })); - var Act = () => sut.GetNotificationsAsync(-1, 15, _identity.UserId, new NotificationFilters(null, null, null, false, null, null, Enumerable.Empty(), null)); + var Act = () => sut.GetNotificationsAsync(-1, 15, new NotificationFilters(null, null, null, false, null, null, Enumerable.Empty(), null)); // Act & Assert await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -175,16 +179,17 @@ public async Task GetNotifications_NegativePage_Throws() public async Task GetNotifications_WithFilters_CallsExpected() { // Arrange - var sut = new NotificationBusinessLogic(_portalRepositories, Options.Create(new NotificationSettings + var sut = new NotificationBusinessLogic(_portalRepositories, _identityService, Options.Create(new NotificationSettings { MaxPageSize = 20 })); var userId = Guid.NewGuid(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { UserId = userId }); var filter = _fixture.Create(); // Act - var result = await sut.GetNotificationsAsync(0, 20, userId, filter).ConfigureAwait(false); + var result = await sut.GetNotificationsAsync(0, 20, filter).ConfigureAwait(false); // Assert A.CallTo(() => _notificationRepository.GetAllNotificationDetailsByReceiver(userId, filter.IsRead, filter.TypeId, filter.TopicId, filter.OnlyDueDate, filter.Sorting, filter.DoneState, A>.That.Matches(x => x.Count() == filter.SearchTypeIds.Count()), filter.SearchQuery)) @@ -199,13 +204,13 @@ public async Task GetNotifications_WithFilters_CallsExpected() public async Task GetNotificationDetailDataAsync_WithIdAndUser_ReturnsCorrectResult() { // Arrange - var sut = new NotificationBusinessLogic(_portalRepositories, Options.Create(new NotificationSettings + var sut = new NotificationBusinessLogic(_portalRepositories, _identityService, Options.Create(new NotificationSettings { MaxPageSize = 15 })); // Act - var result = await sut.GetNotificationDetailDataAsync(_identity.UserId, _notificationDetail.Id).ConfigureAwait(false); + var result = await sut.GetNotificationDetailDataAsync(_notificationDetail.Id).ConfigureAwait(false); // Assert var notificationDetailData = _unreadNotificationDetails.First(); @@ -217,13 +222,14 @@ public async Task GetNotificationDetailDataAsync_WithNotMatchingUser_ThrowsForbi { // Arrange var identity = _fixture.Create(); - var sut = new NotificationBusinessLogic(_portalRepositories, Options.Create(new NotificationSettings + A.CallTo(() => _identityService.IdentityData).Returns(identity); + var sut = new NotificationBusinessLogic(_portalRepositories, _identityService, Options.Create(new NotificationSettings { MaxPageSize = 15 })); // Act - async Task Act() => await sut.GetNotificationDetailDataAsync(identity.UserId, _notificationDetail.Id).ConfigureAwait(false); + async Task Act() => await sut.GetNotificationDetailDataAsync(_notificationDetail.Id).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -234,14 +240,14 @@ public async Task GetNotificationDetailDataAsync_WithNotMatchingUser_ThrowsForbi public async Task GetNotificationDetailDataAsync_WithNotMatchingNotificationId_ThrowsNotFoundException() { // Arrange - var sut = new NotificationBusinessLogic(_portalRepositories, Options.Create(new NotificationSettings + var sut = new NotificationBusinessLogic(_portalRepositories, _identityService, Options.Create(new NotificationSettings { MaxPageSize = 15 })); // Act var notificationId = Guid.NewGuid(); - async Task Act() => await sut.GetNotificationDetailDataAsync(_identity.UserId, notificationId).ConfigureAwait(false); + async Task Act() => await sut.GetNotificationDetailDataAsync(notificationId).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -256,13 +262,13 @@ public async Task GetNotificationDetailDataAsync_WithNotMatchingNotificationId_T public async Task GetNotificationCountAsync_WithIdAndUser_ReturnsCorrectResult() { // Arrange - var sut = new NotificationBusinessLogic(_portalRepositories, Options.Create(new NotificationSettings + var sut = new NotificationBusinessLogic(_portalRepositories, _identityService, Options.Create(new NotificationSettings { MaxPageSize = 15 })); // Act - var result = await sut.GetNotificationCountAsync(_identity.UserId, false).ConfigureAwait(false); + var result = await sut.GetNotificationCountAsync(false).ConfigureAwait(false); // Assert result.Should().Be(5); @@ -288,13 +294,13 @@ public async Task GetNotificationCountDetailsAsync() new (false, false, NotificationTopicId.ACTION, 2), }); A.CallTo(() => _notificationRepository.GetCountDetailsForUserAsync(_identity.UserId)).Returns(data.AsAsyncEnumerable()); - var sut = new NotificationBusinessLogic(_portalRepositories, Options.Create(new NotificationSettings + var sut = new NotificationBusinessLogic(_portalRepositories, _identityService, Options.Create(new NotificationSettings { MaxPageSize = 15 })); // Act - var result = await sut.GetNotificationCountDetailsAsync(_identity.UserId).ConfigureAwait(false); + var result = await sut.GetNotificationCountDetailsAsync().ConfigureAwait(false); // Assert result.Read.Should().Be(9); @@ -322,13 +328,13 @@ public async Task SetNotificationStatus_WithMatchingId_ReturnsDetailData(bool is initializers.Invoke(notification); dbupdatedfield.Invoke(notification); }); - var sut = new NotificationBusinessLogic(_portalRepositories, Options.Create(new NotificationSettings + var sut = new NotificationBusinessLogic(_portalRepositories, _identityService, Options.Create(new NotificationSettings { MaxPageSize = 15 })); // Act - await sut.SetNotificationStatusAsync(_identity.UserId, _notificationDetail.Id, isRead).ConfigureAwait(false); + await sut.SetNotificationStatusAsync(_notificationDetail.Id, isRead).ConfigureAwait(false); // Assert A.CallTo(() => _portalRepositories.SaveAsync()).MustHaveHappenedOnceExactly(); @@ -340,14 +346,15 @@ public async Task SetNotificationToRead_WithNotMatchingNotification_NotFoundExce { // Arrange var randomNotificationId = Guid.NewGuid(); - var sut = new NotificationBusinessLogic(_portalRepositories, Options.Create(new NotificationSettings + var sut = new NotificationBusinessLogic(_portalRepositories, _identityService, Options.Create(new NotificationSettings { MaxPageSize = 15 })); var identity = _fixture.Create(); + A.CallTo(() => _identityService.IdentityData).Returns(identity); // Act - async Task Act() => await sut.SetNotificationStatusAsync(identity.UserId, randomNotificationId, true).ConfigureAwait(false); + async Task Act() => await sut.SetNotificationStatusAsync(randomNotificationId, true).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -359,13 +366,14 @@ public async Task SetNotificationToRead_WithNotExistingCompanyUser_ThrowsForbidd { // Arrange var identity = _fixture.Create(); - var sut = new NotificationBusinessLogic(_portalRepositories, Options.Create(new NotificationSettings + A.CallTo(() => _identityService.IdentityData).Returns(identity); + var sut = new NotificationBusinessLogic(_portalRepositories, _identityService, Options.Create(new NotificationSettings { MaxPageSize = 15 })); // Act - async Task Act() => await sut.SetNotificationStatusAsync(identity.UserId, _notificationDetail.Id, true).ConfigureAwait(false); + async Task Act() => await sut.SetNotificationStatusAsync(_notificationDetail.Id, true).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -380,13 +388,13 @@ public async Task SetNotificationToRead_WithNotExistingCompanyUser_ThrowsForbidd public async Task DeleteNotification_WithValidData_ExecutesSuccessfully() { // Arrange - var sut = new NotificationBusinessLogic(_portalRepositories, Options.Create(new NotificationSettings + var sut = new NotificationBusinessLogic(_portalRepositories, _identityService, Options.Create(new NotificationSettings { MaxPageSize = 15 })); // Act - await sut.DeleteNotificationAsync(_identity.UserId, _notificationDetail.Id).ConfigureAwait(false); + await sut.DeleteNotificationAsync(_notificationDetail.Id).ConfigureAwait(false); // Assert A.CallTo(() => _portalRepositories.SaveAsync()).MustHaveHappenedOnceExactly(); @@ -397,13 +405,14 @@ public async Task DeleteNotification_WithNotExistingCompanyUser_ThrowsForbiddenE { // Arrange var identity = _fixture.Create(); - var sut = new NotificationBusinessLogic(_portalRepositories, Options.Create(new NotificationSettings + A.CallTo(() => _identityService.IdentityData).Returns(identity); + var sut = new NotificationBusinessLogic(_portalRepositories, _identityService, Options.Create(new NotificationSettings { MaxPageSize = 15 })); // Act - async Task Act() => await sut.DeleteNotificationAsync(identity.UserId, _notificationDetail.Id).ConfigureAwait(false); + async Task Act() => await sut.DeleteNotificationAsync(_notificationDetail.Id).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -415,13 +424,13 @@ public async Task DeleteNotification_WithNotExistingNotification_ThrowsNotFoundE { // Arrange var randomNotificationId = Guid.NewGuid(); - var sut = new NotificationBusinessLogic(_portalRepositories, Options.Create(new NotificationSettings + var sut = new NotificationBusinessLogic(_portalRepositories, _identityService, Options.Create(new NotificationSettings { MaxPageSize = 15 })); // Act - async Task Act() => await sut.DeleteNotificationAsync(_identity.UserId, randomNotificationId); + async Task Act() => await sut.DeleteNotificationAsync(randomNotificationId); // Assert var ex = await Assert.ThrowsAsync(Act); diff --git a/tests/notifications/Notifications.Service.Tests/Controllers/NotificationControllerTest.cs b/tests/notifications/Notifications.Service.Tests/Controllers/NotificationControllerTest.cs index ad3fea4acb..ee140a014b 100644 --- a/tests/notifications/Notifications.Service.Tests/Controllers/NotificationControllerTest.cs +++ b/tests/notifications/Notifications.Service.Tests/Controllers/NotificationControllerTest.cs @@ -60,14 +60,14 @@ public async Task GetNotifications_ReturnsExpectedCount() var sorting = _fixture.Create(); var doneState = _fixture.Create(); var paginationResponse = new Pagination.Response(new Pagination.Metadata(15, 1, 1, 15), _fixture.CreateMany(5)); - A.CallTo(() => _logic.GetNotificationsAsync(A._, A._, A._, A._)) + A.CallTo(() => _logic.GetNotificationsAsync(A._, A._, A._)) .ReturnsLazily(() => paginationResponse); //Act var result = await this._controller.GetNotifications(isRead: isRead, notificationTypeId: typeId, notificationTopicId: topicId, onlyDueDate: onlyDueDate, sorting: sorting, doneState: doneState, searchTypeIds: Enumerable.Empty()).ConfigureAwait(false); //Assert - A.CallTo(() => _logic.GetNotificationsAsync(0, 15, A._, A.That.Matches(x => x.IsRead == isRead && x.TypeId == typeId && x.TopicId == topicId && x.OnlyDueDate == onlyDueDate && x.Sorting == sorting && x.DoneState == doneState))).MustHaveHappenedOnceExactly(); + A.CallTo(() => _logic.GetNotificationsAsync(0, 15, A.That.Matches(x => x.IsRead == isRead && x.TypeId == typeId && x.TopicId == topicId && x.OnlyDueDate == onlyDueDate && x.Sorting == sorting && x.DoneState == doneState))).MustHaveHappenedOnceExactly(); Assert.IsType>(result); result.Content.Should().HaveCount(5); } @@ -78,14 +78,14 @@ public async Task GetNotification_ReturnsExpectedData() //Arrange var data = _fixture.Create(); var notificationId = _fixture.Create(); - A.CallTo(() => _logic.GetNotificationDetailDataAsync(_identity.UserId, A._)) + A.CallTo(() => _logic.GetNotificationDetailDataAsync(A._)) .ReturnsLazily(() => data); //Act var result = await this._controller.GetNotification(notificationId).ConfigureAwait(false); //Assert - A.CallTo(() => _logic.GetNotificationDetailDataAsync(_identity.UserId, notificationId)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _logic.GetNotificationDetailDataAsync(notificationId)).MustHaveHappenedOnceExactly(); result.Should().Be(data); } @@ -94,14 +94,14 @@ public async Task NotificationCountDetails_ReturnsExpectedData() { //Arrange var data = _fixture.Create(); - A.CallTo(() => _logic.GetNotificationCountDetailsAsync(_identity.UserId)) + A.CallTo(() => _logic.GetNotificationCountDetailsAsync()) .ReturnsLazily(() => data); //Act var result = await this._controller.NotificationCountDetails().ConfigureAwait(false); //Assert - A.CallTo(() => _logic.GetNotificationCountDetailsAsync(_identity.UserId)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _logic.GetNotificationCountDetailsAsync()).MustHaveHappenedOnceExactly(); Assert.IsType(result); result.Should().Be(data); } @@ -111,14 +111,14 @@ public async Task SetNotificationToRead_ReturnsNoContent() { //Arrange var notificationId = Guid.NewGuid(); - A.CallTo(() => _logic.SetNotificationStatusAsync(_identity.UserId, notificationId, A._)) + A.CallTo(() => _logic.SetNotificationStatusAsync(notificationId, A._)) .ReturnsLazily(() => Task.CompletedTask); //Act var result = await this._controller.SetNotificationToRead(notificationId).ConfigureAwait(false); //Assert - A.CallTo(() => _logic.SetNotificationStatusAsync(_identity.UserId, notificationId, true)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _logic.SetNotificationStatusAsync(notificationId, true)).MustHaveHappenedOnceExactly(); Assert.IsType(result); } @@ -127,14 +127,14 @@ public async Task DeleteNotification_ReturnsNoContent() { //Arrange var notificationId = Guid.NewGuid(); - A.CallTo(() => _logic.DeleteNotificationAsync(_identity.UserId, notificationId)) + A.CallTo(() => _logic.DeleteNotificationAsync(notificationId)) .ReturnsLazily(() => Task.CompletedTask); //Act var result = await this._controller.DeleteNotification(notificationId).ConfigureAwait(false); //Assert - A.CallTo(() => _logic.DeleteNotificationAsync(_identity.UserId, notificationId)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _logic.DeleteNotificationAsync(notificationId)).MustHaveHappenedOnceExactly(); Assert.IsType(result); } } diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/ApplicationRepositoryTests.cs b/tests/portalbackend/PortalBackend.DBAccess.Tests/ApplicationRepositoryTests.cs index 2f79a2028f..c12f25c6db 100644 --- a/tests/portalbackend/PortalBackend.DBAccess.Tests/ApplicationRepositoryTests.cs +++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/ApplicationRepositoryTests.cs @@ -18,6 +18,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +using Microsoft.EntityFrameworkCore; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Tests.Setup; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities; @@ -501,6 +502,37 @@ public async Task GetCompanyIdNameForSubmittedApplication_WithValidData_Creates( #endregion + #region AttachAndModifyCompanyApplications + + [Fact] + public async Task AttachAndModifyCompanyApplications() + { + // Arrange + var (sut, context) = await CreateSutWithContext().ConfigureAwait(false); + var companyApplicationData = new (Guid applicationId, Action?, Action)[] { + (Guid.NewGuid(), null, application => application.ApplicationStatusId = CompanyApplicationStatusId.CREATED), + (Guid.NewGuid(), application => application.ApplicationStatusId = CompanyApplicationStatusId.CREATED, application => application.ApplicationStatusId = CompanyApplicationStatusId.SUBMITTED), + (Guid.NewGuid(), application => application.ApplicationStatusId = CompanyApplicationStatusId.CONFIRMED, application => application.ApplicationStatusId = CompanyApplicationStatusId.DECLINED), + (Guid.NewGuid(), application => application.ApplicationStatusId = CompanyApplicationStatusId.CONFIRMED, application => application.ApplicationStatusId = CompanyApplicationStatusId.CONFIRMED) + }; + + // Act + sut.AttachAndModifyCompanyApplications(companyApplicationData); + + // Assert + var changeTracker = context.ChangeTracker; + var changedEntries = changeTracker.Entries().ToList(); + changeTracker.HasChanges().Should().BeTrue(); + changedEntries.Should().HaveCount(4).And.AllSatisfy(x => x.Entity.Should().BeOfType()).And.Satisfy( + x => x.State == EntityState.Modified && ((CompanyApplication)x.Entity).Id == companyApplicationData[0].applicationId && ((CompanyApplication)x.Entity).ApplicationStatusId == CompanyApplicationStatusId.CREATED, + x => x.State == EntityState.Modified && ((CompanyApplication)x.Entity).Id == companyApplicationData[1].applicationId && ((CompanyApplication)x.Entity).ApplicationStatusId == CompanyApplicationStatusId.SUBMITTED, + x => x.State == EntityState.Modified && ((CompanyApplication)x.Entity).Id == companyApplicationData[2].applicationId && ((CompanyApplication)x.Entity).ApplicationStatusId == CompanyApplicationStatusId.DECLINED, + x => x.State == EntityState.Unchanged && ((CompanyApplication)x.Entity).Id == companyApplicationData[3].applicationId && ((CompanyApplication)x.Entity).ApplicationStatusId == CompanyApplicationStatusId.CONFIRMED + ); + } + + #endregion + private async Task<(IApplicationRepository sut, PortalDbContext context)> CreateSutWithContext() { var context = await _dbTestDbFixture.GetPortalDbContext().ConfigureAwait(false); diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/CompanyRepositoryTests.cs b/tests/portalbackend/PortalBackend.DBAccess.Tests/CompanyRepositoryTests.cs index 9178e87b66..874f94c807 100644 --- a/tests/portalbackend/PortalBackend.DBAccess.Tests/CompanyRepositoryTests.cs +++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/CompanyRepositoryTests.cs @@ -684,11 +684,12 @@ public async Task GetOwnCompanAndCompanyUseryIdWithCompanyNameAndUserEmailAsync_ var (sut, _) = await CreateSut().ConfigureAwait(false); // Act - var result = await sut.GetOwnCompanyInformationAsync(new("2dc4249f-b5ca-4d42-bef1-7a7a950a4f87")).ConfigureAwait(false); + var result = await sut.GetOwnCompanyInformationAsync(new("2dc4249f-b5ca-4d42-bef1-7a7a950a4f87"), new Guid("cd436931-8399-4c1d-bd81-7dffb298c7ca")).ConfigureAwait(false); // Assert result.Should().NotBeNull(); result!.OrganizationName.Should().Be("Catena-X"); + result.CompanyUserEmail.Should().Be("inactive-user@mail.com"); } [Fact] @@ -698,7 +699,7 @@ public async Task GetOwnCompanAndCompanyUseryIdWithCompanyNameAndUserEmailAsync_ var (sut, _) = await CreateSut().ConfigureAwait(false); // Act - var result = await sut.GetOwnCompanyInformationAsync(Guid.NewGuid()).ConfigureAwait(false); + var result = await sut.GetOwnCompanyInformationAsync(Guid.NewGuid(), Guid.NewGuid()).ConfigureAwait(false); // Assert result.Should().BeNull(); @@ -902,6 +903,48 @@ public async Task CheckBpnExists_WithValid_ReturnsTrue() #endregion + #region GetAllMemberCompaniesBPN + + [Fact] + public async Task GetAllMemberCompaniesBPN() + { + // Arrange + var bpnIds = new[] { + "BPNL07800HZ01643", + "BPNL00000003AYRE", + "BPNL00000003LLHA", + "BPNL0000000001ON", + "BPNL07800HZ01645" }; + var (sut, _) = await CreateSut().ConfigureAwait(false); + + // Act + var result = await sut.GetAllMemberCompaniesBPNAsync(bpnIds).ToListAsync().ConfigureAwait(false); + + // Assert + result.Should().NotBeNull().And.HaveCount(2).And.Satisfy( + x => x == "BPNL07800HZ01643", x => x == "BPNL00000003AYRE"); + } + + [Fact] + public async Task GetAllMemberCompaniesBPN_withNull_ReturnsExpected() + { + // Arrange + var (sut, _) = await CreateSut().ConfigureAwait(false); + + // Act + var result = await sut.GetAllMemberCompaniesBPNAsync(null).ToListAsync().ConfigureAwait(false); + + // Assert + result.Should().NotBeNull().And.HaveCount(5).And.Satisfy( + x => x == "BPNL07800HZ01643", + x => x == "BPNL00000003AYRE", + x => x == "BPNL00000003CRHK", + x => x == "BPNL00000003CRHL", + x => x == "BPNL00000001TEST"); + } + + #endregion + #region Setup private async Task<(ICompanyRepository, PortalDbContext)> CreateSut() diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/CompanySsiDetailsRepositoryTests.cs b/tests/portalbackend/PortalBackend.DBAccess.Tests/CompanySsiDetailsRepositoryTests.cs index b122f83eb5..bc480d1a10 100644 --- a/tests/portalbackend/PortalBackend.DBAccess.Tests/CompanySsiDetailsRepositoryTests.cs +++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/CompanySsiDetailsRepositoryTests.cs @@ -188,6 +188,25 @@ public async Task CreateSsiDetails_WithValidData_ReturnsExpected() .Which.CompanySsiDetailStatusId.Should().Be(CompanySsiDetailStatusId.PENDING); } + [Fact] + public async Task CreateSsiDetails_WithConstraintCheckFailing_ThrowsException() + { + // Arrange + var (sut, context) = await CreateSutWithContext(); + sut.CreateSsiDetails(new("9f5b9934-4014-4099-91e9-7b1aee696b03"), VerifiedCredentialTypeId.DISMANTLER_CERTIFICATE, new Guid("00000000-0000-0000-0000-000000000001"), CompanySsiDetailStatusId.PENDING, _userId, + ssi => + { + ssi.VerifiedCredentialExternalTypeUseCaseDetailId = new("1268a76a-ca19-4dd8-b932-01f24071d561"); + }); + async Task Act() => await context.SaveChangesAsync().ConfigureAwait(false); + + // Act + var ex = await Assert.ThrowsAsync(Act); + + // Assert + ex.Message.Should().Be("An error occurred while saving the entity changes. See the inner exception for details."); + } + #endregion #region CheckSsiDetailsExistsForCompany diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/ConnectorRepositoryTests.cs b/tests/portalbackend/PortalBackend.DBAccess.Tests/ConnectorRepositoryTests.cs index 70955aa75e..45bea10780 100644 --- a/tests/portalbackend/PortalBackend.DBAccess.Tests/ConnectorRepositoryTests.cs +++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/ConnectorRepositoryTests.cs @@ -499,6 +499,21 @@ public async Task CreateConnectorAssignedSubscriptions_ExecutesExpected() changedEntries.Single().Entity.Should().BeOfType().Which.OfferSubscriptionId.Should().Be("0b2ca541-206d-48ad-bc02-fb61fbcb5552"); } + [Fact] + public async Task CreateConnectorAssignedSubscriptions_WithManaged_ThrowsException() + { + // Arrange + var (sut, context) = await CreateSut().ConfigureAwait(false); + + // Act + sut.CreateConnectorAssignedSubscriptions(new Guid("7e86a0b8-6903-496b-96d1-0ef508206839"), new Guid("0b2ca541-206d-48ad-bc02-fb61fbcb5552")); + async Task Act() => await context.SaveChangesAsync().ConfigureAwait(false); + + // Assert + var ex = await Assert.ThrowsAsync(Act); + ex.Message.Should().Be("An error occurred while saving the entity changes. See the inner exception for details."); + } + #endregion #region DeleteConnector diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/DocumentRepositoryTests.cs b/tests/portalbackend/PortalBackend.DBAccess.Tests/DocumentRepositoryTests.cs index 775be563ca..120a2d0b52 100644 --- a/tests/portalbackend/PortalBackend.DBAccess.Tests/DocumentRepositoryTests.cs +++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/DocumentRepositoryTests.cs @@ -446,6 +446,36 @@ public async Task GetRegistrationDocumentAsync__ReturnsExpectedResult() result.MediaTypeId.Should().Be(MediaTypeId.PDF); } + [Fact] + public async Task GetDocumentDetailsForApplicationUntrackedAsync_ReturnsExpected() + { + // Arrange + var applicationStatusIds = new[]{ + CompanyApplicationStatusId.SUBMITTED, + CompanyApplicationStatusId.CONFIRMED, + CompanyApplicationStatusId.DECLINED + }; + var (sut, _) = await CreateSut().ConfigureAwait(false); + + // Act + var result = await sut.GetDocumentDetailsForApplicationUntrackedAsync( + new Guid("9685f744-9d90-4102-a949-fcd0bb86f954"), + new Guid("41fd2ab8-71cd-4546-9bef-a388d91b2542"), + applicationStatusIds).ConfigureAwait(false); + + // Assert + result.Should().NotBeNull(); + result.DocumentId.Should().Be(new Guid("9685f744-9d90-4102-a949-fcd0bb86f954")); + result.documentTypeId.Should().Be(DocumentTypeId.CX_FRAME_CONTRACT); + result.DocumentStatusId.Should().Be(DocumentStatusId.LOCKED); + result.applicationId.Should().HaveCount(1).And.Satisfy( + x => x == new Guid("6b2d1263-c073-4a48-bfaf-704dc154ca9e") + ); + result.IsQueriedApplicationStatus.Should().BeTrue(); + result.IsSameApplicationUser.Should().BeTrue(); + + } + #region Setup private async Task<(DocumentRepository, PortalDbContext)> CreateSut() diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/IdentityProviderRepositoryTests.cs b/tests/portalbackend/PortalBackend.DBAccess.Tests/IdentityProviderRepositoryTests.cs index aa8faa72b9..e576f6e30b 100644 --- a/tests/portalbackend/PortalBackend.DBAccess.Tests/IdentityProviderRepositoryTests.cs +++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/IdentityProviderRepositoryTests.cs @@ -340,6 +340,57 @@ public async Task GetCompanyNameIdpAliasUntrackedAsync_ReturnsExpectedResult() #endregion + #region GetOwnIdentityProviderWithConnectedCompanies + + [Fact] + public async Task GetOwnIdentityProviderWithConnectedCompanies_WithNotOwned_ReturnsExpected() + { + var sut = await CreateSut().ConfigureAwait(false); + + var result = await sut.GetOwnIdentityProviderWithConnectedCompanies(new Guid("38f56465-ce26-4f25-9745-1791620dc198"), new Guid("3390c2d7-75c1-4169-aa27-6ce00e1f3cdd")).ConfigureAwait(false); + + // Assert + result.Alias.Should().Be("Idp-123"); + result.IsOwnerCompany.Should().BeFalse(); + result.TypeId.Should().Be(IdentityProviderTypeId.MANAGED); + result.ConnectedCompanies.Should().HaveCount(2).And.Satisfy( + x => x.CompanyId == new Guid("0dcd8209-85e2-4073-b130-ac094fb47106") && x.CompanyName == "SAP AG", + x => x.CompanyId == new Guid("3390c2d7-75c1-4169-aa27-6ce00e1f3cdd") && x.CompanyName == "Service Provider"); + } + + [Fact] + public async Task GetOwnIdentityProviderWithConnectedCompanies_WithValid_ReturnsExpected() + { + var sut = await CreateSut().ConfigureAwait(false); + + var result = await sut.GetOwnIdentityProviderWithConnectedCompanies(new Guid("38f56465-ce26-4f25-9745-1791620dc199"), new Guid("2dc4249f-b5ca-4d42-bef1-7a7a950a4f88")).ConfigureAwait(false); + + // Assert + result.Alias.Should().Be("Test-Alias"); + result.IsOwnerCompany.Should().BeTrue(); + result.TypeId.Should().Be(IdentityProviderTypeId.OWN); + result.ConnectedCompanies.Should().ContainSingle().And.Satisfy(x => + x.CompanyId == new Guid("2dc4249f-b5ca-4d42-bef1-7a7a950a4f88") && x.CompanyName == "CX-Test-Access"); + } + + [Fact] + public async Task GetOwnIdentityProviderWithConnectedCompanies_WithMultipleValid_ReturnsExpected() + { + var sut = await CreateSut().ConfigureAwait(false); + + var result = await sut.GetOwnIdentityProviderWithConnectedCompanies(new Guid("38f56465-ce26-4f25-9745-1791620dc198"), new Guid("ac861325-bc54-4583-bcdc-9e9f2a38ff84")).ConfigureAwait(false); + + // Assert + result.Alias.Should().Be("Idp-123"); + result.IsOwnerCompany.Should().BeTrue(); + result.TypeId.Should().Be(IdentityProviderTypeId.MANAGED); + result.ConnectedCompanies.Should().HaveCount(2).And.Satisfy( + x => x.CompanyId == new Guid("0dcd8209-85e2-4073-b130-ac094fb47106") && x.CompanyName == "SAP AG", + x => x.CompanyId == new Guid("3390c2d7-75c1-4169-aa27-6ce00e1f3cdd") && x.CompanyName == "Service Provider"); + } + + #endregion + #region Setup private async Task<(IdentityProviderRepository, PortalDbContext)> CreateSutWithContext() diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/NetworkRepositoryTests.cs b/tests/portalbackend/PortalBackend.DBAccess.Tests/NetworkRepositoryTests.cs index 44d830d9ff..32da103345 100644 --- a/tests/portalbackend/PortalBackend.DBAccess.Tests/NetworkRepositoryTests.cs +++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/NetworkRepositoryTests.cs @@ -162,16 +162,12 @@ public async Task GetSubmitData_WithoutNetworkRegistration_ReturnsExpected() var sut = await CreateSut().ConfigureAwait(false); // Act - var result = await sut.GetSubmitData(new Guid("729e0af2-6723-4a7f-85a1-833d84b39bdf"), new Guid("8b42e6de-7b59-4217-a63c-198e83d93776"), Enumerable.Repeat(new Guid("aabcdfeb-6669-4c74-89f0-19cda090873e"), 1)).ConfigureAwait(false); + var result = await sut.GetSubmitData(new Guid("3390c2d7-75c1-4169-aa27-6ce00e1f3cdd")).ConfigureAwait(false); // Assert - result.Should().NotBe(default); - result.Exists.Should().Be(true); - result.IsUserInRole.Should().Be(false); - result.CompanyRoleAgreementIds.Should().HaveCount(2).And.Satisfy( - x => x.CompanyRoleId == CompanyRoleId.APP_PROVIDER, - x => x.CompanyRoleId == CompanyRoleId.SERVICE_PROVIDER); - result.CompanyApplications.Should().HaveCount(1).And.Satisfy(x => x.CompanyApplicationStatusId == CompanyApplicationStatusId.CREATED); + result.Exists.Should().BeTrue(); + result.CompanyApplications.Should().BeEmpty(); + result.CompanyRoleAgreementIds.Should().Satisfy(x => x.CompanyRoleId == CompanyRoleId.SERVICE_PROVIDER && x.AgreementIds.Count() == 2); result.ProcessId.Should().BeNull(); } @@ -182,12 +178,11 @@ public async Task GetSubmitData_WithValid_ReturnsExpected() var sut = await CreateSut().ConfigureAwait(false); // Act - var result = await sut.GetSubmitData(new Guid("ac861325-bc54-4583-bcdc-9e9f2a38ff84"), new Guid("8b42e6de-7b59-4217-a63c-198e83d93776"), Enumerable.Repeat(new Guid("aabcdfeb-6669-4c74-89f0-19cda090873e"), 1)).ConfigureAwait(false); + var result = await sut.GetSubmitData(new Guid("ac861325-bc54-4583-bcdc-9e9f2a38ff84")).ConfigureAwait(false); // Assert result.Should().NotBe(default); - result.Exists.Should().Be(true); - result.IsUserInRole.Should().Be(true); + result.Exists.Should().BeTrue(); result.CompanyRoleAgreementIds.Should().HaveCount(2).And.Satisfy( x => x.CompanyRoleId == CompanyRoleId.ACTIVE_PARTICIPANT, x => x.CompanyRoleId == CompanyRoleId.APP_PROVIDER); diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/OfferRepositoryTests.cs b/tests/portalbackend/PortalBackend.DBAccess.Tests/OfferRepositoryTests.cs index 869dbb200d..d979a3b101 100644 --- a/tests/portalbackend/PortalBackend.DBAccess.Tests/OfferRepositoryTests.cs +++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/OfferRepositoryTests.cs @@ -171,6 +171,7 @@ public async Task GetOfferDetailsByIdAsync_ReturnsExpectedResult() documentTypeId.Should().NotContain(DocumentTypeId.APP_LEADIMAGE); documentTypeId.Should().NotContain(DocumentTypeId.APP_IMAGE); offerDetail.TechnicalUserProfile.Should().BeEmpty(); + offerDetail.IsSubscribed.Should().Be(OfferSubscriptionStatusId.PENDING); } #endregion @@ -1441,6 +1442,48 @@ public async Task GetServiceAccountProfileDataForSubscription_WithServiceAccount #endregion + #region GetActiveOfferDocumentTypeData + + [Fact] + public async Task GetActiveOfferDocumentTypeDataAsync_ReturnsExpectedResult() + { + // Arrange + var activeDocumentTypes = new[]{ + DocumentTypeId.APP_IMAGE, + DocumentTypeId.APP_TECHNICAL_INFORMATION, + DocumentTypeId.APP_CONTRACT, + DocumentTypeId.ADDITIONAL_DETAILS + }; + var sut = await CreateSut().ConfigureAwait(false); + + // Act + var result = await sut.GetActiveOfferDocumentTypeDataOrderedAsync( + new("ac1cf001-7fbc-1f2f-817f-bce0572c0007"), + new("2dc4249f-b5ca-4d42-bef1-7a7a950a4f87"), + OfferTypeId.APP, activeDocumentTypes).ToListAsync().ConfigureAwait(false); + + // Assert + result.Should().NotBeNull() + .And.BeInAscendingOrder(x => x.DocumentTypeId) + .And.HaveCount(4) + .And.Satisfy( + x => x.DocumentId == new Guid("e020787d-1e04-4c0b-9c06-bd1cd44724b2") && + x.DocumentName == "Default_App_Image.png" && + x.DocumentTypeId == DocumentTypeId.APP_IMAGE, + x => x.DocumentId == new Guid("0d68c68c-d689-474c-a3be-8493f99feab2") && + x.DocumentName == "AdditionalServiceDetails.pdf" && + x.DocumentTypeId == DocumentTypeId.ADDITIONAL_DETAILS, + x => x.DocumentId == new Guid("aaf53459-c36b-408e-a805-0b406ce9751e") && + x.DocumentName == "AdditionalServiceDetails2.pdf" && + x.DocumentTypeId == DocumentTypeId.ADDITIONAL_DETAILS, + x => x.DocumentId == new Guid("d9926bd9-bce0-4605-a083-7066ffe5147c") && + x.DocumentName == "AdditionalTechnicalInfo.pdf" && + x.DocumentTypeId == DocumentTypeId.APP_TECHNICAL_INFORMATION + ); + } + + #endregion + #region Setup private async Task CreateSut() diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/OfferSubscriptionRepositoryTest.cs b/tests/portalbackend/PortalBackend.DBAccess.Tests/OfferSubscriptionRepositoryTest.cs index c685cd8cc4..67bc891f30 100644 --- a/tests/portalbackend/PortalBackend.DBAccess.Tests/OfferSubscriptionRepositoryTest.cs +++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/OfferSubscriptionRepositoryTest.cs @@ -136,19 +136,19 @@ public async Task GetAllBusinessAppDataForUserIdAsync_WithValidUser_ReturnsExpec #region GetOwnCompanyProvidedOfferSubscriptionStatusesUntracked [Theory] - [InlineData(SubscriptionStatusSorting.OfferIdAsc, null, OfferTypeId.SERVICE, new[] { OfferSubscriptionStatusId.ACTIVE }, 2, true)] - [InlineData(SubscriptionStatusSorting.OfferIdAsc, null, OfferTypeId.SERVICE, new OfferSubscriptionStatusId[] { }, 0, false)] - [InlineData(SubscriptionStatusSorting.OfferIdDesc, null, OfferTypeId.SERVICE, new[] { OfferSubscriptionStatusId.ACTIVE }, 2, false)] - [InlineData(SubscriptionStatusSorting.CompanyNameAsc, null, OfferTypeId.SERVICE, new[] { OfferSubscriptionStatusId.ACTIVE }, 2, true)] - [InlineData(SubscriptionStatusSorting.CompanyNameDesc, null, OfferTypeId.SERVICE, new[] { OfferSubscriptionStatusId.ACTIVE }, 2, true)] - [InlineData(SubscriptionStatusSorting.OfferIdAsc, "a16e73b9-5277-4b69-9f8d-3b227495dfea", OfferTypeId.SERVICE, new[] { OfferSubscriptionStatusId.ACTIVE }, 1, false)] - [InlineData(SubscriptionStatusSorting.OfferIdAsc, "a16e73b9-5277-4b69-9f8d-3b227495dfae", OfferTypeId.SERVICE, new[] { OfferSubscriptionStatusId.ACTIVE }, 1, true)] - [InlineData(SubscriptionStatusSorting.OfferIdAsc, "deadbeef-dead-beef-dead-beefdeadbeef", OfferTypeId.SERVICE, new[] { OfferSubscriptionStatusId.ACTIVE }, 0, false)] - [InlineData(SubscriptionStatusSorting.OfferIdAsc, null, OfferTypeId.APP, new[] { OfferSubscriptionStatusId.ACTIVE }, 1, false)] - [InlineData(SubscriptionStatusSorting.OfferIdAsc, null, OfferTypeId.APP, new[] { OfferSubscriptionStatusId.INACTIVE }, 1, false)] - [InlineData(SubscriptionStatusSorting.OfferIdAsc, null, OfferTypeId.APP, new[] { OfferSubscriptionStatusId.PENDING }, 1, false)] - [InlineData(SubscriptionStatusSorting.OfferIdAsc, null, OfferTypeId.APP, new[] { OfferSubscriptionStatusId.PENDING, OfferSubscriptionStatusId.ACTIVE }, 2, false)] - public async Task GetOwnCompanyProvidedOfferSubscriptionStatusesUntrackedAsync_ReturnsExpectedNotificationDetailData(SubscriptionStatusSorting sorting, string? offerIdTxt, OfferTypeId offerTypeId, IEnumerable offerSubscriptionStatusIds, int count, bool technicalUser) + [InlineData(SubscriptionStatusSorting.OfferIdAsc, null, OfferTypeId.SERVICE, new[] { OfferSubscriptionStatusId.ACTIVE }, 2, true, ProcessStepTypeId.SINGLE_INSTANCE_SUBSCRIPTION_DETAILS_CREATION)] + [InlineData(SubscriptionStatusSorting.OfferIdAsc, null, OfferTypeId.SERVICE, new OfferSubscriptionStatusId[] { }, 0, false, null)] + [InlineData(SubscriptionStatusSorting.OfferIdDesc, null, OfferTypeId.SERVICE, new[] { OfferSubscriptionStatusId.ACTIVE }, 2, false, ProcessStepTypeId.ACTIVATE_SUBSCRIPTION)] + [InlineData(SubscriptionStatusSorting.CompanyNameAsc, null, OfferTypeId.SERVICE, new[] { OfferSubscriptionStatusId.ACTIVE }, 2, true, ProcessStepTypeId.SINGLE_INSTANCE_SUBSCRIPTION_DETAILS_CREATION)] + [InlineData(SubscriptionStatusSorting.CompanyNameDesc, null, OfferTypeId.SERVICE, new[] { OfferSubscriptionStatusId.ACTIVE }, 2, true, ProcessStepTypeId.SINGLE_INSTANCE_SUBSCRIPTION_DETAILS_CREATION)] + [InlineData(SubscriptionStatusSorting.OfferIdAsc, "a16e73b9-5277-4b69-9f8d-3b227495dfea", OfferTypeId.SERVICE, new[] { OfferSubscriptionStatusId.ACTIVE }, 1, false, ProcessStepTypeId.ACTIVATE_SUBSCRIPTION)] + [InlineData(SubscriptionStatusSorting.OfferIdAsc, "a16e73b9-5277-4b69-9f8d-3b227495dfae", OfferTypeId.SERVICE, new[] { OfferSubscriptionStatusId.ACTIVE }, 1, true, ProcessStepTypeId.SINGLE_INSTANCE_SUBSCRIPTION_DETAILS_CREATION)] + [InlineData(SubscriptionStatusSorting.OfferIdAsc, "deadbeef-dead-beef-dead-beefdeadbeef", OfferTypeId.SERVICE, new[] { OfferSubscriptionStatusId.ACTIVE }, 0, false, null)] + [InlineData(SubscriptionStatusSorting.OfferIdAsc, null, OfferTypeId.APP, new[] { OfferSubscriptionStatusId.ACTIVE }, 1, false, ProcessStepTypeId.RETRIGGER_PROVIDER)] + [InlineData(SubscriptionStatusSorting.OfferIdAsc, null, OfferTypeId.APP, new[] { OfferSubscriptionStatusId.INACTIVE }, 1, false, ProcessStepTypeId.START_AUTOSETUP)] + [InlineData(SubscriptionStatusSorting.OfferIdAsc, null, OfferTypeId.APP, new[] { OfferSubscriptionStatusId.PENDING }, 1, false, ProcessStepTypeId.TRIGGER_PROVIDER_CALLBACK)] + [InlineData(SubscriptionStatusSorting.OfferIdAsc, null, OfferTypeId.APP, new[] { OfferSubscriptionStatusId.PENDING, OfferSubscriptionStatusId.ACTIVE }, 2, false, ProcessStepTypeId.RETRIGGER_PROVIDER)] + public async Task GetOwnCompanyProvidedOfferSubscriptionStatusesUntrackedAsync_ReturnsExpectedNotificationDetailData(SubscriptionStatusSorting sorting, string? offerIdTxt, OfferTypeId offerTypeId, IEnumerable offerSubscriptionStatusIds, int count, bool technicalUser, ProcessStepTypeId? processStepTypeId) { // Arrange Guid? offerId = offerIdTxt == null ? null : new Guid(offerIdTxt); @@ -165,6 +165,7 @@ public async Task GetOwnCompanyProvidedOfferSubscriptionStatusesUntrackedAsync_R results.Data.Should().HaveCount(count); results.Data.Should().AllBeOfType().Which.First().CompanySubscriptionStatuses.Should().HaveCount(1); results.Data.Should().AllBeOfType().Which.First().CompanySubscriptionStatuses.Should().Match(x => x.Count() == 1 && x.First().TechnicalUser == technicalUser); + results.Data.Should().AllBeOfType().Which.First().ProcessStepTypeId.Should().Match(x => x == processStepTypeId); } else { @@ -297,7 +298,8 @@ public async Task GetAppSubscriptionDetailForProviderAsync_ReturnsExpected() x.Contact.SequenceEqual(new[] { "tobeadded@cx.com" }) && x.OfferSubscriptionStatus == OfferSubscriptionStatusId.ACTIVE && x.TenantUrl == "https://ec-qas.d13fe27.kyma.ondemand.com" && - x.AppInstanceId == "https://catenax-int-dismantler-s66pftcc.authentication.eu10.hana.ondemand.com"); + x.AppInstanceId == "https://catenax-int-dismantler-s66pftcc.authentication.eu10.hana.ondemand.com" && + x.ProcessStepTypeId == ProcessStepTypeId.ACTIVATE_SUBSCRIPTION); } [Fact] @@ -1105,6 +1107,30 @@ public async Task CheckOfferSubscriptionForProvider_WithoutProvidingCompany_Retu result.Should().BeFalse(); } + #endregion + #region Create OfferSubscription + + [Fact] + public async Task CreateOfferSubscription_ReturnsExpectedResult() + { + // Arrange + var (sut, context) = await CreateSut().ConfigureAwait(false); + + // Act + var results = sut.CreateOfferSubscription(new Guid("ac1cf001-7fbc-1f2f-817f-bce0572c0007"), + new Guid("2dc4249f-b5ca-4d42-bef1-7a7a950a4f87"), OfferSubscriptionStatusId.PENDING, default); + + // Assert + var changeTracker = context.ChangeTracker; + var changedEntries = changeTracker.Entries().ToList(); + results.CompanyId.Should().Be(new Guid("2dc4249f-b5ca-4d42-bef1-7a7a950a4f87")); + changeTracker.HasChanges().Should().BeTrue(); + changedEntries.Should().NotBeEmpty(); + changedEntries.Should().HaveCount(1); + changedEntries.Single().State.Should().Be(EntityState.Added); + changedEntries.Single().Entity.Should().BeOfType().Which.CompanyId.Should().Be(new Guid("2dc4249f-b5ca-4d42-bef1-7a7a950a4f87")); + } + #endregion #region Setup diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/company_service_accounts.test.json b/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/company_service_accounts.test.json index c7ce894670..781ab3aebb 100644 --- a/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/company_service_accounts.test.json +++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/company_service_accounts.test.json @@ -41,7 +41,6 @@ "company_id": "41fd2ab8-71cd-4546-9bef-a388d91b2543", "client_client_id": "sa-x-2" }, - { "id": "cd436931-8399-4c1d-bd81-7dffb298c7ca", "name": "test-user-service-accounts", @@ -50,6 +49,14 @@ "offer_subscription_id": null, "company_id": "2dc4249f-b5ca-4d42-bef1-7a7a950a4f8", "client_client_id": "sa-x-3" + }, + { + "id": "38c92162-6328-40ce-80f3-22e3f3e9b94d", + "name": "sa-inactive", + "description": "inactive service account", + "company_service_account_type_id": 1, + "offer_subscription_id": null, + "company_id": "729e0af2-6723-4a7f-85a1-833d84b39bdf", + "client_client_id": "sa-x-inactive" } - ] diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/documents.test.json b/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/documents.test.json index 46b308638c..ff1c00bfdb 100644 --- a/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/documents.test.json +++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/documents.test.json @@ -10,6 +10,17 @@ "document_content": "iVBORw0KGgoAAAANSUhEUgAAAP4AAAD6CAYAAACBB/pHAAAAAXNSR0IArs4c6QAAAHhlWElmTU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUAAAABAAAARgEoAAMAAAABAAIAAIdpAAQAAAABAAAATgAAAAAAAACQAAAAAQAAAJAAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAAP6gAwAEAAAAAQAAAPoAAAAADPFyXQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAJdlJREFUeAHt3QmXJEXVBuBCcd8QFQUFGhEZYAB15P//ABQBAREYHXXEBfd996sn8dZX9FR3V2VFZEZU3jinTu2ZkW/c925xI/Ku/67bKlsikAgsBoG71u19i7navNBEIBHYIJDE30CRLxKB5SCQxF/OWOeVJgIbBJL4GyjyRSKwHASS+MsZ67zSRGCDQBJ/A0W+SASWg0ASfzljnVeaCGwQSOJvoMgXicByEEjiL2es80oTgQ0CSfwNFPkiEVgOAkn85Yx1XmkisEEgib+BIl8kAstBIIm/nLHOK00ENggk8TdQ5ItEYDkIJPGXM9Z5pYnABoEk/gaKfJEILAeBJP5yxjqvNBHYIJDE30CRLxKB5SCQxF/OWOeVJgIbBJL4GyjyRSKwHASS+MsZ67zSRGCDQBJ/A0W+SASWg0ASfzljnVeaCGwQSOJvoMgXicByELh7OZfa15X+85//XP3tb39b/fGPf1z94x//WN1zzz2rj33sY6v3v//9q/e9L/V1X6PZXm+T+I2NyX/+85+B6L/4xS9Wt27dWv3lL39ZudnR3XffvXr44YdXZ2dnqw996EON9Tq70xsCSfyGRuzf//73YOER/uc///nqX//612p9t6OhhzyAH/7wh6sPf/jDgwJoqNvZlQ4RSOI3MGgsOnce2X/84x8P5PdZkD66SDH85je/WT3wwAOrD3zgA/FxPicCByOQxD8YsrJ/4Npz53/wgx+suPcUwGUN+f0nWyJwDAJJ/GPQO+K/LDpX/re//e3qzTffXP3+978fYvmrDnneC7jq9/l9IrALgST+LlQqf8Zi//nPfx7c+p/+9KeDAqAIsiUCUyGQxJ8K6fV5kFuSTpz+ox/9aHj2WZJ+wkHIUw0IJPEnEgTkNi/PwiO919kSgbkQSOJXRh7hufasvIy9BF5a+Mqg5+GvRCCJfyVE43+A4H/9619XP/vZz1a3b99e/elPfxp/sPxnIlAQgSR+QTDjUCy8h3JbxTjvvPPOENvH9/mcCMyNQBK/8Aiw8ubaWXmVdmnlCwOchyuCQBK/CIzvHoSVV4xz8+bNTcltwcPnoRKBYggk8QtBifS/+93vVm+99dbqV7/6VSbwCuGah6mDQBK/AK7ce/H8G2+8sfr1r39d4Ih5iESgLgK5sPtIfJHenDz33pRdtkSgBwSS+EeMEtJrinKsrIv3Rxwy/5oITIJAEv9ImGXtTdkl6Y8EMv8+KQJJ/CPgltBTfqv+Plsi0BMCSfwjRssKO8tq09ofAWL+dRYEkvhHwM7NV5KbLRHoDYEk/sgRY+VZfJtppMUfCWL+bTYEkvgjoVeWy9on6UcCmH+bFYEk/kj4EZ+1z5YI9IhAEv+IUcv9744AL/86KwJJ/Fnhz5MnAvMgkMSfB/c8ayIwKwK5SGdW+PPkxyBwPrGaodf+aCbx98cqfzkjAkiuUtIjXutOkB/ptx9uLOoGo9l2I5DE341LftoAAlY9mjL9+9//vnm405ASaQ8zK4gflt6NRd1azLMbi24/3HPQ+/htA5c3axeS+LPCnyeHAPKG5UZ2y5uVQtvjwI5GHgjP2gfZ4z/xv21r73XcThzhPdxi/OMf//jq05/+9Oree+9dfeQjH3mP0liaQkjiJ/dmQyBIi9CI7v6Bv/zlLwcrHxY9FMNVnYxjxe9i4RSlEaTm/lMCH/zgB1ef/exnV1/+8pdXn/nMZwYl4f/xuzjGKT8n8U95dBu9NkRX/BR3CHbvQNuVIR4CnifxsZcRx+MthAfhXoUUDet/7dq1QREIBYQJFMSptyT+yBEmTAQ42/4IwIsl/sMf/jDcWMQNRmJ/wiD9/kcb98tQAvHMw3CTEx7A2dnZ6nOf+9zqk5/85JAPOGUFkMQfIT+E1956rEe2/RBgbbnzb7/99rCHgY1JKQKEn9PFjvMbT7mFe+65Z/XAAw+sHnzwwSEM4AGcYjvNq6o4UtxTLqJ983NJ7tVAs6wUpHsMsPAIT3EG4a4+wjS/COWjf5KKtlKjAB599NHVpz71qWk6MeFZkvh7gE14PcSFdtIlHLlA52rgYASrl156aXM3ITgGya4+wjy/CO9ESCIUePLJJwclYKag9b7vi1gS/wqkCCorTwDsmZ/u/RWArb/mwsPM/QJfeOGFLu8MbNwpLuPOA5AAZP3NCrTmrVw9Inf+Iol/JyabT2h+g25fPa6999kuRwBZxMqUJPf+FDAT0vFaeAAUgDxA71WBSfwL5FghiWwvq8XFZwGyXYwAfGD2k5/8ZCC9ZNkpYcaLocwYgieeeGJw/VUJ9tqS+FsjF4JqLz3WCvG5rNkuRiAwY+W///3vD4qSAjjFxsUnE1FC/Mgjjwzz/j3G/Un8/0koATaAbo4ha4/8tHy2ixGAGYxk67/73e8OrvCpY0ZGeIBcf2HNV77ylWF9QG/kT+Kv5ZqwiuMIMNfedFNYsovFftnfwMxmo6+//vpw+7ClYUZeXn755SHWZ/mVAffUFk185I5klASeuLR1ixWLT+YSMpjFLIepTUlPny1RUcLhW9/61lDii/w9TfctlvgEldZWSSYh1cs0nXryuTLKYeXlPyLR1ZuLW1phMhwsv/Les3XJ71xjc+h1LZL4BJh1v7W+553nXqacCNdHP/rR2RaRyH+w8ua2o/ruUIE7td9TfEKeV155ZZjjV+3XgzJcFPHDTRXHh5XvyUUVRyL+lA0+sthW0IWVn/L8vZxLwu+1114bxsc8f+vkXwTxCS8rrwBDLG9KhovWUyNIVo1NVTcOLw/TdK+++upQu87KZ7sYAXJFQT777LPD6r6Lfzn/NydPfKQnsLEqjFvWk5UnIvprldj9998/SfYY4Vl5XpGsfRYw7UdUuMl/2Nyj9Xj/pIkvdjcfz8pbbdWrxRLbcx8///nP7yeBR/wKZuG2iukpgGz7I6B46Xvf+95Afh5aq2v6T5b4tK9NHm7evDkIsvc9NtZeXB+FIjWvIaw8wbWqDmatx6o18RhzbHgJj3hKN27cSOKPAXHsf8TvXHuk72Wa7vy1EiCkl9CzN5xNIms05/CQ/xCfclWj5DZJPx5xxWAy/A899ND4g1T858lZfEQHOve+twTe+XFGeoUhX/ziF6tZjlCSrHxPU5vnsWrtPeVpFkS8z2NrTYmeDPFZLQU5rJZqsl5dewIiLlSow1rYAqrG9k+R/7AuAWZh5VsjUM/9EWryPK3jT+JXGknxKQ3b+7r5SOSJ6VmL0gJDQbLypp7MOyvGoQRKn6fSMHd1WDKpSOxLX/rSsI9/S53v3uITZDXTSE+7EuIeG+Kx8tz6WPRRmozhFYWVN+Phs9Ln6RH/Wn22wahkX2sVfd0TPyy9Oede3Xv13Qpzzta13vfdd1+Vem9Wnusp22yazvskfC26v3tcSjVmSkzF1gjZxl5B18Q3L8/SK8HtjfRBOru4fOELXxhI7xZP8fnYAT3/v7DysvVmOUzTaaXPc/68td7r97aX4rV2/nri81r92Pe4+iGcgru9+1tp3RKfS0+YWa9e3XtWnlsfVv688B4rJJQhgbNJhtxH77sJBT5mOyhJ2XL3wNMkJ83oCF9cZyiIYzEs8X8FUWZMauRsxvavS+ITaIJs2q430hNIVp7rd7Z27T/xiU8MYxdCPXYgt//HyiACjKwaM0ffm0e0fT0SnjBDdrGy0mWk5zrHMlihiwfSv/POO0O5McJ5P/e1k1F9evjhh4cVfNvXNtfr7ohPqGOxjfipp4bc7tpqio4QhNCWvAZCxuqZopO1h1dJpVKyr/scK/Ifipi++tWvXhgnS4xGcxssv5X3sQ+gBNuc5doUl1kU60Rsz91C64r4hBjZufi0eU+NdSKQCO9GjTXICJtYM8/CaDXOMxXurDol+dhjjw2YHXJeeAujxNVmMeQ35lygZWzILHe/hdYd8Qk27UkJ9NAQj4tqLpebWkvjs2oSncIfAt5rM64sJMKy2nDbtuaHXpdQyp1wjIFch+2x55AdnphZFcqoBWXcDfHFaTQma996XB8DS4BZd4PtubRrT4DFtRShNfMEq3VsLiMu3CTuzta5D6SX/CyBmfyAKkjH/853vjOLYiS/Eq3GLOTjMixqf9cN8cVotn3qJTNN2Lj1hJgwl24ESALPvDxcest3nMeDkpT/eOqpp6pgZjzkCeQ/JDwpzCmb8TLrwBuLhO6U5z9/ri6IDzQuPnfW65ab2JIAu9tKrXiOEuT92OQRLq1jctl4sX6R/3jmmWeGqc3Lfn/sd26BZWpN4m/K5jopG6GGsGNuq98F8YHVeg2+gRSLKsZh6Q1u6YbgLIY4Xta+twTneTxYeZtVwMtClhqYnT8ny//0008P02tTL0xC/FbyL80TX8yK9MjfWkN2ZCTA4lFxpPl5wlWyOYeHWD7WJBDaua3G2GvUb1aekhTLT1nO6tyUzdk6BLMUeSoMnQfxrSA1llOd96Ixap74gDI1NXcRxi4ADaDkU8zLc/FrDKjzRCzPYlCGNc6z6xprfCbnEbF8Lcwu6zfFTOlIFE+ZGyHDzmc8525NEx9ArFysIpsbrO3zs/Km5sSMpp5YsJJkdO0ExbW/+OKLw8pDFqMFodnGYd/XsKEkJbaee+65oaahRMZ+3/Nv/05fWH2hxdSeE0MmRzPXtQcOTRNfFhTxW5qiIjRILnGnsIQAlW7IzTJY3OHmjJZ1llQqpft71fH0Xf5DKGTr6aivv+p/Nb/naXiYAp2qwaEVz7VZ4gOIwMdqsqkG57LzGDjCoqjEuvkaxTiu2zVzQ1WcsRA9k56SVMMgeSeJV2Nq87Ixu+w7yojlnZKMrYxls8TnDrH2BqUFsPSBlTcXXKMYh4C6Zhl75aUskfctXPtl5LnsO4pR8VJsFio8aqXBVayvT1MSv5Xrb5b4pqpYvrkFP86v3JYAi1HjsxKDyK33kLSzoMQmoax8Kwrv0GuEjYdZDgk8K+kogJKYHdqnXb/XH8RvrV+7+lrjs2aJz+K1UKWHlLL2CnJqJPAcX2GS2y2L6b3vuSGSMMie8pJnLVn587gulfRwaI74BF/2GhnmtnqElsUy11ya9K6NZVdBJoE35bTSeQKUeC9WtprOJqGPP/548VoGfYSZRG/IhTFpWbGUwLXWMZojPi0sqYcUczYCFTF96SSe2J11l8C7td6FlSD33CTJFOFI4El81rCkvD9ywRNkGCgaNxmx1Nn5sx2GQHPERwLx/ZyJLYLLeonpS07X8WbMGyN87H/Xq2sPI32X82DlZexLYhVi7ByqNu2rKNlrijcsvvshwrPFfeuj/60+N0d8hEf8OQnBhYyltCUHjgA///zzg9Xq3bVHPvPysRipdJly4M7CW5dg16Wo5wj3nhdgFkTilaLOtj8CzREfIWS45yI+S8Z9lNAr0VwHgZWttxbc9fXq2sPGA8nF8R7c7CBiCbwcA2bceaRWy8AY7JIHnyE/TJP4h6HfJPG5b3M18byKPAJ+bEN4Vt40Hff+IgE+9jxT/B8e4mq360b4s/UiF+9LN4SHGbwsztqn7VIK+/xvyb9pivgGUG36XBaRcIvrS5SUskIEF+lbXWR0iOBTiLwgpEf+Eopx+/zGnsKHmZkOcuAcSeptlMq9bor4CE/bzzXYBJqbf6wlO5X974gZ8kXGXixdQinuEl+Yce0pyajfmEsOdvXv1D5rjvhzTeMhu6WaY6fuQkjtiGNrJ1NPc85MlBBUsfzZ2qVn5Uvtf7fdL5h5yH8g/Zy5ne1+LeF1c8QPbT81+JJD5u3HWnveCuFVjBNeS2l3eCpM9BseSm5NlZUuXnIdCM+dN62ppkFsH8pzqutc8nmaIr4YjwBM3WSllZeOtfaSeOaYkd60U8/N6jnhjv3vKMIaGXuekGk6CTx4heXvGbfe+t4U8eea6mLlxfdj56LVHdgso2fSI7hiHPULZjVqxPK8IgU4knduaT7n7E1vRC3d3yT+GlFWTtXZGOtGmO3dJinVs2tvYQ3Cy3Nw7Us3nhyMxPPyH3DrFa/S2MxxvPIjfMRVzOXysW422BjTTD9J6PUoxPAW3ojlWXpxfY3rYNm59dtWvsZ5xozfUv+zeOITQMQf49pKRKosmyshOVZoXTPvxl6BtsISy48Ncy7rg9yHPRVgZC97Vj5bGwg0RXyWYWrhQIKxq7sIdW8CHYouinHGhjgXiW9k5ilDnhBLL3cTn1/0v/x8WgSaIv60l/5ucYrE3tg6b9N25p57aax87Ixj+WyN/e8obsnOW+vlxqbpWP1s7SGwaOKzQsgwJplFoGXxp/ZQxoiQ66TcWHnbgSM/y1+6sfJyHhJ45ujTypdGuNzxFk18MI519WWp56oyPGT4XZ8NKxC+1i63lB/vB+ERf45ajEMwyd82uPXW1INyjMWXk2jZqknYmaZzf3jkH1uVeNmYIDmyc+2jYvGy3+d3bSCQFn+ky8vKtezmc+ftjGO1Ya0189x5yTtVi6rxsvWDwOKJ389QXd1Tbj0rrwjHwhqr6nzmUarxcOQ3FOOw8hJ5FGDLnk+paz+l4yTxT2g0JfBYeRV4Y2cqLoMDuU3NWYwknu+tfuGya1vad0n8ExhxsbuFNWJ5a+blLUo3Vt3CGoRn7dPCl0Z42uMl8afFu/jZWHZLZ8Xy4voazcIaxTge6hZKhg41+pvHvBqBJP7VGDX3i4jbldyapmPlS5fcsuisvJ1xJPAsrIlinLT2zYnEwR1K4h8M2fx/UHFnUY07/JQuuXV1iG2aLkpu1SucItlbnpWpLWVJ/NoIFzy+WB7RWXnEH1NxeFV3kIE7b2GN+XnvWyf9mJyGa1KHEV7MVbic2vdJ/E5GlJVXjIP0Enk1moy9BB7Sm6ZrPZbXP6Qfs3MS4qfFryFFecwiCBBuuwOZpjtbb3w5ZvnwVR1BAkS3M47bUpmma530cU2Sm2MXGyk6Wir50+KHBDX4zJWP5bNKbksn8OKSEd7cvEq8nohAYUWRUlzLvs+UWywX7kXJ7Xtt+/wuib8PShP+hhB6sOyq70zTcWXHxLGXdTti3Lfeemuw8lFy6/NeGktvZuPQ5hpNUfawyOrQa9v390n8fZGa6HcIzrW/cePGUHpb47QSWjYRsVdg7HJb4zw1j4m8ch42CB1jsZGexR/z37HX1ZJSTeKPHcXC/yOA9v2zdNYdaGvF8iydbD33vmeLBytu/piZDYrPSkJZ/amb/k6pbC66viT+RchM+LlpOgtruPV2xqkRyxN2GXuEt11Yz2vmkUfR0thKRWEN5ccCT01C4ckYZVVaHJP4pRE98HhIrhAnSm5rxPJc2tgkg8VvyeU8BC4khY+4fqyCdO3qFCwlnpL0zovw8jVTnvcifJP4FyEzwed2t/36178+CDIFUFogCBuX9o033hisPKvfM+kNidkN24GP3SDVrMXt27eH/QNKK9mrRMb5xk49XnXsQ79P4h+K2JG/N/g0v2k6t6kyD116ZxzkNl2lvt5tumNhTc+kh5mY/vr164PVH6skxfX2EZia9MSGch+bjDxS7O74exL/DkjqfUDYxKVW03mMtVqX9ZBFY+XV2ZubZ+W1XklPKUbSk3t/LGHdpJMinLrBn/KqsU/CmGtJ4o9BbcR/kNz0E8KzXMcK8K4usPKSVkhvuq5Xsse1sZCSnnDj4h+LWVQnhjKM80z1zM13c9ax3krJfibxj0BzH2L5DaFVjMNi0fg1Bp6VV2Mvcx8VaUdc2qx/hRmXWMLTugRK81jMzGLAZ64bm4a3VzqsGztQSfyRyBlIFumiRlD9hsUSyyvK4eodK8Dnz8d6WTP/2muvDdVoXP19FNL547TwHjYepuqsPuTiw7AEZqYw7Ssw1zQmwo+dfqwxNkn8kahy2yJRc55oBNW0DYv19NNPV8nkOifX3jTdnAI9Er47/obgMFXA9NBDDxXFTKHS66+/PsT258fqjo5U+oDSN4tTQomV6GISfySKBlJm3m2iWFxFIQaV8Bpgc/MEuEZjtWTsZafj3n3OPZdQH3uNsBQOweu+++47Opbf7g/l+Oabbw536p0LH+e1j4L4vpWWxD9iJBD8G9/4xpA9lzjizikuoRC4dTW0+/n976L7cwl1nH/MM3zkPO6///7BvedBlWzCHh6ROgYKoMZ47NNfY0MuxuwbsM/xx/wmiT8Gtf/9B9Fl6MXv2xb/sth/zOmC1Kx7WPm5YtUx/T//nyAgxXm23mPg3nvvvTRfcv7/+7xHetOZr7766pD7iHPu89/Sv+EFIn5puTimn0n8Y9D7339lnWvMyUfXCK04Xla694y9axLPI7x4vlYJqynNb3/72wPpA8e5nnl/jENLLYnf0mic60sU4yg6sZf9XPPP57o16i3lhfCIbjchmXuflbbEPCGkf+GFF5pYfeia5S1ayugbwMUTnxsdrvQoia7wJ/0ROkgcsvRzzT2XujTkDnfXTIdEV+kGM9l7Mf0rr7zSBOldI0+QkqMAWmpNEb/GPPdVYLOqEj8ttagws4KMa99zI/CSdoqXJPFqhERIzyOym5Blx61gRuGZrZDDaK0tmvgGhvs8x4YMuwRBX95+++0hKcXKU0o9N6RHeLMcprIo9tIN6U3XeShTbikccr3KjWsou2NxLD8SR/SIoEzpEhEaMaFy17maPmiUj+SdWnseSHw+V7+OPa9YXi2D+JabXzqWh4+pzZdffnlYZsvKt6Qo9Y+lb9HNN7ZNEd90x5TEB4ABsrss4s01z6q+XgJPIVBLwgufQ5vxI/BIL5NdmvD6Q1kLg1566aWhkKlFzMLat5bUi/FsivhcoqmJDwjLNMXVUxKfwqFsYmvr1vIMISD7Phs3+LFwXPtaewbyzihJ3hGL32qLSsRW+9cU8QnOHKuXuIky6DUKSXYNvDhUMY4CE9a+pbh0V38v+4wCY91gh/BW09WI5WHEyqu5d9OPlguYyLDl1xYZtdqaIj6BmaO6iVAhoOSQCqsa7ikBQBICi/Asfc/738X18NLO1sU4LH2tJcdwkrGXwGsdM2GHNQeKk+bwXvdVNE0RH1C0pAUoUzcCdWu96MX5a+2SIpfAYrm+li3WvthzZxXjKL2tYeX1gydmybGkp9qGlhvFbupSfqNGQrPktTdHfMBRAHMkbAiZ2JQwl4z3hRLcU8U44vqeXXveEK/MnDxLD68alg1minEoyl5u+kH5wYTXWAOTkyU+oUL8Wq72PsBxwWnuIP8xfaG8JKMIcMSljt1jg4OH+XixPNeeVSvdYBabhBqLXpKesJHfOFsTvwYupXFuyuK7OJaWq80tnoMkBE+tt/JPCRru7BjtzS1VTSb7jPyuZY7rKSUwrDzBtjNOeGWljh3HCSsvlpf8PEbpxjGneNZPns9jjz02yMsU5zz2HM0RX7JILTfiz9Ui2Sfu59KqvhL77yOIFIf5eHu3y0K3HpdehTFlZS5awso2YrWq0ChHNfasPAWg9aAo9VEWn4dYYhfgq8aj1Pd3rTvelO+pO7LeYjuk2YdspcDYdRyDyr2NmmvWzmfbXgBFoa9iUW6q2YHYwrkxeHdd4h2fwVy/XWdYeeT3vnSDm8SdBJ6ZFYqzt8YLeu655walOLe87oPduo93NWfxAWdOmGVpwVoiNUKzSEIA8Zu+bcdxEnaslP4S3B6Fd1tg9F+4JZb3cL2lBZpigakbftxaz6bAsDclqb9yHTZTLZkM3h6LWq+bIz4wWVgWppU52xBIU3Ae+rVNhPjeIG2/rjVoNY/LqpueMw9NAXu/fa0lzg1DyU636Wblve8NN5jI3rsFGi+wt9Yc8UPIxJOm1whFC+28YJ5/30Ifj+kD3Fkt+QxWvlYtgxCIhRfKtaLYD8UNVtYhPPvss6OTv4ees/TvmyN+XCBgJfl6yu5G33t7lq+A99l6KspquhqxvPDBLAfCm97suUn0Xrt2bUh21sBqCmyaJb4YWpZ0jiq+KYBv5RxwNnMRN7Co0S9To6Y1ld1aDMVi9ugx6TNj5F4JdhLaTvDWwK3mMZslPk0qxpRNNz2WrSwC4a4ifCRTy57h3XwHosvYm97saZpuFxZietup91CZt6v/2581S3ydFGeyRrK/rcT62+D1+BrhlZbaFpxrL5Faw11lHU1rPv/8891vFMqyw0tMfwqkJ7dNE5+QIr4MMKvfo3vYknKAJ2XKTYUrBeCzGs303IsvvjgUMfU8bjAScj711FPdJvJ2jW/TxNdhc8iAlw0OV3HXheRnlyOg5JZLb+VY7fUQ6hlsiaXuoUfS6zOFSPaUbT/55JPVZjkuH7V63zZPfAPAzZLdtxFlj4JUb/iuPjL8ZKFjmo4w1248NNWXvY6V0Ectg9p79Qxz7BFRe4yaJz4AZJ7ViksUzVnDX3swSh9fbKrklvBKknJbazdemem6HivxYEMxkjWe0dgFWrUxLnH8+pJQopfrY5hnNhjixt5LYgtBsvMwLDxLqxjnbJ28E8t7PdXUk0o88/W9WXu4SXRev359syX2VJjtHMjKH3ZDfAPDelkFZdlmb4JVeRw3hyes5poff/zxoex5Ciu/Ofn6BTdfRV4vjVzBiGyZqoPd1JjNgVVXxBd7KSeV6Mt4/05x4aYqdZa1tz6cUE/ZJPUsaDL1OvW5x1ynPrLyZ2vP6Gtf+1oXfR5znbv+0w3xdd5AEW5FJ2JJCb+0/O/efdaiJrG8ktu5klEUsiq91huZgZGVdTxI4dDSWlfENzjIbzrKNAvLIuG3ZPJThATYg5s6Z1xKGdsqq3VrT34QnqKsVcDUuiLpjvgAJdzmpM2v2rWFe0nYlqYAQgGqJjPzMSfhYI/0re+Rx7orxoEZqz8nZnMqhy6JDzADJtNvPbSy0J4SSscOOMUnlpfAY/G9X6oA74slxcjKMxZz5D/27edUv+ua+EAyiN/85jeHSjGW/5Sn+hBcya1KRm5q1Ngn6S+miwy9EMgy2rN1Ei+V5LtYdUv8GGrCL07jvln6aQ751Bb0RDKKe2pW41QWisQY1npmFODF0qvESwX5/0h3T3yXYkBltRX4GOzYj5127z3u13+xPCsvPk039f+F97JXUfOhVLnWbkKXnb/1706C+EBGfjXp5rBZRPu5RdKv9UHY1b+wTjEvz6vhtsbnu/6Tn72LgNyHOnsKcwnFOGPG/WSI7+KRQhJHxv/GjRvDji+2bhb392L5g9iuI2L5SOCNGeCl/Id3pzTZ7jhn61hext5n2XYjcFLEd4mII+5n/WMNtZViiktaj/31PZJRj6yLlLirKby7BXf7UySHFdIrYArluf2bfP1eBE6O+NuXRwGwmqb91JBL/Fnd16ICYOHlKQiwYhzvs12NgDGWvOPec+2z7YfASROf5vcwnSPBg1Q277SCzI4+asvntKjCDwSXk/CwDFQ/CXO2qxGAH6wsozXG2fZH4KSJvw0DF5rlZxVs7MHy8wLi/nahJGrlAhw/ju1ZPCpLTxlJ3Injk/DbI7b/a7jBFMbZ9kNgMcQHB8GgAMT/LGvssiIBGMtJJQJrJAN5Fh7OjfCy9ax9kD2Fdj+BzV+VQWBRxA/IkMwDERFPIk0lnN18rfjzbAcZoYCH++exKGGx4zi7nuPYFIwHcrPuXFHWncKJ38TzruPkZ4lATQQWSfxtQCPGpwBMA3qw+Gr/LTGlACw8sfIs7op7kVsZRPeM7Nx3RFd0E+fZPne+TgTmQmDxxN8FPEss7vbQEB3prwoDKA+PbZI71j6ewq5+5GeJQC0Ekvg7kEXW7eY9Kz62nT/e2OPk/xKBUghkaVMpJPM4iUBHCCTxOxqs7GoiUAqBJH4pJPM4iUBHCCTxOxqs7OrFCGQe5WJsdn2TxN+FSn7WDQIIb+o022EIJPEPwyt/3RgCUSDVWLea704Sv/khyg5ehoB1F+nmX4bQ7u+S+LtxyU87QEChlK21tgumOuh2E11M4jcxDNmJQxFQRWntgxLrbIcjkMQ/HLP8RwMI2HXnbL3FVix6aqBLXXUhid/VcGVnAwFLm+1UZG1EtsMRSOIfjln+Y2YEbKZiF91YRDVzd7o8fRK/y2FbbqeR/fr168NmJpnUGy8H45ecjT9n/jMROBgBS5ttnWbnZPdOyCm8gyF8zx+S+O+BI9+0iIA43lZlbnhp3j4t/fGjlMQ/HsM8QkUE7FH46KOPDlaem5+WvgzYSfwyOOZRCiKA3Fx7N8dg5T0rzU1LXw7kJH45LPNIhRCw25EboLL0NilNwhcCduswSfwtMPLlvAgguLsJPfPMM5s5+nTt64xJEr8OrnnUAxDg1lta63ZnboXljkKUQJL+ABAP/GkS/0DA8udlEUBu9fbuf/fggw9mCW5ZeC88WhL/Qmjyi5oIsPJRb68Kj5U/Zifjmn09xWMn8U9xVDu4JmW3TzzxxHAHIzceyQTetIOWxJ8W78WfjVV3z8K4l73inIzlpxeLJP70mJ/kGZEXqS9aLed7Vl4cL4GXC2zmFYMk/rz4n9TZ1dIrqb158+ZwXchuwwwKwTJasbznjOXnH/Yk/vxjcDI9MCV37dq1werfvn17uOmopJ27EbP0LH669m0M913r7Op/2+hK9uIUEHBzUXcYdrdh1l7m3i45EngZy7cxwutxuCuJ38ZYZC8SgckQwPvciGMyuPNEiUA7CCTx2xmL7EkiMBkCSfzJoM4TJQLtIJDEb2cssieJwGQIJPEngzpPlAi0g0ASv52xyJ4kApMhkMSfDOo8USLQDgJJ/HbGInuSCEyGQBJ/MqjzRIlAOwgk8dsZi+xJIjAZAkn8yaDOEyUC7SCQxG9nLLInicBkCCTxJ4M6T5QItINAEr+dscieJAKTIZDEnwzqPFEi0A4CSfx2xiJ7kghMhkASfzKo80SJQDsIJPHbGYvsSSIwGQJJ/MmgzhMlAu0gkMRvZyyyJ4nAZAgk8SeDOk+UCLSDQBK/nbHIniQCkyGQxJ8M6jxRItAOAkn8dsYie5IITIZAEn8yqPNEiUAikAgkAonAjAj8H+4FyMWonSP/AAAAAElFTkSuQmCC", "document_status_id": 2 }, + { + "id": "d9926bd9-bce0-4605-a083-7066ffe5147c", + "date_created": "2023-10-08T08:15:00.000000+00:00", + "document_name": "AdditionalTechnicalInfo.pdf", + "media_type_id": 6, + "document_type_id": 9, + "company_user_id": "ac1cf001-7fbc-1f2f-817f-bce058019993", + "document_hash": "z4PhNX7vuL3xVChQ1m2AB9Yg5AULVxXcg/SpIdNs6c5H0NE8XYXysP+DGNKHfuwvY7kxvUdBeoGlODJ6+SfaPg==", + "document_content": "iVBORw0KGgoAAAANSUhEUgAAAP4AAAD6CAYAAACBB/pHAAAAAXNSR0IArs4c6QAAAHhlWElmTU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUAAAABAAAARgEoAAMAAAABAAIAAIdpAAQAAAABAAAATgAAAAAAAACQAAAAAQAAAJAAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAAP6gAwAEAAAAAQAAAPoAAAAADPFyXQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAJdlJREFUeAHt3QmXJEXVBuBCcd8QFQUFGhEZYAB15P//ABQBAREYHXXEBfd996sn8dZX9FR3V2VFZEZU3jinTu2ZkW/c925xI/Ku/67bKlsikAgsBoG71u19i7navNBEIBHYIJDE30CRLxKB5SCQxF/OWOeVJgIbBJL4GyjyRSKwHASS+MsZ67zSRGCDQBJ/A0W+SASWg0ASfzljnVeaCGwQSOJvoMgXicByEEjiL2es80oTgQ0CSfwNFPkiEVgOAkn85Yx1XmkisEEgib+BIl8kAstBIIm/nLHOK00ENggk8TdQ5ItEYDkIJPGXM9Z5pYnABoEk/gaKfJEILAeBJP5yxjqvNBHYIJDE30CRLxKB5SCQxF/OWOeVJgIbBJL4GyjyRSKwHASS+MsZ67zSRGCDQBJ/A0W+SASWg0ASfzljnVeaCGwQSOJvoMgXicByELh7OZfa15X+85//XP3tb39b/fGPf1z94x//WN1zzz2rj33sY6v3v//9q/e9L/V1X6PZXm+T+I2NyX/+85+B6L/4xS9Wt27dWv3lL39ZudnR3XffvXr44YdXZ2dnqw996EON9Tq70xsCSfyGRuzf//73YOER/uc///nqX//612p9t6OhhzyAH/7wh6sPf/jDgwJoqNvZlQ4RSOI3MGgsOnce2X/84x8P5PdZkD66SDH85je/WT3wwAOrD3zgA/FxPicCByOQxD8YsrJ/4Npz53/wgx+suPcUwGUN+f0nWyJwDAJJ/GPQO+K/LDpX/re//e3qzTffXP3+978fYvmrDnneC7jq9/l9IrALgST+LlQqf8Zi//nPfx7c+p/+9KeDAqAIsiUCUyGQxJ8K6fV5kFuSTpz+ox/9aHj2WZJ+wkHIUw0IJPEnEgTkNi/PwiO919kSgbkQSOJXRh7hufasvIy9BF5a+Mqg5+GvRCCJfyVE43+A4H/9619XP/vZz1a3b99e/elPfxp/sPxnIlAQgSR+QTDjUCy8h3JbxTjvvPPOENvH9/mcCMyNQBK/8Aiw8ubaWXmVdmnlCwOchyuCQBK/CIzvHoSVV4xz8+bNTcltwcPnoRKBYggk8QtBifS/+93vVm+99dbqV7/6VSbwCuGah6mDQBK/AK7ce/H8G2+8sfr1r39d4Ih5iESgLgK5sPtIfJHenDz33pRdtkSgBwSS+EeMEtJrinKsrIv3Rxwy/5oITIJAEv9ImGXtTdkl6Y8EMv8+KQJJ/CPgltBTfqv+Plsi0BMCSfwjRssKO8tq09ofAWL+dRYEkvhHwM7NV5KbLRHoDYEk/sgRY+VZfJtppMUfCWL+bTYEkvgjoVeWy9on6UcCmH+bFYEk/kj4EZ+1z5YI9IhAEv+IUcv9744AL/86KwJJ/Fnhz5MnAvMgkMSfB/c8ayIwKwK5SGdW+PPkxyBwPrGaodf+aCbx98cqfzkjAkiuUtIjXutOkB/ptx9uLOoGo9l2I5DE341LftoAAlY9mjL9+9//vnm405ASaQ8zK4gflt6NRd1azLMbi24/3HPQ+/htA5c3axeS+LPCnyeHAPKG5UZ2y5uVQtvjwI5GHgjP2gfZ4z/xv21r73XcThzhPdxi/OMf//jq05/+9Oree+9dfeQjH3mP0liaQkjiJ/dmQyBIi9CI7v6Bv/zlLwcrHxY9FMNVnYxjxe9i4RSlEaTm/lMCH/zgB1ef/exnV1/+8pdXn/nMZwYl4f/xuzjGKT8n8U95dBu9NkRX/BR3CHbvQNuVIR4CnifxsZcRx+MthAfhXoUUDet/7dq1QREIBYQJFMSptyT+yBEmTAQ42/4IwIsl/sMf/jDcWMQNRmJ/wiD9/kcb98tQAvHMw3CTEx7A2dnZ6nOf+9zqk5/85JAPOGUFkMQfIT+E1956rEe2/RBgbbnzb7/99rCHgY1JKQKEn9PFjvMbT7mFe+65Z/XAAw+sHnzwwSEM4AGcYjvNq6o4UtxTLqJ983NJ7tVAs6wUpHsMsPAIT3EG4a4+wjS/COWjf5KKtlKjAB599NHVpz71qWk6MeFZkvh7gE14PcSFdtIlHLlA52rgYASrl156aXM3ITgGya4+wjy/CO9ESCIUePLJJwclYKag9b7vi1gS/wqkCCorTwDsmZ/u/RWArb/mwsPM/QJfeOGFLu8MbNwpLuPOA5AAZP3NCrTmrVw9Inf+Iol/JyabT2h+g25fPa6999kuRwBZxMqUJPf+FDAT0vFaeAAUgDxA71WBSfwL5FghiWwvq8XFZwGyXYwAfGD2k5/8ZCC9ZNkpYcaLocwYgieeeGJw/VUJ9tqS+FsjF4JqLz3WCvG5rNkuRiAwY+W///3vD4qSAjjFxsUnE1FC/Mgjjwzz/j3G/Un8/0koATaAbo4ha4/8tHy2ixGAGYxk67/73e8OrvCpY0ZGeIBcf2HNV77ylWF9QG/kT+Kv5ZqwiuMIMNfedFNYsovFftnfwMxmo6+//vpw+7ClYUZeXn755SHWZ/mVAffUFk185I5klASeuLR1ixWLT+YSMpjFLIepTUlPny1RUcLhW9/61lDii/w9TfctlvgEldZWSSYh1cs0nXryuTLKYeXlPyLR1ZuLW1phMhwsv/Les3XJ71xjc+h1LZL4BJh1v7W+553nXqacCNdHP/rR2RaRyH+w8ua2o/ruUIE7td9TfEKeV155ZZjjV+3XgzJcFPHDTRXHh5XvyUUVRyL+lA0+sthW0IWVn/L8vZxLwu+1114bxsc8f+vkXwTxCS8rrwBDLG9KhovWUyNIVo1NVTcOLw/TdK+++upQu87KZ7sYAXJFQT777LPD6r6Lfzn/NydPfKQnsLEqjFvWk5UnIvprldj9998/SfYY4Vl5XpGsfRYw7UdUuMl/2Nyj9Xj/pIkvdjcfz8pbbdWrxRLbcx8///nP7yeBR/wKZuG2iukpgGz7I6B46Xvf+95Afh5aq2v6T5b4tK9NHm7evDkIsvc9NtZeXB+FIjWvIaw8wbWqDmatx6o18RhzbHgJj3hKN27cSOKPAXHsf8TvXHuk72Wa7vy1EiCkl9CzN5xNIms05/CQ/xCfclWj5DZJPx5xxWAy/A899ND4g1T858lZfEQHOve+twTe+XFGeoUhX/ziF6tZjlCSrHxPU5vnsWrtPeVpFkS8z2NrTYmeDPFZLQU5rJZqsl5dewIiLlSow1rYAqrG9k+R/7AuAWZh5VsjUM/9EWryPK3jT+JXGknxKQ3b+7r5SOSJ6VmL0gJDQbLypp7MOyvGoQRKn6fSMHd1WDKpSOxLX/rSsI9/S53v3uITZDXTSE+7EuIeG+Kx8tz6WPRRmozhFYWVN+Phs9Ln6RH/Wn22wahkX2sVfd0TPyy9Oede3Xv13Qpzzta13vfdd1+Vem9Wnusp22yazvskfC26v3tcSjVmSkzF1gjZxl5B18Q3L8/SK8HtjfRBOru4fOELXxhI7xZP8fnYAT3/v7DysvVmOUzTaaXPc/68td7r97aX4rV2/nri81r92Pe4+iGcgru9+1tp3RKfS0+YWa9e3XtWnlsfVv688B4rJJQhgbNJhtxH77sJBT5mOyhJ2XL3wNMkJ83oCF9cZyiIYzEs8X8FUWZMauRsxvavS+ITaIJs2q430hNIVp7rd7Z27T/xiU8MYxdCPXYgt//HyiACjKwaM0ffm0e0fT0SnjBDdrGy0mWk5zrHMlihiwfSv/POO0O5McJ5P/e1k1F9evjhh4cVfNvXNtfr7ohPqGOxjfipp4bc7tpqio4QhNCWvAZCxuqZopO1h1dJpVKyr/scK/Ifipi++tWvXhgnS4xGcxssv5X3sQ+gBNuc5doUl1kU60Rsz91C64r4hBjZufi0eU+NdSKQCO9GjTXICJtYM8/CaDXOMxXurDol+dhjjw2YHXJeeAujxNVmMeQ35lygZWzILHe/hdYd8Qk27UkJ9NAQj4tqLpebWkvjs2oSncIfAt5rM64sJMKy2nDbtuaHXpdQyp1wjIFch+2x55AdnphZFcqoBWXcDfHFaTQma996XB8DS4BZd4PtubRrT4DFtRShNfMEq3VsLiMu3CTuzta5D6SX/CyBmfyAKkjH/853vjOLYiS/Eq3GLOTjMixqf9cN8cVotn3qJTNN2Lj1hJgwl24ESALPvDxcest3nMeDkpT/eOqpp6pgZjzkCeQ/JDwpzCmb8TLrwBuLhO6U5z9/ri6IDzQuPnfW65ab2JIAu9tKrXiOEuT92OQRLq1jctl4sX6R/3jmmWeGqc3Lfn/sd26BZWpN4m/K5jopG6GGsGNuq98F8YHVeg2+gRSLKsZh6Q1u6YbgLIY4Xta+twTneTxYeZtVwMtClhqYnT8ny//0008P02tTL0xC/FbyL80TX8yK9MjfWkN2ZCTA4lFxpPl5wlWyOYeHWD7WJBDaua3G2GvUb1aekhTLT1nO6tyUzdk6BLMUeSoMnQfxrSA1llOd96Ixap74gDI1NXcRxi4ADaDkU8zLc/FrDKjzRCzPYlCGNc6z6xprfCbnEbF8Lcwu6zfFTOlIFE+ZGyHDzmc8525NEx9ArFysIpsbrO3zs/Km5sSMpp5YsJJkdO0ExbW/+OKLw8pDFqMFodnGYd/XsKEkJbaee+65oaahRMZ+3/Nv/05fWH2hxdSeE0MmRzPXtQcOTRNfFhTxW5qiIjRILnGnsIQAlW7IzTJY3OHmjJZ1llQqpft71fH0Xf5DKGTr6aivv+p/Nb/naXiYAp2qwaEVz7VZ4gOIwMdqsqkG57LzGDjCoqjEuvkaxTiu2zVzQ1WcsRA9k56SVMMgeSeJV2Nq87Ixu+w7yojlnZKMrYxls8TnDrH2BqUFsPSBlTcXXKMYh4C6Zhl75aUskfctXPtl5LnsO4pR8VJsFio8aqXBVayvT1MSv5Xrb5b4pqpYvrkFP86v3JYAi1HjsxKDyK33kLSzoMQmoax8Kwrv0GuEjYdZDgk8K+kogJKYHdqnXb/XH8RvrV+7+lrjs2aJz+K1UKWHlLL2CnJqJPAcX2GS2y2L6b3vuSGSMMie8pJnLVn587gulfRwaI74BF/2GhnmtnqElsUy11ya9K6NZVdBJoE35bTSeQKUeC9WtprOJqGPP/548VoGfYSZRG/IhTFpWbGUwLXWMZojPi0sqYcUczYCFTF96SSe2J11l8C7td6FlSD33CTJFOFI4El81rCkvD9ywRNkGCgaNxmx1Nn5sx2GQHPERwLx/ZyJLYLLeonpS07X8WbMGyN87H/Xq2sPI32X82DlZexLYhVi7ByqNu2rKNlrijcsvvshwrPFfeuj/60+N0d8hEf8OQnBhYyltCUHjgA///zzg9Xq3bVHPvPysRipdJly4M7CW5dg16Wo5wj3nhdgFkTilaLOtj8CzREfIWS45yI+S8Z9lNAr0VwHgZWttxbc9fXq2sPGA8nF8R7c7CBiCbwcA2bceaRWy8AY7JIHnyE/TJP4h6HfJPG5b3M18byKPAJ+bEN4Vt40Hff+IgE+9jxT/B8e4mq360b4s/UiF+9LN4SHGbwsztqn7VIK+/xvyb9pivgGUG36XBaRcIvrS5SUskIEF+lbXWR0iOBTiLwgpEf+Eopx+/zGnsKHmZkOcuAcSeptlMq9bor4CE/bzzXYBJqbf6wlO5X974gZ8kXGXixdQinuEl+Yce0pyajfmEsOdvXv1D5rjvhzTeMhu6WaY6fuQkjtiGNrJ1NPc85MlBBUsfzZ2qVn5Uvtf7fdL5h5yH8g/Zy5ne1+LeF1c8QPbT81+JJD5u3HWnveCuFVjBNeS2l3eCpM9BseSm5NlZUuXnIdCM+dN62ppkFsH8pzqutc8nmaIr4YjwBM3WSllZeOtfaSeOaYkd60U8/N6jnhjv3vKMIaGXuekGk6CTx4heXvGbfe+t4U8eea6mLlxfdj56LVHdgso2fSI7hiHPULZjVqxPK8IgU4knduaT7n7E1vRC3d3yT+GlFWTtXZGOtGmO3dJinVs2tvYQ3Cy3Nw7Us3nhyMxPPyH3DrFa/S2MxxvPIjfMRVzOXysW422BjTTD9J6PUoxPAW3ojlWXpxfY3rYNm59dtWvsZ5xozfUv+zeOITQMQf49pKRKosmyshOVZoXTPvxl6BtsISy48Ncy7rg9yHPRVgZC97Vj5bGwg0RXyWYWrhQIKxq7sIdW8CHYouinHGhjgXiW9k5ilDnhBLL3cTn1/0v/x8WgSaIv60l/5ucYrE3tg6b9N25p57aax87Ixj+WyN/e8obsnOW+vlxqbpWP1s7SGwaOKzQsgwJplFoGXxp/ZQxoiQ66TcWHnbgSM/y1+6sfJyHhJ45ujTypdGuNzxFk18MI519WWp56oyPGT4XZ8NKxC+1i63lB/vB+ERf45ajEMwyd82uPXW1INyjMWXk2jZqknYmaZzf3jkH1uVeNmYIDmyc+2jYvGy3+d3bSCQFn+ky8vKtezmc+ftjGO1Ya0189x5yTtVi6rxsvWDwOKJ389QXd1Tbj0rrwjHwhqr6nzmUarxcOQ3FOOw8hJ5FGDLnk+paz+l4yTxT2g0JfBYeRV4Y2cqLoMDuU3NWYwknu+tfuGya1vad0n8ExhxsbuFNWJ5a+blLUo3Vt3CGoRn7dPCl0Z42uMl8afFu/jZWHZLZ8Xy4voazcIaxTge6hZKhg41+pvHvBqBJP7VGDX3i4jbldyapmPlS5fcsuisvJ1xJPAsrIlinLT2zYnEwR1K4h8M2fx/UHFnUY07/JQuuXV1iG2aLkpu1SucItlbnpWpLWVJ/NoIFzy+WB7RWXnEH1NxeFV3kIE7b2GN+XnvWyf9mJyGa1KHEV7MVbic2vdJ/E5GlJVXjIP0Enk1moy9BB7Sm6ZrPZbXP6Qfs3MS4qfFryFFecwiCBBuuwOZpjtbb3w5ZvnwVR1BAkS3M47bUpmma530cU2Sm2MXGyk6Wir50+KHBDX4zJWP5bNKbksn8OKSEd7cvEq8nohAYUWRUlzLvs+UWywX7kXJ7Xtt+/wuib8PShP+hhB6sOyq70zTcWXHxLGXdTti3Lfeemuw8lFy6/NeGktvZuPQ5hpNUfawyOrQa9v390n8fZGa6HcIzrW/cePGUHpb47QSWjYRsVdg7HJb4zw1j4m8ch42CB1jsZGexR/z37HX1ZJSTeKPHcXC/yOA9v2zdNYdaGvF8iydbD33vmeLBytu/piZDYrPSkJZ/amb/k6pbC66viT+RchM+LlpOgtruPV2xqkRyxN2GXuEt11Yz2vmkUfR0thKRWEN5ccCT01C4ckYZVVaHJP4pRE98HhIrhAnSm5rxPJc2tgkg8VvyeU8BC4khY+4fqyCdO3qFCwlnpL0zovw8jVTnvcifJP4FyEzwed2t/36178+CDIFUFogCBuX9o033hisPKvfM+kNidkN24GP3SDVrMXt27eH/QNKK9mrRMb5xk49XnXsQ79P4h+K2JG/N/g0v2k6t6kyD116ZxzkNl2lvt5tumNhTc+kh5mY/vr164PVH6skxfX2EZia9MSGch+bjDxS7O74exL/DkjqfUDYxKVW03mMtVqX9ZBFY+XV2ZubZ+W1XklPKUbSk3t/LGHdpJMinLrBn/KqsU/CmGtJ4o9BbcR/kNz0E8KzXMcK8K4usPKSVkhvuq5Xsse1sZCSnnDj4h+LWVQnhjKM80z1zM13c9ax3krJfibxj0BzH2L5DaFVjMNi0fg1Bp6VV2Mvcx8VaUdc2qx/hRmXWMLTugRK81jMzGLAZ64bm4a3VzqsGztQSfyRyBlIFumiRlD9hsUSyyvK4eodK8Dnz8d6WTP/2muvDdVoXP19FNL547TwHjYepuqsPuTiw7AEZqYw7Ssw1zQmwo+dfqwxNkn8kahy2yJRc55oBNW0DYv19NNPV8nkOifX3jTdnAI9Er47/obgMFXA9NBDDxXFTKHS66+/PsT258fqjo5U+oDSN4tTQomV6GISfySKBlJm3m2iWFxFIQaV8Bpgc/MEuEZjtWTsZafj3n3OPZdQH3uNsBQOweu+++47Opbf7g/l+Oabbw536p0LH+e1j4L4vpWWxD9iJBD8G9/4xpA9lzjizikuoRC4dTW0+/n976L7cwl1nH/MM3zkPO6///7BvedBlWzCHh6ROgYKoMZ47NNfY0MuxuwbsM/xx/wmiT8Gtf/9B9Fl6MXv2xb/sth/zOmC1Kx7WPm5YtUx/T//nyAgxXm23mPg3nvvvTRfcv7/+7xHetOZr7766pD7iHPu89/Sv+EFIn5puTimn0n8Y9D7339lnWvMyUfXCK04Xla694y9axLPI7x4vlYJqynNb3/72wPpA8e5nnl/jENLLYnf0mic60sU4yg6sZf9XPPP57o16i3lhfCIbjchmXuflbbEPCGkf+GFF5pYfeia5S1ayugbwMUTnxsdrvQoia7wJ/0ROkgcsvRzzT2XujTkDnfXTIdEV+kGM9l7Mf0rr7zSBOldI0+QkqMAWmpNEb/GPPdVYLOqEj8ttagws4KMa99zI/CSdoqXJPFqhERIzyOym5Blx61gRuGZrZDDaK0tmvgGhvs8x4YMuwRBX95+++0hKcXKU0o9N6RHeLMcprIo9tIN6U3XeShTbikccr3KjWsou2NxLD8SR/SIoEzpEhEaMaFy17maPmiUj+SdWnseSHw+V7+OPa9YXi2D+JabXzqWh4+pzZdffnlYZsvKt6Qo9Y+lb9HNN7ZNEd90x5TEB4ABsrss4s01z6q+XgJPIVBLwgufQ5vxI/BIL5NdmvD6Q1kLg1566aWhkKlFzMLat5bUi/FsivhcoqmJDwjLNMXVUxKfwqFsYmvr1vIMISD7Phs3+LFwXPtaewbyzihJ3hGL32qLSsRW+9cU8QnOHKuXuIky6DUKSXYNvDhUMY4CE9a+pbh0V38v+4wCY91gh/BW09WI5WHEyqu5d9OPlguYyLDl1xYZtdqaIj6BmaO6iVAhoOSQCqsa7ikBQBICi/Asfc/738X18NLO1sU4LH2tJcdwkrGXwGsdM2GHNQeKk+bwXvdVNE0RH1C0pAUoUzcCdWu96MX5a+2SIpfAYrm+li3WvthzZxXjKL2tYeX1gydmybGkp9qGlhvFbupSfqNGQrPktTdHfMBRAHMkbAiZ2JQwl4z3hRLcU8U44vqeXXveEK/MnDxLD68alg1minEoyl5u+kH5wYTXWAOTkyU+oUL8Wq72PsBxwWnuIP8xfaG8JKMIcMSljt1jg4OH+XixPNeeVSvdYBabhBqLXpKesJHfOFsTvwYupXFuyuK7OJaWq80tnoMkBE+tt/JPCRru7BjtzS1VTSb7jPyuZY7rKSUwrDzBtjNOeGWljh3HCSsvlpf8PEbpxjGneNZPns9jjz02yMsU5zz2HM0RX7JILTfiz9Ui2Sfu59KqvhL77yOIFIf5eHu3y0K3HpdehTFlZS5awso2YrWq0ChHNfasPAWg9aAo9VEWn4dYYhfgq8aj1Pd3rTvelO+pO7LeYjuk2YdspcDYdRyDyr2NmmvWzmfbXgBFoa9iUW6q2YHYwrkxeHdd4h2fwVy/XWdYeeT3vnSDm8SdBJ6ZFYqzt8YLeu655walOLe87oPduo93NWfxAWdOmGVpwVoiNUKzSEIA8Zu+bcdxEnaslP4S3B6Fd1tg9F+4JZb3cL2lBZpigakbftxaz6bAsDclqb9yHTZTLZkM3h6LWq+bIz4wWVgWppU52xBIU3Ae+rVNhPjeIG2/rjVoNY/LqpueMw9NAXu/fa0lzg1DyU636Wblve8NN5jI3rsFGi+wt9Yc8UPIxJOm1whFC+28YJ5/30Ifj+kD3Fkt+QxWvlYtgxCIhRfKtaLYD8UNVtYhPPvss6OTv4ees/TvmyN+XCBgJfl6yu5G33t7lq+A99l6KspquhqxvPDBLAfCm97suUn0Xrt2bUh21sBqCmyaJb4YWpZ0jiq+KYBv5RxwNnMRN7Co0S9To6Y1ld1aDMVi9ugx6TNj5F4JdhLaTvDWwK3mMZslPk0qxpRNNz2WrSwC4a4ifCRTy57h3XwHosvYm97saZpuFxZietup91CZt6v/2581S3ydFGeyRrK/rcT62+D1+BrhlZbaFpxrL5Faw11lHU1rPv/8891vFMqyw0tMfwqkJ7dNE5+QIr4MMKvfo3vYknKAJ2XKTYUrBeCzGs303IsvvjgUMfU8bjAScj711FPdJvJ2jW/TxNdhc8iAlw0OV3HXheRnlyOg5JZLb+VY7fUQ6hlsiaXuoUfS6zOFSPaUbT/55JPVZjkuH7V63zZPfAPAzZLdtxFlj4JUb/iuPjL8ZKFjmo4w1248NNWXvY6V0Ectg9p79Qxz7BFRe4yaJz4AZJ7ViksUzVnDX3swSh9fbKrklvBKknJbazdemem6HivxYEMxkjWe0dgFWrUxLnH8+pJQopfrY5hnNhjixt5LYgtBsvMwLDxLqxjnbJ28E8t7PdXUk0o88/W9WXu4SXRev359syX2VJjtHMjKH3ZDfAPDelkFZdlmb4JVeRw3hyes5poff/zxoex5Ciu/Ofn6BTdfRV4vjVzBiGyZqoPd1JjNgVVXxBd7KSeV6Mt4/05x4aYqdZa1tz6cUE/ZJPUsaDL1OvW5x1ynPrLyZ2vP6Gtf+1oXfR5znbv+0w3xdd5AEW5FJ2JJCb+0/O/efdaiJrG8ktu5klEUsiq91huZgZGVdTxI4dDSWlfENzjIbzrKNAvLIuG3ZPJThATYg5s6Z1xKGdsqq3VrT34QnqKsVcDUuiLpjvgAJdzmpM2v2rWFe0nYlqYAQgGqJjPzMSfhYI/0re+Rx7orxoEZqz8nZnMqhy6JDzADJtNvPbSy0J4SSscOOMUnlpfAY/G9X6oA74slxcjKMxZz5D/27edUv+ua+EAyiN/85jeHSjGW/5Sn+hBcya1KRm5q1Ngn6S+miwy9EMgy2rN1Ei+V5LtYdUv8GGrCL07jvln6aQ751Bb0RDKKe2pW41QWisQY1npmFODF0qvESwX5/0h3T3yXYkBltRX4GOzYj5127z3u13+xPCsvPk039f+F97JXUfOhVLnWbkKXnb/1706C+EBGfjXp5rBZRPu5RdKv9UHY1b+wTjEvz6vhtsbnu/6Tn72LgNyHOnsKcwnFOGPG/WSI7+KRQhJHxv/GjRvDji+2bhb392L5g9iuI2L5SOCNGeCl/Id3pzTZ7jhn61hext5n2XYjcFLEd4mII+5n/WMNtZViiktaj/31PZJRj6yLlLirKby7BXf7UySHFdIrYArluf2bfP1eBE6O+NuXRwGwmqb91JBL/Fnd16ICYOHlKQiwYhzvs12NgDGWvOPec+2z7YfASROf5vcwnSPBg1Q277SCzI4+asvntKjCDwSXk/CwDFQ/CXO2qxGAH6wsozXG2fZH4KSJvw0DF5rlZxVs7MHy8wLi/nahJGrlAhw/ju1ZPCpLTxlJ3Injk/DbI7b/a7jBFMbZ9kNgMcQHB8GgAMT/LGvssiIBGMtJJQJrJAN5Fh7OjfCy9ax9kD2Fdj+BzV+VQWBRxA/IkMwDERFPIk0lnN18rfjzbAcZoYCH++exKGGx4zi7nuPYFIwHcrPuXFHWncKJ38TzruPkZ4lATQQWSfxtQCPGpwBMA3qw+Gr/LTGlACw8sfIs7op7kVsZRPeM7Nx3RFd0E+fZPne+TgTmQmDxxN8FPEss7vbQEB3prwoDKA+PbZI71j6ewq5+5GeJQC0Ekvg7kEXW7eY9Kz62nT/e2OPk/xKBUghkaVMpJPM4iUBHCCTxOxqs7GoiUAqBJH4pJPM4iUBHCCTxOxqs7OrFCGQe5WJsdn2TxN+FSn7WDQIIb+o022EIJPEPwyt/3RgCUSDVWLea704Sv/khyg5ehoB1F+nmX4bQ7u+S+LtxyU87QEChlK21tgumOuh2E11M4jcxDNmJQxFQRWntgxLrbIcjkMQ/HLP8RwMI2HXnbL3FVix6aqBLXXUhid/VcGVnAwFLm+1UZG1EtsMRSOIfjln+Y2YEbKZiF91YRDVzd7o8fRK/y2FbbqeR/fr168NmJpnUGy8H45ecjT9n/jMROBgBS5ttnWbnZPdOyCm8gyF8zx+S+O+BI9+0iIA43lZlbnhp3j4t/fGjlMQ/HsM8QkUE7FH46KOPDlaem5+WvgzYSfwyOOZRCiKA3Fx7N8dg5T0rzU1LXw7kJH45LPNIhRCw25EboLL0NilNwhcCduswSfwtMPLlvAgguLsJPfPMM5s5+nTt64xJEr8OrnnUAxDg1lta63ZnboXljkKUQJL+ABAP/GkS/0DA8udlEUBu9fbuf/fggw9mCW5ZeC88WhL/Qmjyi5oIsPJRb68Kj5U/Zifjmn09xWMn8U9xVDu4JmW3TzzxxHAHIzceyQTetIOWxJ8W78WfjVV3z8K4l73inIzlpxeLJP70mJ/kGZEXqS9aLed7Vl4cL4GXC2zmFYMk/rz4n9TZ1dIrqb158+ZwXchuwwwKwTJasbznjOXnH/Yk/vxjcDI9MCV37dq1werfvn17uOmopJ27EbP0LH669m0M913r7Op/2+hK9uIUEHBzUXcYdrdh1l7m3i45EngZy7cxwutxuCuJ38ZYZC8SgckQwPvciGMyuPNEiUA7CCTx2xmL7EkiMBkCSfzJoM4TJQLtIJDEb2cssieJwGQIJPEngzpPlAi0g0ASv52xyJ4kApMhkMSfDOo8USLQDgJJ/HbGInuSCEyGQBJ/MqjzRIlAOwgk8dsZi+xJIjAZAkn8yaDOEyUC7SCQxG9nLLInicBkCCTxJ4M6T5QItINAEr+dscieJAKTIZDEnwzqPFEi0A4CSfx2xiJ7kghMhkASfzKo80SJQDsIJPHbGYvsSSIwGQJJ/MmgzhMlAu0gkMRvZyyyJ4nAZAgk8SeDOk+UCLSDQBK/nbHIniQCkyGQxJ8M6jxRItAOAkn8dsYie5IITIZAEn8yqPNEiUAikAgkAonAjAj8H+4FyMWonSP/AAAAAElFTkSuQmCC", + "document_status_id": 2 + }, { "id": "88793f9f-c5a4-4621-847b-3d47cd839283", "date_created": "2023-01-04T16:05:14.294575+00:00", @@ -97,5 +108,16 @@ "document_hash": "", "document_content": "", "document_status_id": 3 - } + }, + { + "id": "aaf53459-c36b-408e-a805-0b406ce9751e", + "date_created": "2023-10-08T08:00:00.000000+00:00", + "document_name": "AdditionalServiceDetails2.pdf", + "media_type_id": 6, + "document_type_id": 5, + "company_user_id": "ac1cf001-7fbc-1f2f-817f-bce058019993", + "document_hash": "z4PhNX7vuL3xVChQ1m2AB9Yg5AULVxXcg/SpIdNs6c5H0NE8XYXysP+DGNKHfuwvY7kxvUdBeoGlODJ6+SfaPg==", + "document_content": "iVBORw0KGgoAAAANSUhEUgAAAP4AAAD6CAYAAACBB/pHAAAAAXNSR0IArs4c6QAAAHhlWElmTU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUAAAABAAAARgEoAAMAAAABAAIAAIdpAAQAAAABAAAATgAAAAAAAACQAAAAAQAAAJAAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAAP6gAwAEAAAAAQAAAPoAAAAADPFyXQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAJdlJREFUeAHt3QmXJEXVBuBCcd8QFQUFGhEZYAB15P//ABQBAREYHXXEBfd996sn8dZX9FR3V2VFZEZU3jinTu2ZkW/c925xI/Ku/67bKlsikAgsBoG71u19i7navNBEIBHYIJDE30CRLxKB5SCQxF/OWOeVJgIbBJL4GyjyRSKwHASS+MsZ67zSRGCDQBJ/A0W+SASWg0ASfzljnVeaCGwQSOJvoMgXicByEEjiL2es80oTgQ0CSfwNFPkiEVgOAkn85Yx1XmkisEEgib+BIl8kAstBIIm/nLHOK00ENggk8TdQ5ItEYDkIJPGXM9Z5pYnABoEk/gaKfJEILAeBJP5yxjqvNBHYIJDE30CRLxKB5SCQxF/OWOeVJgIbBJL4GyjyRSKwHASS+MsZ67zSRGCDQBJ/A0W+SASWg0ASfzljnVeaCGwQSOJvoMgXicByELh7OZfa15X+85//XP3tb39b/fGPf1z94x//WN1zzz2rj33sY6v3v//9q/e9L/V1X6PZXm+T+I2NyX/+85+B6L/4xS9Wt27dWv3lL39ZudnR3XffvXr44YdXZ2dnqw996EON9Tq70xsCSfyGRuzf//73YOER/uc///nqX//612p9t6OhhzyAH/7wh6sPf/jDgwJoqNvZlQ4RSOI3MGgsOnce2X/84x8P5PdZkD66SDH85je/WT3wwAOrD3zgA/FxPicCByOQxD8YsrJ/4Npz53/wgx+suPcUwGUN+f0nWyJwDAJJ/GPQO+K/LDpX/re//e3qzTffXP3+978fYvmrDnneC7jq9/l9IrALgST+LlQqf8Zi//nPfx7c+p/+9KeDAqAIsiUCUyGQxJ8K6fV5kFuSTpz+ox/9aHj2WZJ+wkHIUw0IJPEnEgTkNi/PwiO919kSgbkQSOJXRh7hufasvIy9BF5a+Mqg5+GvRCCJfyVE43+A4H/9619XP/vZz1a3b99e/elPfxp/sPxnIlAQgSR+QTDjUCy8h3JbxTjvvPPOENvH9/mcCMyNQBK/8Aiw8ubaWXmVdmnlCwOchyuCQBK/CIzvHoSVV4xz8+bNTcltwcPnoRKBYggk8QtBifS/+93vVm+99dbqV7/6VSbwCuGah6mDQBK/AK7ce/H8G2+8sfr1r39d4Ih5iESgLgK5sPtIfJHenDz33pRdtkSgBwSS+EeMEtJrinKsrIv3Rxwy/5oITIJAEv9ImGXtTdkl6Y8EMv8+KQJJ/CPgltBTfqv+Plsi0BMCSfwjRssKO8tq09ofAWL+dRYEkvhHwM7NV5KbLRHoDYEk/sgRY+VZfJtppMUfCWL+bTYEkvgjoVeWy9on6UcCmH+bFYEk/kj4EZ+1z5YI9IhAEv+IUcv9744AL/86KwJJ/Fnhz5MnAvMgkMSfB/c8ayIwKwK5SGdW+PPkxyBwPrGaodf+aCbx98cqfzkjAkiuUtIjXutOkB/ptx9uLOoGo9l2I5DE341LftoAAlY9mjL9+9//vnm405ASaQ8zK4gflt6NRd1azLMbi24/3HPQ+/htA5c3axeS+LPCnyeHAPKG5UZ2y5uVQtvjwI5GHgjP2gfZ4z/xv21r73XcThzhPdxi/OMf//jq05/+9Oree+9dfeQjH3mP0liaQkjiJ/dmQyBIi9CI7v6Bv/zlLwcrHxY9FMNVnYxjxe9i4RSlEaTm/lMCH/zgB1ef/exnV1/+8pdXn/nMZwYl4f/xuzjGKT8n8U95dBu9NkRX/BR3CHbvQNuVIR4CnifxsZcRx+MthAfhXoUUDet/7dq1QREIBYQJFMSptyT+yBEmTAQ42/4IwIsl/sMf/jDcWMQNRmJ/wiD9/kcb98tQAvHMw3CTEx7A2dnZ6nOf+9zqk5/85JAPOGUFkMQfIT+E1956rEe2/RBgbbnzb7/99rCHgY1JKQKEn9PFjvMbT7mFe+65Z/XAAw+sHnzwwSEM4AGcYjvNq6o4UtxTLqJ983NJ7tVAs6wUpHsMsPAIT3EG4a4+wjS/COWjf5KKtlKjAB599NHVpz71qWk6MeFZkvh7gE14PcSFdtIlHLlA52rgYASrl156aXM3ITgGya4+wjy/CO9ESCIUePLJJwclYKag9b7vi1gS/wqkCCorTwDsmZ/u/RWArb/mwsPM/QJfeOGFLu8MbNwpLuPOA5AAZP3NCrTmrVw9Inf+Iol/JyabT2h+g25fPa6999kuRwBZxMqUJPf+FDAT0vFaeAAUgDxA71WBSfwL5FghiWwvq8XFZwGyXYwAfGD2k5/8ZCC9ZNkpYcaLocwYgieeeGJw/VUJ9tqS+FsjF4JqLz3WCvG5rNkuRiAwY+W///3vD4qSAjjFxsUnE1FC/Mgjjwzz/j3G/Un8/0koATaAbo4ha4/8tHy2ixGAGYxk67/73e8OrvCpY0ZGeIBcf2HNV77ylWF9QG/kT+Kv5ZqwiuMIMNfedFNYsovFftnfwMxmo6+//vpw+7ClYUZeXn755SHWZ/mVAffUFk185I5klASeuLR1ixWLT+YSMpjFLIepTUlPny1RUcLhW9/61lDii/w9TfctlvgEldZWSSYh1cs0nXryuTLKYeXlPyLR1ZuLW1phMhwsv/Les3XJ71xjc+h1LZL4BJh1v7W+553nXqacCNdHP/rR2RaRyH+w8ua2o/ruUIE7td9TfEKeV155ZZjjV+3XgzJcFPHDTRXHh5XvyUUVRyL+lA0+sthW0IWVn/L8vZxLwu+1114bxsc8f+vkXwTxCS8rrwBDLG9KhovWUyNIVo1NVTcOLw/TdK+++upQu87KZ7sYAXJFQT777LPD6r6Lfzn/NydPfKQnsLEqjFvWk5UnIvprldj9998/SfYY4Vl5XpGsfRYw7UdUuMl/2Nyj9Xj/pIkvdjcfz8pbbdWrxRLbcx8///nP7yeBR/wKZuG2iukpgGz7I6B46Xvf+95Afh5aq2v6T5b4tK9NHm7evDkIsvc9NtZeXB+FIjWvIaw8wbWqDmatx6o18RhzbHgJj3hKN27cSOKPAXHsf8TvXHuk72Wa7vy1EiCkl9CzN5xNIms05/CQ/xCfclWj5DZJPx5xxWAy/A899ND4g1T858lZfEQHOve+twTe+XFGeoUhX/ziF6tZjlCSrHxPU5vnsWrtPeVpFkS8z2NrTYmeDPFZLQU5rJZqsl5dewIiLlSow1rYAqrG9k+R/7AuAWZh5VsjUM/9EWryPK3jT+JXGknxKQ3b+7r5SOSJ6VmL0gJDQbLypp7MOyvGoQRKn6fSMHd1WDKpSOxLX/rSsI9/S53v3uITZDXTSE+7EuIeG+Kx8tz6WPRRmozhFYWVN+Phs9Ln6RH/Wn22wahkX2sVfd0TPyy9Oede3Xv13Qpzzta13vfdd1+Vem9Wnusp22yazvskfC26v3tcSjVmSkzF1gjZxl5B18Q3L8/SK8HtjfRBOru4fOELXxhI7xZP8fnYAT3/v7DysvVmOUzTaaXPc/68td7r97aX4rV2/nri81r92Pe4+iGcgru9+1tp3RKfS0+YWa9e3XtWnlsfVv688B4rJJQhgbNJhtxH77sJBT5mOyhJ2XL3wNMkJ83oCF9cZyiIYzEs8X8FUWZMauRsxvavS+ITaIJs2q430hNIVp7rd7Z27T/xiU8MYxdCPXYgt//HyiACjKwaM0ffm0e0fT0SnjBDdrGy0mWk5zrHMlihiwfSv/POO0O5McJ5P/e1k1F9evjhh4cVfNvXNtfr7ohPqGOxjfipp4bc7tpqio4QhNCWvAZCxuqZopO1h1dJpVKyr/scK/Ifipi++tWvXhgnS4xGcxssv5X3sQ+gBNuc5doUl1kU60Rsz91C64r4hBjZufi0eU+NdSKQCO9GjTXICJtYM8/CaDXOMxXurDol+dhjjw2YHXJeeAujxNVmMeQ35lygZWzILHe/hdYd8Qk27UkJ9NAQj4tqLpebWkvjs2oSncIfAt5rM64sJMKy2nDbtuaHXpdQyp1wjIFch+2x55AdnphZFcqoBWXcDfHFaTQma996XB8DS4BZd4PtubRrT4DFtRShNfMEq3VsLiMu3CTuzta5D6SX/CyBmfyAKkjH/853vjOLYiS/Eq3GLOTjMixqf9cN8cVotn3qJTNN2Lj1hJgwl24ESALPvDxcest3nMeDkpT/eOqpp6pgZjzkCeQ/JDwpzCmb8TLrwBuLhO6U5z9/ri6IDzQuPnfW65ab2JIAu9tKrXiOEuT92OQRLq1jctl4sX6R/3jmmWeGqc3Lfn/sd26BZWpN4m/K5jopG6GGsGNuq98F8YHVeg2+gRSLKsZh6Q1u6YbgLIY4Xta+twTneTxYeZtVwMtClhqYnT8ny//0008P02tTL0xC/FbyL80TX8yK9MjfWkN2ZCTA4lFxpPl5wlWyOYeHWD7WJBDaua3G2GvUb1aekhTLT1nO6tyUzdk6BLMUeSoMnQfxrSA1llOd96Ixap74gDI1NXcRxi4ADaDkU8zLc/FrDKjzRCzPYlCGNc6z6xprfCbnEbF8Lcwu6zfFTOlIFE+ZGyHDzmc8525NEx9ArFysIpsbrO3zs/Km5sSMpp5YsJJkdO0ExbW/+OKLw8pDFqMFodnGYd/XsKEkJbaee+65oaahRMZ+3/Nv/05fWH2hxdSeE0MmRzPXtQcOTRNfFhTxW5qiIjRILnGnsIQAlW7IzTJY3OHmjJZ1llQqpft71fH0Xf5DKGTr6aivv+p/Nb/naXiYAp2qwaEVz7VZ4gOIwMdqsqkG57LzGDjCoqjEuvkaxTiu2zVzQ1WcsRA9k56SVMMgeSeJV2Nq87Ixu+w7yojlnZKMrYxls8TnDrH2BqUFsPSBlTcXXKMYh4C6Zhl75aUskfctXPtl5LnsO4pR8VJsFio8aqXBVayvT1MSv5Xrb5b4pqpYvrkFP86v3JYAi1HjsxKDyK33kLSzoMQmoax8Kwrv0GuEjYdZDgk8K+kogJKYHdqnXb/XH8RvrV+7+lrjs2aJz+K1UKWHlLL2CnJqJPAcX2GS2y2L6b3vuSGSMMie8pJnLVn587gulfRwaI74BF/2GhnmtnqElsUy11ya9K6NZVdBJoE35bTSeQKUeC9WtprOJqGPP/548VoGfYSZRG/IhTFpWbGUwLXWMZojPi0sqYcUczYCFTF96SSe2J11l8C7td6FlSD33CTJFOFI4El81rCkvD9ywRNkGCgaNxmx1Nn5sx2GQHPERwLx/ZyJLYLLeonpS07X8WbMGyN87H/Xq2sPI32X82DlZexLYhVi7ByqNu2rKNlrijcsvvshwrPFfeuj/60+N0d8hEf8OQnBhYyltCUHjgA///zzg9Xq3bVHPvPysRipdJly4M7CW5dg16Wo5wj3nhdgFkTilaLOtj8CzREfIWS45yI+S8Z9lNAr0VwHgZWttxbc9fXq2sPGA8nF8R7c7CBiCbwcA2bceaRWy8AY7JIHnyE/TJP4h6HfJPG5b3M18byKPAJ+bEN4Vt40Hff+IgE+9jxT/B8e4mq360b4s/UiF+9LN4SHGbwsztqn7VIK+/xvyb9pivgGUG36XBaRcIvrS5SUskIEF+lbXWR0iOBTiLwgpEf+Eopx+/zGnsKHmZkOcuAcSeptlMq9bor4CE/bzzXYBJqbf6wlO5X974gZ8kXGXixdQinuEl+Yce0pyajfmEsOdvXv1D5rjvhzTeMhu6WaY6fuQkjtiGNrJ1NPc85MlBBUsfzZ2qVn5Uvtf7fdL5h5yH8g/Zy5ne1+LeF1c8QPbT81+JJD5u3HWnveCuFVjBNeS2l3eCpM9BseSm5NlZUuXnIdCM+dN62ppkFsH8pzqutc8nmaIr4YjwBM3WSllZeOtfaSeOaYkd60U8/N6jnhjv3vKMIaGXuekGk6CTx4heXvGbfe+t4U8eea6mLlxfdj56LVHdgso2fSI7hiHPULZjVqxPK8IgU4knduaT7n7E1vRC3d3yT+GlFWTtXZGOtGmO3dJinVs2tvYQ3Cy3Nw7Us3nhyMxPPyH3DrFa/S2MxxvPIjfMRVzOXysW422BjTTD9J6PUoxPAW3ojlWXpxfY3rYNm59dtWvsZ5xozfUv+zeOITQMQf49pKRKosmyshOVZoXTPvxl6BtsISy48Ncy7rg9yHPRVgZC97Vj5bGwg0RXyWYWrhQIKxq7sIdW8CHYouinHGhjgXiW9k5ilDnhBLL3cTn1/0v/x8WgSaIv60l/5ucYrE3tg6b9N25p57aax87Ixj+WyN/e8obsnOW+vlxqbpWP1s7SGwaOKzQsgwJplFoGXxp/ZQxoiQ66TcWHnbgSM/y1+6sfJyHhJ45ujTypdGuNzxFk18MI519WWp56oyPGT4XZ8NKxC+1i63lB/vB+ERf45ajEMwyd82uPXW1INyjMWXk2jZqknYmaZzf3jkH1uVeNmYIDmyc+2jYvGy3+d3bSCQFn+ky8vKtezmc+ftjGO1Ya0189x5yTtVi6rxsvWDwOKJ389QXd1Tbj0rrwjHwhqr6nzmUarxcOQ3FOOw8hJ5FGDLnk+paz+l4yTxT2g0JfBYeRV4Y2cqLoMDuU3NWYwknu+tfuGya1vad0n8ExhxsbuFNWJ5a+blLUo3Vt3CGoRn7dPCl0Z42uMl8afFu/jZWHZLZ8Xy4voazcIaxTge6hZKhg41+pvHvBqBJP7VGDX3i4jbldyapmPlS5fcsuisvJ1xJPAsrIlinLT2zYnEwR1K4h8M2fx/UHFnUY07/JQuuXV1iG2aLkpu1SucItlbnpWpLWVJ/NoIFzy+WB7RWXnEH1NxeFV3kIE7b2GN+XnvWyf9mJyGa1KHEV7MVbic2vdJ/E5GlJVXjIP0Enk1moy9BB7Sm6ZrPZbXP6Qfs3MS4qfFryFFecwiCBBuuwOZpjtbb3w5ZvnwVR1BAkS3M47bUpmma530cU2Sm2MXGyk6Wir50+KHBDX4zJWP5bNKbksn8OKSEd7cvEq8nohAYUWRUlzLvs+UWywX7kXJ7Xtt+/wuib8PShP+hhB6sOyq70zTcWXHxLGXdTti3Lfeemuw8lFy6/NeGktvZuPQ5hpNUfawyOrQa9v390n8fZGa6HcIzrW/cePGUHpb47QSWjYRsVdg7HJb4zw1j4m8ch42CB1jsZGexR/z37HX1ZJSTeKPHcXC/yOA9v2zdNYdaGvF8iydbD33vmeLBytu/piZDYrPSkJZ/amb/k6pbC66viT+RchM+LlpOgtruPV2xqkRyxN2GXuEt11Yz2vmkUfR0thKRWEN5ccCT01C4ckYZVVaHJP4pRE98HhIrhAnSm5rxPJc2tgkg8VvyeU8BC4khY+4fqyCdO3qFCwlnpL0zovw8jVTnvcifJP4FyEzwed2t/36178+CDIFUFogCBuX9o033hisPKvfM+kNidkN24GP3SDVrMXt27eH/QNKK9mrRMb5xk49XnXsQ79P4h+K2JG/N/g0v2k6t6kyD116ZxzkNl2lvt5tumNhTc+kh5mY/vr164PVH6skxfX2EZia9MSGch+bjDxS7O74exL/DkjqfUDYxKVW03mMtVqX9ZBFY+XV2ZubZ+W1XklPKUbSk3t/LGHdpJMinLrBn/KqsU/CmGtJ4o9BbcR/kNz0E8KzXMcK8K4usPKSVkhvuq5Xsse1sZCSnnDj4h+LWVQnhjKM80z1zM13c9ax3krJfibxj0BzH2L5DaFVjMNi0fg1Bp6VV2Mvcx8VaUdc2qx/hRmXWMLTugRK81jMzGLAZ64bm4a3VzqsGztQSfyRyBlIFumiRlD9hsUSyyvK4eodK8Dnz8d6WTP/2muvDdVoXP19FNL547TwHjYepuqsPuTiw7AEZqYw7Ssw1zQmwo+dfqwxNkn8kahy2yJRc55oBNW0DYv19NNPV8nkOifX3jTdnAI9Er47/obgMFXA9NBDDxXFTKHS66+/PsT258fqjo5U+oDSN4tTQomV6GISfySKBlJm3m2iWFxFIQaV8Bpgc/MEuEZjtWTsZafj3n3OPZdQH3uNsBQOweu+++47Opbf7g/l+Oabbw536p0LH+e1j4L4vpWWxD9iJBD8G9/4xpA9lzjizikuoRC4dTW0+/n976L7cwl1nH/MM3zkPO6///7BvedBlWzCHh6ROgYKoMZ47NNfY0MuxuwbsM/xx/wmiT8Gtf/9B9Fl6MXv2xb/sth/zOmC1Kx7WPm5YtUx/T//nyAgxXm23mPg3nvvvTRfcv7/+7xHetOZr7766pD7iHPu89/Sv+EFIn5puTimn0n8Y9D7339lnWvMyUfXCK04Xla694y9axLPI7x4vlYJqynNb3/72wPpA8e5nnl/jENLLYnf0mic60sU4yg6sZf9XPPP57o16i3lhfCIbjchmXuflbbEPCGkf+GFF5pYfeia5S1ayugbwMUTnxsdrvQoia7wJ/0ROkgcsvRzzT2XujTkDnfXTIdEV+kGM9l7Mf0rr7zSBOldI0+QkqMAWmpNEb/GPPdVYLOqEj8ttagws4KMa99zI/CSdoqXJPFqhERIzyOym5Blx61gRuGZrZDDaK0tmvgGhvs8x4YMuwRBX95+++0hKcXKU0o9N6RHeLMcprIo9tIN6U3XeShTbikccr3KjWsou2NxLD8SR/SIoEzpEhEaMaFy17maPmiUj+SdWnseSHw+V7+OPa9YXi2D+JabXzqWh4+pzZdffnlYZsvKt6Qo9Y+lb9HNN7ZNEd90x5TEB4ABsrss4s01z6q+XgJPIVBLwgufQ5vxI/BIL5NdmvD6Q1kLg1566aWhkKlFzMLat5bUi/FsivhcoqmJDwjLNMXVUxKfwqFsYmvr1vIMISD7Phs3+LFwXPtaewbyzihJ3hGL32qLSsRW+9cU8QnOHKuXuIky6DUKSXYNvDhUMY4CE9a+pbh0V38v+4wCY91gh/BW09WI5WHEyqu5d9OPlguYyLDl1xYZtdqaIj6BmaO6iVAhoOSQCqsa7ikBQBICi/Asfc/738X18NLO1sU4LH2tJcdwkrGXwGsdM2GHNQeKk+bwXvdVNE0RH1C0pAUoUzcCdWu96MX5a+2SIpfAYrm+li3WvthzZxXjKL2tYeX1gydmybGkp9qGlhvFbupSfqNGQrPktTdHfMBRAHMkbAiZ2JQwl4z3hRLcU8U44vqeXXveEK/MnDxLD68alg1minEoyl5u+kH5wYTXWAOTkyU+oUL8Wq72PsBxwWnuIP8xfaG8JKMIcMSljt1jg4OH+XixPNeeVSvdYBabhBqLXpKesJHfOFsTvwYupXFuyuK7OJaWq80tnoMkBE+tt/JPCRru7BjtzS1VTSb7jPyuZY7rKSUwrDzBtjNOeGWljh3HCSsvlpf8PEbpxjGneNZPns9jjz02yMsU5zz2HM0RX7JILTfiz9Ui2Sfu59KqvhL77yOIFIf5eHu3y0K3HpdehTFlZS5awso2YrWq0ChHNfasPAWg9aAo9VEWn4dYYhfgq8aj1Pd3rTvelO+pO7LeYjuk2YdspcDYdRyDyr2NmmvWzmfbXgBFoa9iUW6q2YHYwrkxeHdd4h2fwVy/XWdYeeT3vnSDm8SdBJ6ZFYqzt8YLeu655walOLe87oPduo93NWfxAWdOmGVpwVoiNUKzSEIA8Zu+bcdxEnaslP4S3B6Fd1tg9F+4JZb3cL2lBZpigakbftxaz6bAsDclqb9yHTZTLZkM3h6LWq+bIz4wWVgWppU52xBIU3Ae+rVNhPjeIG2/rjVoNY/LqpueMw9NAXu/fa0lzg1DyU636Wblve8NN5jI3rsFGi+wt9Yc8UPIxJOm1whFC+28YJ5/30Ifj+kD3Fkt+QxWvlYtgxCIhRfKtaLYD8UNVtYhPPvss6OTv4ees/TvmyN+XCBgJfl6yu5G33t7lq+A99l6KspquhqxvPDBLAfCm97suUn0Xrt2bUh21sBqCmyaJb4YWpZ0jiq+KYBv5RxwNnMRN7Co0S9To6Y1ld1aDMVi9ugx6TNj5F4JdhLaTvDWwK3mMZslPk0qxpRNNz2WrSwC4a4ifCRTy57h3XwHosvYm97saZpuFxZietup91CZt6v/2581S3ydFGeyRrK/rcT62+D1+BrhlZbaFpxrL5Faw11lHU1rPv/8891vFMqyw0tMfwqkJ7dNE5+QIr4MMKvfo3vYknKAJ2XKTYUrBeCzGs303IsvvjgUMfU8bjAScj711FPdJvJ2jW/TxNdhc8iAlw0OV3HXheRnlyOg5JZLb+VY7fUQ6hlsiaXuoUfS6zOFSPaUbT/55JPVZjkuH7V63zZPfAPAzZLdtxFlj4JUb/iuPjL8ZKFjmo4w1248NNWXvY6V0Ectg9p79Qxz7BFRe4yaJz4AZJ7ViksUzVnDX3swSh9fbKrklvBKknJbazdemem6HivxYEMxkjWe0dgFWrUxLnH8+pJQopfrY5hnNhjixt5LYgtBsvMwLDxLqxjnbJ28E8t7PdXUk0o88/W9WXu4SXRev359syX2VJjtHMjKH3ZDfAPDelkFZdlmb4JVeRw3hyes5poff/zxoex5Ciu/Ofn6BTdfRV4vjVzBiGyZqoPd1JjNgVVXxBd7KSeV6Mt4/05x4aYqdZa1tz6cUE/ZJPUsaDL1OvW5x1ynPrLyZ2vP6Gtf+1oXfR5znbv+0w3xdd5AEW5FJ2JJCb+0/O/efdaiJrG8ktu5klEUsiq91huZgZGVdTxI4dDSWlfENzjIbzrKNAvLIuG3ZPJThATYg5s6Z1xKGdsqq3VrT34QnqKsVcDUuiLpjvgAJdzmpM2v2rWFe0nYlqYAQgGqJjPzMSfhYI/0re+Rx7orxoEZqz8nZnMqhy6JDzADJtNvPbSy0J4SSscOOMUnlpfAY/G9X6oA74slxcjKMxZz5D/27edUv+ua+EAyiN/85jeHSjGW/5Sn+hBcya1KRm5q1Ngn6S+miwy9EMgy2rN1Ei+V5LtYdUv8GGrCL07jvln6aQ751Bb0RDKKe2pW41QWisQY1npmFODF0qvESwX5/0h3T3yXYkBltRX4GOzYj5127z3u13+xPCsvPk039f+F97JXUfOhVLnWbkKXnb/1706C+EBGfjXp5rBZRPu5RdKv9UHY1b+wTjEvz6vhtsbnu/6Tn72LgNyHOnsKcwnFOGPG/WSI7+KRQhJHxv/GjRvDji+2bhb392L5g9iuI2L5SOCNGeCl/Id3pzTZ7jhn61hext5n2XYjcFLEd4mII+5n/WMNtZViiktaj/31PZJRj6yLlLirKby7BXf7UySHFdIrYArluf2bfP1eBE6O+NuXRwGwmqb91JBL/Fnd16ICYOHlKQiwYhzvs12NgDGWvOPec+2z7YfASROf5vcwnSPBg1Q277SCzI4+asvntKjCDwSXk/CwDFQ/CXO2qxGAH6wsozXG2fZH4KSJvw0DF5rlZxVs7MHy8wLi/nahJGrlAhw/ju1ZPCpLTxlJ3Injk/DbI7b/a7jBFMbZ9kNgMcQHB8GgAMT/LGvssiIBGMtJJQJrJAN5Fh7OjfCy9ax9kD2Fdj+BzV+VQWBRxA/IkMwDERFPIk0lnN18rfjzbAcZoYCH++exKGGx4zi7nuPYFIwHcrPuXFHWncKJ38TzruPkZ4lATQQWSfxtQCPGpwBMA3qw+Gr/LTGlACw8sfIs7op7kVsZRPeM7Nx3RFd0E+fZPne+TgTmQmDxxN8FPEss7vbQEB3prwoDKA+PbZI71j6ewq5+5GeJQC0Ekvg7kEXW7eY9Kz62nT/e2OPk/xKBUghkaVMpJPM4iUBHCCTxOxqs7GoiUAqBJH4pJPM4iUBHCCTxOxqs7OrFCGQe5WJsdn2TxN+FSn7WDQIIb+o022EIJPEPwyt/3RgCUSDVWLea704Sv/khyg5ehoB1F+nmX4bQ7u+S+LtxyU87QEChlK21tgumOuh2E11M4jcxDNmJQxFQRWntgxLrbIcjkMQ/HLP8RwMI2HXnbL3FVix6aqBLXXUhid/VcGVnAwFLm+1UZG1EtsMRSOIfjln+Y2YEbKZiF91YRDVzd7o8fRK/y2FbbqeR/fr168NmJpnUGy8H45ecjT9n/jMROBgBS5ttnWbnZPdOyCm8gyF8zx+S+O+BI9+0iIA43lZlbnhp3j4t/fGjlMQ/HsM8QkUE7FH46KOPDlaem5+WvgzYSfwyOOZRCiKA3Fx7N8dg5T0rzU1LXw7kJH45LPNIhRCw25EboLL0NilNwhcCduswSfwtMPLlvAgguLsJPfPMM5s5+nTt64xJEr8OrnnUAxDg1lta63ZnboXljkKUQJL+ABAP/GkS/0DA8udlEUBu9fbuf/fggw9mCW5ZeC88WhL/Qmjyi5oIsPJRb68Kj5U/Zifjmn09xWMn8U9xVDu4JmW3TzzxxHAHIzceyQTetIOWxJ8W78WfjVV3z8K4l73inIzlpxeLJP70mJ/kGZEXqS9aLed7Vl4cL4GXC2zmFYMk/rz4n9TZ1dIrqb158+ZwXchuwwwKwTJasbznjOXnH/Yk/vxjcDI9MCV37dq1werfvn17uOmopJ27EbP0LH669m0M913r7Op/2+hK9uIUEHBzUXcYdrdh1l7m3i45EngZy7cxwutxuCuJ38ZYZC8SgckQwPvciGMyuPNEiUA7CCTx2xmL7EkiMBkCSfzJoM4TJQLtIJDEb2cssieJwGQIJPEngzpPlAi0g0ASv52xyJ4kApMhkMSfDOo8USLQDgJJ/HbGInuSCEyGQBJ/MqjzRIlAOwgk8dsZi+xJIjAZAkn8yaDOEyUC7SCQxG9nLLInicBkCCTxJ4M6T5QItINAEr+dscieJAKTIZDEnwzqPFEi0A4CSfx2xiJ7kghMhkASfzKo80SJQDsIJPHbGYvsSSIwGQJJ/MmgzhMlAu0gkMRvZyyyJ4nAZAgk8SeDOk+UCLSDQBK/nbHIniQCkyGQxJ8M6jxRItAOAkn8dsYie5IITIZAEn8yqPNEiUAikAgkAonAjAj8H+4FyMWonSP/AAAAAElFTkSuQmCC", + "document_status_id": 2 + } ] \ No newline at end of file diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/identities.test.json b/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/identities.test.json index 3ee01de950..be40a1f939 100644 --- a/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/identities.test.json +++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/identities.test.json @@ -150,5 +150,13 @@ "user_status_id": 1, "user_entity_id": null, "identity_type_id": 1 + }, + { + "id": "38c92162-6328-40ce-80f3-22e3f3e9b94d", + "date_created": "2022-06-01 18:01:33.439000 +00:00", + "company_id": "729e0af2-6723-4a7f-85a1-833d84b39bdf", + "user_status_id": 2, + "user_entity_id": null, + "identity_type_id": 2 } ] diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/offer_assigned_documents.test.json b/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/offer_assigned_documents.test.json index 3d5b391b2d..816c23c287 100644 --- a/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/offer_assigned_documents.test.json +++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/offer_assigned_documents.test.json @@ -5,7 +5,7 @@ }, { "offer_id": "ac1cf001-7fbc-1f2f-817f-bce0572c0007", - "document_id": "e020787d-1e04-4c0b-9c06-bd1cd44724b2" + "document_id": "d9926bd9-bce0-4605-a083-7066ffe5147c" }, { "offer_id": "ac1cf001-7fbc-1f2f-817f-bce0000c0001", @@ -14,5 +14,21 @@ { "offer_id": "ac1cf001-7fbc-1f2f-817f-bce0000c0001", "document_id": "3291cae8-3c7b-4862-8cec-93ea0dc8c61e" + }, + { + "offer_id": "ac1cf001-7fbc-1f2f-817f-bce0572c0007", + "document_id": "0d68c68c-d689-474c-a3be-8493f99feab2" + }, + { + "offer_id": "ac1cf001-7fbc-1f2f-817f-bce0572c0007", + "document_id": "e020787d-1e04-4c0b-9c06-bd1cd44724b2" + }, + { + "offer_id": "ac1cf001-7fbc-1f2f-817f-bce0572c0007", + "document_id": "3291cae8-3c7b-4862-8cec-93ea0dc8c61e" + }, + { + "offer_id": "ac1cf001-7fbc-1f2f-817f-bce0572c0007", + "document_id": "aaf53459-c36b-408e-a805-0b406ce9751e" } ] \ No newline at end of file diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/offer_subscriptions.test.json b/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/offer_subscriptions.test.json index f2b633e8f3..506ac513b2 100644 --- a/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/offer_subscriptions.test.json +++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/offer_subscriptions.test.json @@ -17,7 +17,8 @@ "id": "3DE6A31F-A5D1-4F60-AA3A-4B1A769BECBF", "last_editor_id": null, "display_name": null, - "description": null + "description": null, + "process_id": "0cc208c3-bdf6-456c-af81-6c3ebe14fe09" }, { "company_id": "2dc4249f-b5ca-4d42-bef1-7a7a950a4f87", @@ -27,7 +28,8 @@ "id": "ed4de48d-fd4b-4384-a72f-ecae3c6cc5ba", "last_editor_id": null, "display_name": null, - "description": null + "description": null, + "date_created": "2022-03-24 18:01:33.394000 +00:00" }, { "company_id": "2dc4249f-b5ca-4d42-bef1-7a7a950a4f87", @@ -37,7 +39,8 @@ "id": "e80b5f5c-3a16-480b-b82e-1cc06a71fddc", "last_editor_id": null, "display_name": null, - "description": null + "description": null, + "process_id": "0cc208c3-bdf6-456c-af81-6c3ebe14fe10" }, { "company_id": "2dc4249f-b5ca-4d42-bef1-7a7a950a4f87", @@ -48,7 +51,8 @@ "last_editor_id": null, "display_name": null, "description": null, - "process_id": "0cc208c3-bdf6-456c-af81-6c3ebe14fe06" + "process_id": "0cc208c3-bdf6-456c-af81-6c3ebe14fe06", + "date_created": "2022-03-28 18:01:33.394000 +00:00" }, { "company_id": "ac861325-bc54-4583-bcdc-9e9f2a38ff84", @@ -58,7 +62,8 @@ "id": "81a8211d-6261-4969-8123-a420364ae997", "last_editor_id": null, "display_name": null, - "description": null + "description": null, + "process_id": "0cc208c3-bdf6-456c-af81-6c3ebe14fe11" }, { "company_id": "ac861325-bc54-4583-bcdc-9e9f2a38ff84", @@ -68,7 +73,8 @@ "id": "783eb74f-0fe4-4652-a97e-913141539cf3", "last_editor_id": null, "display_name": null, - "description": null + "description": null, + "process_id": "0cc208c3-bdf6-456c-af81-6c3ebe14fe12" }, { "company_id": "ac861325-bc54-4583-bcdc-9e9f2a38ff84", @@ -78,7 +84,8 @@ "id": "d395798b-07df-48b6-8e18-fb0f1f23c3ca", "last_editor_id": null, "display_name": null, - "description": null + "description": null, + "process_id": "0cc208c3-bdf6-456c-af81-6c3ebe14fe13" }, { "company_id": "41fd2ab8-71cd-4546-9bef-a388d91b2542", diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/process_steps.test.json b/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/process_steps.test.json index ae0ce08611..c6f3f5def1 100644 --- a/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/process_steps.test.json +++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/process_steps.test.json @@ -150,5 +150,69 @@ "process_id": "0cc208c3-bdf6-456c-af81-6c3ebe14fe07", "date_created": "2023-02-21 08:15:20.479000 +00:00", "date_last_changed": null + }, + { + "id": "72616420-72a0-42cc-bbdd-0b1a95f68069", + "process_step_type_id": 102, + "process_step_status_id": 1, + "process_id": "0cc208c3-bdf6-456c-af81-6c3ebe14fe10", + "date_created": "2023-10-10 08:15:20.479000 +00:00", + "date_last_changed": null + }, + { + "id": "72616420-72a0-42cc-bbdd-0b1a95f68070", + "process_step_type_id": 103, + "process_step_status_id": 1, + "process_id": "0cc208c3-bdf6-456c-af81-6c3ebe14fe10", + "date_created": "2023-10-11 08:15:20.479000 +00:00", + "date_last_changed": null + }, + { + "id": "72616420-72a0-42cc-bbdd-0b1a95f68071", + "process_step_type_id": 101, + "process_step_status_id": 1, + "process_id": "0cc208c3-bdf6-456c-af81-6c3ebe14fe09", + "date_created": "2023-02-21 08:15:20.479000 +00:00", + "date_last_changed": null + }, + { + "id": "72616420-72a0-42cc-bbdd-0b1a95f68072", + "process_step_type_id": 102, + "process_step_status_id": 1, + "process_id": "0cc208c3-bdf6-456c-af81-6c3ebe14fe09", + "date_created": "2023-10-10 08:15:20.479000 +00:00", + "date_last_changed": null + }, + { + "id": "72616420-72a0-42cc-bbdd-0b1a95f68073", + "process_step_type_id": 105, + "process_step_status_id": 1, + "process_id": "0cc208c3-bdf6-456c-af81-6c3ebe14fe09", + "date_created": "2023-10-11 08:15:20.479000 +00:00", + "date_last_changed": null + }, + { + "id": "72616420-72a0-42cc-bbdd-0b1a95f68074", + "process_step_type_id": 106, + "process_step_status_id": 1, + "process_id": "0cc208c3-bdf6-456c-af81-6c3ebe14fe11", + "date_created": "2023-10-11 08:15:20.479000 +00:00", + "date_last_changed": null + }, + { + "id": "72616420-72a0-42cc-bbdd-0b1a95f68075", + "process_step_type_id": 107, + "process_step_status_id": 1, + "process_id": "0cc208c3-bdf6-456c-af81-6c3ebe14fe12", + "date_created": "2023-10-11 08:15:20.479000 +00:00", + "date_last_changed": null + }, + { + "id": "72616420-72a0-42cc-bbdd-0b1a95f68076", + "process_step_type_id": 101, + "process_step_status_id": 1, + "process_id": "0cc208c3-bdf6-456c-af81-6c3ebe14fe13", + "date_created": "2023-10-11 08:15:20.479000 +00:00", + "date_last_changed": null } ] diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/processes.test.json b/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/processes.test.json index f4ffcf21fe..11c96797bd 100644 --- a/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/processes.test.json +++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/processes.test.json @@ -34,5 +34,35 @@ "process_type_id" : 1, "lock_expiry_date" : "2023-03-01 00:00:00.000000 +00:00", "version" : "deadbeef-dead-beef-dead-beefdeadbeef" + }, + { + "id": "0cc208c3-bdf6-456c-af81-6c3ebe14fe09", + "process_type_id" : 3, + "lock_expiry_date" : "2023-10-10 00:00:00.000000 +00:00", + "version" : "deadbeef-dead-beef-dead-beefdeadbeef" + }, + { + "id": "0cc208c3-bdf6-456c-af81-6c3ebe14fe10", + "process_type_id" : 3, + "lock_expiry_date" : "2023-10-10 00:00:00.000000 +00:00", + "version" : "deadbeef-dead-beef-dead-beefdeadbeef" + }, + { + "id": "0cc208c3-bdf6-456c-af81-6c3ebe14fe11", + "process_type_id" : 3, + "lock_expiry_date" : "2023-10-10 00:00:00.000000 +00:00", + "version" : "deadbeef-dead-beef-dead-beefdeadbeef" + }, + { + "id": "0cc208c3-bdf6-456c-af81-6c3ebe14fe12", + "process_type_id" : 3, + "lock_expiry_date" : "2023-10-10 00:00:00.000000 +00:00", + "version" : "deadbeef-dead-beef-dead-beefdeadbeef" + }, + { + "id": "0cc208c3-bdf6-456c-af81-6c3ebe14fe13", + "process_type_id" : 3, + "lock_expiry_date" : "2023-10-10 00:00:00.000000 +00:00", + "version" : "deadbeef-dead-beef-dead-beefdeadbeef" } ] diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/UserRepositoryTests.cs b/tests/portalbackend/PortalBackend.DBAccess.Tests/UserRepositoryTests.cs index a2c2a32573..34b3650c0d 100644 --- a/tests/portalbackend/PortalBackend.DBAccess.Tests/UserRepositoryTests.cs +++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/UserRepositoryTests.cs @@ -432,6 +432,26 @@ public async Task GetUserAssignedIdentityProviderForNetworkRegistration_ReturnsE #endregion + #region GetNextServiceAccountsWithoutUserEntityId + + [Fact] + public async Task GetNextServiceAccountsWithoutUserEntityId_ReturnsExpectedResult() + { + // Arrange + var sut = await CreateSut().ConfigureAwait(false); + + // Act + var results = await sut.GetNextServiceAccountsWithoutUserEntityId().ToListAsync().ConfigureAwait(false); + + // Assert + results.Should().HaveCount(2) + .And.Satisfy( + x => x.ClientClientId == "sa-x-2" && x.ServiceAccountId == new Guid("93eecd4e-ca47-4dd2-85bf-775ea72eb009"), + x => x.ClientClientId == "sa-x-1" && x.ServiceAccountId == new Guid("d0c8ae19-d4f3-49cc-9cb4-6c766d4680f4")); + } + + #endregion + private async Task<(UserRepository sut, PortalDbContext context)> CreateSutWithContext() { var context = await _dbTestDbFixture.GetPortalDbContext().ConfigureAwait(false); diff --git a/tests/processes/NetworkRegistration.Library.Tests/NetworkRegistrationHandlerTests.cs b/tests/processes/NetworkRegistration.Library.Tests/NetworkRegistrationHandlerTests.cs index 93fe9a3710..6d7b38c446 100644 --- a/tests/processes/NetworkRegistration.Library.Tests/NetworkRegistrationHandlerTests.cs +++ b/tests/processes/NetworkRegistration.Library.Tests/NetworkRegistrationHandlerTests.cs @@ -21,6 +21,7 @@ using Microsoft.Extensions.Options; using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Configuration; +using Org.Eclipse.TractusX.Portal.Backend.Mailing.SendMail; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; @@ -42,28 +43,47 @@ public class NetworkRegistrationHandlerTests private readonly IProvisioningManager _provisioningManger; private readonly IUserRepository _userRepository; + private readonly INetworkRepository _networkRepository; private readonly NetworkRegistrationHandler _sut; - private readonly NetworkRegistrationProcessSettings _settings; + private readonly IMailingService _mailingService; public NetworkRegistrationHandlerTests() { var portalRepositories = A.Fake(); _userRepository = A.Fake(); + _networkRepository = A.Fake(); _userProvisioningService = A.Fake(); _provisioningManger = A.Fake(); + _mailingService = A.Fake(); - _settings = new NetworkRegistrationProcessSettings + var settings = new NetworkRegistrationProcessSettings { InitialRoles = Enumerable.Repeat(new UserRoleConfig("cl1", Enumerable.Repeat("Company Admin", 1)), 1) }; var options = A.Fake>(); - A.CallTo(() => options.Value).Returns(_settings); + A.CallTo(() => options.Value).Returns(settings); A.CallTo(() => portalRepositories.GetInstance()).Returns(_userRepository); + A.CallTo(() => portalRepositories.GetInstance()).Returns(_networkRepository); - _sut = new NetworkRegistrationHandler(portalRepositories, _userProvisioningService, _provisioningManger, options); + _sut = new NetworkRegistrationHandler(portalRepositories, _userProvisioningService, _provisioningManger, _mailingService, options); + } + + [Fact] + public async Task SynchronizeUser_WithoutOspName_ThrowsUnexpectedConditionException() + { + // Arrange + A.CallTo(() => _networkRepository.GetOspCompanyName(NetworkRegistrationId)) + .Returns((string?)null); + + // Act + async Task Act() => await _sut.SynchronizeUser(NetworkRegistrationId).ConfigureAwait(false); + + // Assert + var ex = await Assert.ThrowsAsync(Act); + ex.Message.Should().Be("Onboarding Service Provider name must be set"); } [Theory] @@ -78,6 +98,8 @@ public async Task SynchronizeUser_WithUserDataNull_ThrowsConflictException(strin "123456789", "Test Company", "BPNL00000001TEST", Enumerable.Repeat(new ProviderLinkData("ironman", "idp1", "id1234"), 1)); + A.CallTo(() => _networkRepository.GetOspCompanyName(NetworkRegistrationId)) + .Returns("Onboarding Service Provider"); A.CallTo(() => _userRepository.GetUserAssignedIdentityProviderForNetworkRegistration(NetworkRegistrationId)) .Returns(new[] { @@ -102,10 +124,12 @@ public async Task SynchronizeUser_WithAliasNull_ThrowsConflictException() var user1 = new CompanyUserIdentityProviderProcessData(user1Id, "tony", "stark", "tony@stark.com", "123456789", "Test Company", "BPNL00000001TEST", Enumerable.Repeat(new ProviderLinkData("ironman", null, "id1234"), 1)); + A.CallTo(() => _networkRepository.GetOspCompanyName(NetworkRegistrationId)) + .Returns("Onboarding Service Provider"); A.CallTo(() => _userRepository.GetUserAssignedIdentityProviderForNetworkRegistration(NetworkRegistrationId)) .Returns(new[] { - user1, + user1 }.ToAsyncEnumerable()); A.CallTo(() => _userProvisioningService.GetRoleDatas(A>._)) .Returns(Enumerable.Repeat(new UserRoleData(UserRoleIds, "cl1", "Company Admin"), 1).ToAsyncEnumerable()); @@ -123,7 +147,6 @@ public async Task SynchronizeUser_WithValidData_ReturnsExpected() { // Arrange var user1Id = Guid.NewGuid().ToString(); - var user2Id = Guid.NewGuid().ToString(); var user1 = new CompanyUserIdentityProviderProcessData(Guid.NewGuid(), "tony", "stark", "tony@stark.com", "123456789", "Test Company", "BPNL00000001TEST", Enumerable.Repeat(new ProviderLinkData("ironman", "idp1", "id1234"), 1)); @@ -131,14 +154,14 @@ public async Task SynchronizeUser_WithValidData_ReturnsExpected() "steven@strange.com", "987654321", "Test Company", "BPNL00000001TEST", Enumerable.Repeat(new ProviderLinkData("drstrange", "idp1", "id9876"), 1)); + A.CallTo(() => _networkRepository.GetOspCompanyName(NetworkRegistrationId)) + .Returns("Onboarding Service Provider"); A.CallTo(() => _userRepository.GetUserAssignedIdentityProviderForNetworkRegistration(NetworkRegistrationId)) .Returns(new[] { user1, user2 }.ToAsyncEnumerable()); - A.CallTo(() => _userProvisioningService.CreateCentralUserWithProviderLinks(user2.CompanyUserId, A._, A._, A._, A>._)) - .Returns(user2Id); A.CallTo(() => _userProvisioningService.GetRoleDatas(A>._)) .Returns(Enumerable.Repeat(new UserRoleData(UserRoleIds, "cl1", "Company Admin"), 1).ToAsyncEnumerable()); A.CallTo(() => _provisioningManger.GetUserByUserName(user1.CompanyUserId.ToString())).Returns(user1Id); @@ -148,12 +171,19 @@ public async Task SynchronizeUser_WithValidData_ReturnsExpected() var result = await _sut.SynchronizeUser(NetworkRegistrationId).ConfigureAwait(false); // Assert - A.CallTo(() => _userProvisioningService.CreateCentralUserWithProviderLinks(user2.CompanyUserId, A._, A._, A._, A>._)) + A.CallTo(() => _userProvisioningService.HandleCentralKeycloakCreation(A._, user1.CompanyUserId, A._, A._, null, A>._, A._, A._)) + .MustNotHaveHappened(); + A.CallTo(() => _userProvisioningService.HandleCentralKeycloakCreation(A._, user2.CompanyUserId, A._, A._, null, A>._, A._, A._)) .MustHaveHappenedOnceExactly(); A.CallTo(() => _userRepository.AttachAndModifyIdentity(user1.CompanyUserId, A>._, A>._)) .MustHaveHappenedOnceExactly(); A.CallTo(() => _userRepository.AttachAndModifyIdentity(user2.CompanyUserId, A>._, A>._)) + .MustNotHaveHappened(); + A.CallTo(() => _mailingService.SendMails("tony@stark.com", A>._, A>._)) + .MustHaveHappenedOnceExactly(); + A.CallTo(() => _mailingService.SendMails("steven@strange.com", A>._, A>._)) .MustHaveHappenedOnceExactly(); + result.modified.Should().BeFalse(); result.processMessage.Should().BeNull(); result.stepStatusId.Should().Be(ProcessStepStatusId.DONE); diff --git a/tests/processes/ServiceAccountSync.Executor.Tests/ServiceAccountSync.Executor.Tests.csproj b/tests/processes/ServiceAccountSync.Executor.Tests/ServiceAccountSync.Executor.Tests.csproj new file mode 100644 index 0000000000..bc5fb1dbc9 --- /dev/null +++ b/tests/processes/ServiceAccountSync.Executor.Tests/ServiceAccountSync.Executor.Tests.csproj @@ -0,0 +1,49 @@ + + + + + net7.0 + enable + enable + false + Org.Eclipse.TractusX.Portal.Backend.ServiceAccountSync.Executor.Tests + Org.Eclipse.TractusX.Portal.Backend.ServiceAccountSync.Executor.Tests + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + diff --git a/tests/processes/ServiceAccountSync.Executor.Tests/ServiceAccountSyncProcessTypeExecutorTests.cs b/tests/processes/ServiceAccountSync.Executor.Tests/ServiceAccountSyncProcessTypeExecutorTests.cs new file mode 100644 index 0000000000..9a0aedb986 --- /dev/null +++ b/tests/processes/ServiceAccountSync.Executor.Tests/ServiceAccountSyncProcessTypeExecutorTests.cs @@ -0,0 +1,307 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 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; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; +using Org.Eclipse.TractusX.Portal.Backend.Processes.ServiceACcountSync.Executor; +using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library; + +namespace Org.Eclipse.TractusX.Portal.Backend.ServiceAccountSync.Executor.Tests; + +public class ServiceAccountSyncProcessTypeExecutorTests +{ + private readonly IUserRepository _userRepository; + private readonly IProvisioningManager _provisioningManager; + private readonly IFixture _fixture; + private readonly ServiceAccountSyncProcessTypeExecutor _executor; + + public ServiceAccountSyncProcessTypeExecutorTests() + { + _fixture = new Fixture().Customize(new AutoFakeItEasyCustomization { ConfigureMembers = true }); + _fixture.Behaviors.OfType().ToList() + .ForEach(b => _fixture.Behaviors.Remove(b)); + _fixture.Behaviors.Add(new OmitOnRecursionBehavior()); + + var portalRepositories = A.Fake(); + _provisioningManager = A.Fake(); + _userRepository = A.Fake(); + + A.CallTo(() => portalRepositories.GetInstance()) + .Returns(_userRepository); + + _executor = new ServiceAccountSyncProcessTypeExecutor(portalRepositories, _provisioningManager); + } + + #region InitializeProcess + + [Fact] + public async Task InitializeProcess_ValidProcessId_ReturnsExpected() + { + // Arrange + var result = await _executor.InitializeProcess(Guid.NewGuid(), _fixture.CreateMany()).ConfigureAwait(false); + + // Assert + result.Modified.Should().BeFalse(); + result.ScheduleStepTypeIds.Should().BeNull(); + } + + #endregion + + #region ExecuteProcessStep + + [Fact] + public async Task ExecuteProcessStep_WithUnrecoverableServiceException_Throws() + { + // Arrange + const ProcessStepTypeId processStepTypeId = ProcessStepTypeId.SYNCHRONIZE_SERVICE_ACCOUNTS; + var processStepTypeIds = _fixture.CreateMany(); + A.CallTo(() => _provisioningManager.GetServiceAccountUserId(A._)) + .ThrowsAsync(new ServiceException("test")); + A.CallTo(() => _userRepository.GetNextServiceAccountsWithoutUserEntityId()) + .Returns(Enumerable.Repeat(new ValueTuple(Guid.NewGuid(), "sa1"), 1).ToAsyncEnumerable()); + + // Act + var result = await _executor.ExecuteProcessStep(processStepTypeId, processStepTypeIds, CancellationToken.None).ConfigureAwait(false); + + // Assert + result.Modified.Should().BeTrue(); + result.ProcessStepStatusId.Should().Be(ProcessStepStatusId.FAILED); + result.ProcessMessage.Should().Be("test"); + } + + [Fact] + public async Task ExecuteProcessStep_WithConflictException_Throws() + { + // Arrange + const ProcessStepTypeId processStepTypeId = ProcessStepTypeId.SYNCHRONIZE_SERVICE_ACCOUNTS; + var processStepTypeIds = _fixture.CreateMany(); + A.CallTo(() => _provisioningManager.GetServiceAccountUserId(A._)) + .ThrowsAsync(new ConflictException("test")); + A.CallTo(() => _userRepository.GetNextServiceAccountsWithoutUserEntityId()) + .Returns(Enumerable.Repeat(new ValueTuple(Guid.NewGuid(), "sa1"), 1).ToAsyncEnumerable()); + + // Act + var result = await _executor.ExecuteProcessStep(processStepTypeId, processStepTypeIds, CancellationToken.None).ConfigureAwait(false); + + // Assert + result.Modified.Should().BeTrue(); + result.ProcessStepStatusId.Should().Be(ProcessStepStatusId.FAILED); + result.ProcessMessage.Should().Be("test"); + } + + [Fact] + public async Task ExecuteProcessStep_WithRecoverableServiceException_Throws() + { + // Arrange + const ProcessStepTypeId processStepTypeId = ProcessStepTypeId.SYNCHRONIZE_SERVICE_ACCOUNTS; + var processStepTypeIds = _fixture.CreateMany(); + A.CallTo(() => _provisioningManager.GetServiceAccountUserId(A._)) + .ThrowsAsync(new ServiceException("test", true)); + A.CallTo(() => _userRepository.GetNextServiceAccountsWithoutUserEntityId()) + .Returns(Enumerable.Repeat(new ValueTuple(Guid.NewGuid(), "sa1"), 1).ToAsyncEnumerable()); + + // Act + var result = await _executor.ExecuteProcessStep(processStepTypeId, processStepTypeIds, CancellationToken.None).ConfigureAwait(false); + + // Assert + result.Modified.Should().BeTrue(); + result.ProcessStepStatusId.Should().Be(ProcessStepStatusId.TODO); + } + + [Fact] + public async Task ExecuteProcessStep_WithNoIdentity_ExecutesExpected() + { + // Arrange + var identity = new Identity(Guid.NewGuid(), DateTimeOffset.Now, Guid.NewGuid(), UserStatusId.ACTIVE, IdentityTypeId.COMPANY_SERVICE_ACCOUNT); + var userEntityId = Guid.NewGuid().ToString(); + A.CallTo(() => _userRepository.GetNextServiceAccountsWithoutUserEntityId()) + .Returns(Enumerable.Empty<(Guid, string)>().ToAsyncEnumerable()); + + // Act + var result = await _executor.ExecuteProcessStep(ProcessStepTypeId.SYNCHRONIZE_SERVICE_ACCOUNTS, new[] { ProcessStepTypeId.SYNCHRONIZE_SERVICE_ACCOUNTS }, CancellationToken.None).ConfigureAwait(false); + + // Assert + result.Modified.Should().BeFalse(); + result.ScheduleStepTypeIds.Should().BeNull(); + result.ProcessStepStatusId.Should().Be(ProcessStepStatusId.DONE); + result.ProcessMessage.Should().Be("no serviceAccounts to synchronize found"); + + A.CallTo(() => _userRepository.GetNextServiceAccountsWithoutUserEntityId()) + .MustHaveHappenedOnceExactly(); + A.CallTo(() => _provisioningManager.GetServiceAccountUserId(A._)) + .MustNotHaveHappened(); + A.CallTo(() => _userRepository.AttachAndModifyIdentity(A._, A>._, A>._)) + .MustNotHaveHappened(); + } + + [Fact] + public async Task ExecuteProcessStep_WithSingleIdentity_ExecutesExpected() + { + // Arrange + var identity = new Identity(Guid.NewGuid(), DateTimeOffset.Now, Guid.NewGuid(), UserStatusId.ACTIVE, IdentityTypeId.COMPANY_SERVICE_ACCOUNT); + var userEntityId = Guid.NewGuid().ToString(); + A.CallTo(() => _userRepository.GetNextServiceAccountsWithoutUserEntityId()) + .Returns(new[] + { + (identity.Id, "sa1"), + }.ToAsyncEnumerable()); + A.CallTo(() => _provisioningManager.GetServiceAccountUserId(A._)) + .Returns(userEntityId); + A.CallTo(() => _userRepository.AttachAndModifyIdentity(A._, A>._, A>._)) + .Invokes((Guid id, Action? initialize, Action setOptionalFields) => + { + initialize?.Invoke(identity); + setOptionalFields.Invoke(identity); + }); + + // Act + var result = await _executor.ExecuteProcessStep(ProcessStepTypeId.SYNCHRONIZE_SERVICE_ACCOUNTS, new[] { ProcessStepTypeId.SYNCHRONIZE_SERVICE_ACCOUNTS }, CancellationToken.None).ConfigureAwait(false); + + // Assert + result.Modified.Should().BeTrue(); + result.ScheduleStepTypeIds.Should().BeNull(); + result.ProcessStepStatusId.Should().Be(ProcessStepStatusId.DONE); + result.ProcessMessage.Should().Be($"synchronized serviceAccountId {identity.Id}, clientClientId sa1 with userEntityId {userEntityId}"); + identity.UserEntityId.Should().Be(userEntityId); + + A.CallTo(() => _userRepository.GetNextServiceAccountsWithoutUserEntityId()) + .MustHaveHappenedOnceExactly(); + A.CallTo(() => _provisioningManager.GetServiceAccountUserId("sa1")) + .MustHaveHappenedOnceExactly(); + A.CallTo(() => _userRepository.AttachAndModifyIdentity(identity.Id, A>._, A>._)) + .MustHaveHappenedOnceExactly(); + } + + [Fact] + public async Task ExecuteProcessStep_WithMultipleIdentities_ExecutesExpected() + { + // Arrange + var identity = new Identity(Guid.NewGuid(), DateTimeOffset.Now, Guid.NewGuid(), UserStatusId.ACTIVE, IdentityTypeId.COMPANY_SERVICE_ACCOUNT); + var userEntityId = Guid.NewGuid().ToString(); + var identity2Id = Guid.NewGuid(); + A.CallTo(() => _userRepository.GetNextServiceAccountsWithoutUserEntityId()) + .Returns(new[] + { + (identity.Id, "sa1"), + (identity2Id, "sa2") + }.ToAsyncEnumerable()); + A.CallTo(() => _provisioningManager.GetServiceAccountUserId(A._)) + .Returns(userEntityId); + A.CallTo(() => _userRepository.AttachAndModifyIdentity(A._, A>._, A>._)) + .Invokes((Guid id, Action? initialize, Action setOptionalFields) => + { + initialize?.Invoke(identity); + setOptionalFields.Invoke(identity); + }); + + // Act + var result = await _executor.ExecuteProcessStep(ProcessStepTypeId.SYNCHRONIZE_SERVICE_ACCOUNTS, new[] { ProcessStepTypeId.SYNCHRONIZE_SERVICE_ACCOUNTS }, CancellationToken.None).ConfigureAwait(false); + + // Assert + result.Modified.Should().BeTrue(); + result.ScheduleStepTypeIds.Should().ContainSingle(x => x == ProcessStepTypeId.SYNCHRONIZE_SERVICE_ACCOUNTS); + result.ProcessStepStatusId.Should().Be(ProcessStepStatusId.DONE); + result.ProcessMessage.Should().Be($"synchronized serviceAccountId {identity.Id}, clientClientId sa1 with userEntityId {userEntityId}"); + identity.UserEntityId.Should().Be(userEntityId); + + A.CallTo(() => _userRepository.GetNextServiceAccountsWithoutUserEntityId()) + .MustHaveHappenedOnceExactly(); + A.CallTo(() => _provisioningManager.GetServiceAccountUserId("sa1")) + .MustHaveHappenedOnceExactly(); + A.CallTo(() => _provisioningManager.GetServiceAccountUserId("sa2")) + .MustNotHaveHappened(); + A.CallTo(() => _userRepository.AttachAndModifyIdentity(identity.Id, A>._, A>._)) + .MustHaveHappenedOnceExactly(); + A.CallTo(() => _userRepository.AttachAndModifyIdentity(identity2Id, A>._, A>._)) + .MustNotHaveHappened(); + } + + #endregion + + #region GetProcessTypeId + + [Fact] + public void GetProcessTypeId_ReturnsExpected() + { + // Act + var result = _executor.GetProcessTypeId(); + + // Assert + result.Should().Be(ProcessTypeId.SERVICE_ACCOUNT_SYNC); + } + + #endregion + + #region GetProcessTypeId + + [Fact] + public async Task IsLockRequested_ReturnsExpected() + { + // Act + var result = await _executor.IsLockRequested(_fixture.Create()).ConfigureAwait(false); + + // Assert + result.Should().BeFalse(); + } + + #endregion + + #region IsExecutableStepTypeId + + [Theory] + [InlineData(ProcessStepTypeId.SYNCHRONIZE_SERVICE_ACCOUNTS, true)] + [InlineData(ProcessStepTypeId.OFFERSUBSCRIPTION_CLIENT_CREATION, false)] + [InlineData(ProcessStepTypeId.OFFERSUBSCRIPTION_TECHNICALUSER_CREATION, false)] + [InlineData(ProcessStepTypeId.ACTIVATE_SUBSCRIPTION, false)] + [InlineData(ProcessStepTypeId.TRIGGER_PROVIDER_CALLBACK, false)] + [InlineData(ProcessStepTypeId.SINGLE_INSTANCE_SUBSCRIPTION_DETAILS_CREATION, false)] + [InlineData(ProcessStepTypeId.START_AUTOSETUP, false)] + [InlineData(ProcessStepTypeId.END_CLEARING_HOUSE, false)] + [InlineData(ProcessStepTypeId.START_CLEARING_HOUSE, false)] + [InlineData(ProcessStepTypeId.DECLINE_APPLICATION, false)] + [InlineData(ProcessStepTypeId.CREATE_IDENTITY_WALLET, false)] + [InlineData(ProcessStepTypeId.TRIGGER_ACTIVATE_SUBSCRIPTION, false)] + public void IsExecutableProcessStep_ReturnsExpected(ProcessStepTypeId processStepTypeId, bool expectedResult) + { + // Act + var result = _executor.IsExecutableStepTypeId(processStepTypeId); + + // Assert + result.Should().Be(expectedResult); + } + + #endregion + + #region GetExecutableStepTypeIds + + [Fact] + public void GetExecutableStepTypeIds_ReturnsExpected() + { + //Act + var result = _executor.GetExecutableStepTypeIds(); + + // Assert + result.Should().HaveCount(1).And.Satisfy(x => x == ProcessStepTypeId.SYNCHRONIZE_SERVICE_ACCOUNTS); + } + + #endregion +} diff --git a/tests/processes/ServiceAccountSync.Executor.Tests/Usings.cs b/tests/processes/ServiceAccountSync.Executor.Tests/Usings.cs new file mode 100644 index 0000000000..65016aec51 --- /dev/null +++ b/tests/processes/ServiceAccountSync.Executor.Tests/Usings.cs @@ -0,0 +1,24 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 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 + ********************************************************************************/ + +global using AutoFixture; +global using AutoFixture.AutoFakeItEasy; +global using FakeItEasy; +global using FluentAssertions; +global using Xunit; diff --git a/tests/provisioning/Provisioning.Library.Tests/Extensions/ClientManagerTests.cs b/tests/provisioning/Provisioning.Library.Tests/Extensions/ClientManagerTests.cs index dd75189ef7..2bd033d0e7 100644 --- a/tests/provisioning/Provisioning.Library.Tests/Extensions/ClientManagerTests.cs +++ b/tests/provisioning/Provisioning.Library.Tests/Extensions/ClientManagerTests.cs @@ -54,7 +54,7 @@ public ClientManagerTests() .Returns(new KeycloakClient(CentralUrl, "test", "test", "test", false)); A.CallTo(() => keycloakFactory.CreateKeycloakClient("shared")) .Returns(new KeycloakClient(SharedUrl, "test", "test", "test", false)); - A.CallTo(() => keycloakFactory.CreateKeycloakClient("shared", A._, A._, A._)) + A.CallTo(() => keycloakFactory.CreateKeycloakClient("shared", A._, A._)) .Returns(new KeycloakClient(SharedUrl, "test", "test", "test", false)); var settings = new ProvisioningSettings { diff --git a/tests/provisioning/Provisioning.Library.Tests/Extensions/ServiceAccountCreationTests.cs b/tests/provisioning/Provisioning.Library.Tests/Extensions/ServiceAccountCreationTests.cs index 0ec00a8fe3..da66e671e7 100644 --- a/tests/provisioning/Provisioning.Library.Tests/Extensions/ServiceAccountCreationTests.cs +++ b/tests/provisioning/Provisioning.Library.Tests/Extensions/ServiceAccountCreationTests.cs @@ -123,7 +123,7 @@ public async Task CreateServiceAccountAsync_WithValidData_ReturnsExpected() A.CallTo(() => _portalRepositories.SaveAsync()).MustNotHaveHappened(); serviceAccounts.Should().ContainSingle().Which.Name.Should().Be("testName"); serviceAccounts.Should().ContainSingle().Which.ClientId.Should().Be("internal-sa1"); - identities.Should().ContainSingle().Which.CompanyId.Should().Be(_companyId); + identities.Should().ContainSingle().And.Satisfy(x => x.CompanyId == _companyId && x.UserEntityId == _iamUserId); } [Fact] @@ -153,7 +153,7 @@ public async Task CreateServiceAccountAsync_WithNameSetAndValidData_ReturnsExpec A.CallTo(() => _portalRepositories.SaveAsync()).MustNotHaveHappened(); serviceAccounts.Should().ContainSingle().Which.Name.Should().Be("sa1-testName"); serviceAccounts.Should().ContainSingle().Which.ClientId.Should().Be("internal-sa1"); - identities.Should().ContainSingle().Which.CompanyId.Should().Be(_companyId); + identities.Should().ContainSingle().And.Satisfy(x => x.CompanyId == _companyId && x.UserEntityId == _iamUserId); } #region Setup @@ -166,10 +166,11 @@ private void Setup(ICollection? serviceAccounts = null, I A.CallTo(() => _provisioningManager.SetupCentralServiceAccountClientAsync(A._, A._, A._)) .Returns(new ServiceAccountData("internal-sa1", _iamUserId, new ClientAuthData(IamClientAuthMethod.SECRET))); - A.CallTo(() => _userRepository.CreateIdentity(_companyId, A._, IdentityTypeId.COMPANY_SERVICE_ACCOUNT)) - .Invokes((Guid companyId, UserStatusId userStatusId, IdentityTypeId identityTypeId) => + A.CallTo(() => _userRepository.CreateIdentity(_companyId, A._, IdentityTypeId.COMPANY_SERVICE_ACCOUNT, A>._)) + .Invokes((Guid companyId, UserStatusId userStatusId, IdentityTypeId identityTypeId, Action? setOptionalFields) => { var identity = new Identity(Guid.NewGuid(), DateTimeOffset.UtcNow, companyId, userStatusId, identityTypeId); + setOptionalFields?.Invoke(identity); identities?.Add(identity); }) .Returns(new Identity(_identityId, default, default, default, default)); diff --git a/tests/provisioning/Provisioning.Library.Tests/ProvisioningManagerTests.cs b/tests/provisioning/Provisioning.Library.Tests/ProvisioningManagerTests.cs index 709da2d292..161757eb78 100644 --- a/tests/provisioning/Provisioning.Library.Tests/ProvisioningManagerTests.cs +++ b/tests/provisioning/Provisioning.Library.Tests/ProvisioningManagerTests.cs @@ -59,7 +59,7 @@ public ProvisioningManagerTests() .Returns(new KeycloakClient(CentralUrl, "test", "test", "test", false)); A.CallTo(() => keycloakFactory.CreateKeycloakClient("shared")) .Returns(new KeycloakClient(SharedUrl, "test", "test", "test", false)); - A.CallTo(() => keycloakFactory.CreateKeycloakClient("shared", A._, A._, A._)) + A.CallTo(() => keycloakFactory.CreateKeycloakClient("shared", A._, A._)) .Returns(new KeycloakClient(SharedUrl, "test", "test", "test", false)); var settings = new ProvisioningSettings { diff --git a/tests/provisioning/Provisioning.Library.Tests/UserManagerTests.cs b/tests/provisioning/Provisioning.Library.Tests/UserManagerTests.cs index ec1cadf73b..22112280ac 100644 --- a/tests/provisioning/Provisioning.Library.Tests/UserManagerTests.cs +++ b/tests/provisioning/Provisioning.Library.Tests/UserManagerTests.cs @@ -58,7 +58,7 @@ public UserManagerTests() .Returns(new KeycloakClient(CentralUrl, "test", "test", "test", false)); A.CallTo(() => keycloakFactory.CreateKeycloakClient("shared")) .Returns(new KeycloakClient(SharedUrl, "test", "test", "test", false)); - A.CallTo(() => keycloakFactory.CreateKeycloakClient("shared", A._, A._, A._)) + A.CallTo(() => keycloakFactory.CreateKeycloakClient("shared", A._, A._)) .Returns(new KeycloakClient(SharedUrl, "test", "test", "test", false)); var settings = new ProvisioningSettings { diff --git a/tests/provisioning/Provisioning.Library.Tests/UserProvisioningServiceCreateUsersTests.cs b/tests/provisioning/Provisioning.Library.Tests/UserProvisioningServiceCreateUsersTests.cs index d9eec91ebf..4165afae07 100644 --- a/tests/provisioning/Provisioning.Library.Tests/UserProvisioningServiceCreateUsersTests.cs +++ b/tests/provisioning/Provisioning.Library.Tests/UserProvisioningServiceCreateUsersTests.cs @@ -257,8 +257,8 @@ public async Task TestCreateUsersNotExistingCompanyUserWithoutKeycloakUserSucces A.CallTo(() => _userRepository.GetMatchingCompanyIamUsersByNameEmail(A.That.IsEqualTo(userInfo.FirstName), A._, A._, A._, A>._)) .Returns(new[] { (UserEntityId: (string?)null, CompanyUserId: Guid.Empty) }.ToAsyncEnumerable()); - A.CallTo(() => _userRepository.CreateIdentity(A._, A._, IdentityTypeId.COMPANY_USER)) - .ReturnsLazily((Guid companyId, UserStatusId userStatusId, IdentityTypeId identityId) => new Identity(Guid.NewGuid(), DateTimeOffset.UtcNow, companyId, userStatusId, identityId) + A.CallTo(() => _userRepository.CreateIdentity(A._, A._, IdentityTypeId.COMPANY_USER, null)) + .ReturnsLazily((Guid companyId, UserStatusId userStatusId, IdentityTypeId identityId, Action _) => new Identity(Guid.NewGuid(), DateTimeOffset.UtcNow, companyId, userStatusId, identityId) { UserEntityId = centralUserId }); @@ -277,7 +277,7 @@ public async Task TestCreateUsersNotExistingCompanyUserWithoutKeycloakUserSucces A.CallTo(() => _provisioningManager.GetProviderUserLinkDataForCentralUserIdAsync(A._)).MustNotHaveHappened(); A.CallTo(() => _provisioningManager.CreateCentralUserAsync(A._, A)>>._)).MustHaveHappened(userCreationInfoIdp.Count, Times.Exactly); A.CallTo(() => _provisioningManager.CreateCentralUserAsync(A.That.Matches(u => u.FirstName == userInfo.FirstName), A)>>._)).MustHaveHappenedOnceExactly(); - A.CallTo(() => _userRepository.CreateIdentity(_companyNameIdpAliasData.CompanyId, UserStatusId.ACTIVE, IdentityTypeId.COMPANY_USER)).MustHaveHappened(userCreationInfoIdp.Count, Times.Exactly); + A.CallTo(() => _userRepository.CreateIdentity(_companyNameIdpAliasData.CompanyId, UserStatusId.ACTIVE, IdentityTypeId.COMPANY_USER, null)).MustHaveHappened(userCreationInfoIdp.Count, Times.Exactly); A.CallTo(() => _userRepository.AddCompanyUserAssignedIdentityProvider(A._, A._, A._, A._)).MustHaveHappened(userCreationInfoIdp.Count, Times.Exactly); A.CallTo(() => _userRepository.AddCompanyUserAssignedIdentityProvider(identityId, A._, A._, A._)).MustHaveHappenedOnceExactly(); A.CallTo(() => _userRepository.CreateCompanyUser(A._, A._, A._, A._)).MustHaveHappened(userCreationInfoIdp.Count, Times.Exactly); @@ -315,7 +315,7 @@ public async Task TestCreateUsersExistingCompanyUserWithoutKeycloakUserSuccess() A.CallTo(() => _provisioningManager.GetProviderUserLinkDataForCentralUserIdAsync(A._)).MustNotHaveHappened(); A.CallTo(() => _provisioningManager.CreateCentralUserAsync(A._, A)>>._)).MustHaveHappened(userCreationInfoIdp.Count, Times.Exactly); A.CallTo(() => _provisioningManager.CreateCentralUserAsync(A.That.Matches(u => u.FirstName == userInfo.FirstName), A)>>._)).MustHaveHappenedOnceExactly(); - A.CallTo(() => _userRepository.CreateIdentity(A._, UserStatusId.ACTIVE, IdentityTypeId.COMPANY_USER)).MustHaveHappened(userCreationInfoIdp.Count - 1, Times.Exactly); + A.CallTo(() => _userRepository.CreateIdentity(A._, UserStatusId.ACTIVE, IdentityTypeId.COMPANY_USER, null)).MustHaveHappened(userCreationInfoIdp.Count - 1, Times.Exactly); A.CallTo(() => _userRepository.CreateCompanyUser(A._, A._, A._, A._)).MustHaveHappened(userCreationInfoIdp.Count - 1, Times.Exactly); A.CallTo(() => _userRepository.CreateCompanyUser(A._, userInfo.FirstName, A._, A._)).MustNotHaveHappened(); A.CallTo(() => _businessPartnerRepository.CreateCompanyUserAssignedBusinessPartner(A._, _companyNameIdpAliasData.BusinessPartnerNumber!)).MustHaveHappened(userCreationInfoIdp.Count - 1, Times.Exactly); @@ -409,14 +409,18 @@ private void SetupRepositories() A.CallTo(() => _portalRepositories.GetInstance()).Returns(_businessPartnerRepository); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_userRolesRepository); - A.CallTo(() => _userRepository.CreateIdentity(A._, A._, IdentityTypeId.COMPANY_USER)) - .ReturnsLazily((Guid companyId, UserStatusId userStatusId, IdentityTypeId identityTypeId) => - new Identity( + A.CallTo(() => _userRepository.CreateIdentity(A._, A._, IdentityTypeId.COMPANY_USER, null)) + .ReturnsLazily((Guid companyId, UserStatusId userStatusId, IdentityTypeId identityTypeId, Action? setOptionalFields) => + { + var identity = new Identity( Guid.NewGuid(), DateTimeOffset.UtcNow, companyId, userStatusId, - identityTypeId)); + identityTypeId); + setOptionalFields?.Invoke(identity); + return identity; + }); A.CallTo(() => _userRepository.CreateCompanyUser(A._, A._, A._, A._)) .ReturnsLazily((Guid _, string firstName, string _, string _) => diff --git a/tests/registration/Registration.Service.Tests/BusinessLogic/NetworkBusinessLogicTests.cs b/tests/registration/Registration.Service.Tests/BusinessLogic/NetworkBusinessLogicTests.cs new file mode 100644 index 0000000000..a0e7380de3 --- /dev/null +++ b/tests/registration/Registration.Service.Tests/BusinessLogic/NetworkBusinessLogicTests.cs @@ -0,0 +1,380 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 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 AutoFixture; +using AutoFixture.AutoFakeItEasy; +using FakeItEasy; +using FluentAssertions; +using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Configuration; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities; +using Org.Eclipse.TractusX.Portal.Backend.Processes.ApplicationChecklist.Library; +using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Service; +using Org.Eclipse.TractusX.Portal.Backend.Registration.Service.BusinessLogic; +using Org.Eclipse.TractusX.Portal.Backend.Registration.Service.Model; +using Xunit; + +namespace Org.Eclipse.TractusX.Portal.Backend.Registration.Service.Tests.BusinessLogic; + +public class NetworkBusinessLogicTests +{ + private const string Bpnl = "BPNL00000001TEST"; + private static readonly Guid ExistingExternalId = Guid.NewGuid(); + private static readonly Guid UserRoleId = Guid.NewGuid(); + private static readonly Guid MultiIdpCompanyId = Guid.NewGuid(); + private static readonly Guid NoIdpCompanyId = Guid.NewGuid(); + private static readonly Guid IdpId = Guid.NewGuid(); + private static readonly Guid NoAliasIdpCompanyId = Guid.NewGuid(); + + private readonly IFixture _fixture; + + private readonly IdentityData _identity = new(Guid.NewGuid().ToString(), Guid.NewGuid(), IdentityTypeId.COMPANY_USER, Guid.NewGuid()); + private readonly IUserProvisioningService _userProvisioningService; + private readonly IApplicationChecklistCreationService _checklistService; + + private readonly IPortalRepositories _portalRepositories; + private readonly ICompanyRepository _companyRepository; + private readonly IProcessStepRepository _processStepRepository; + private readonly IApplicationRepository _applicationRepository; + private readonly INetworkRepository _networkRepository; + private readonly IIdentityProviderRepository _identityProviderRepository; + private readonly ICountryRepository _countryRepository; + private readonly NetworkBusinessLogic _sut; + private readonly IConsentRepository _consentRepository; + + public NetworkBusinessLogicTests() + { + _fixture = new Fixture().Customize(new AutoFakeItEasyCustomization { ConfigureMembers = true }); + _fixture.Behaviors.OfType().ToList() + .ForEach(b => _fixture.Behaviors.Remove(b)); + _fixture.Behaviors.Add(new OmitOnRecursionBehavior()); + + _userProvisioningService = A.Fake(); + _portalRepositories = A.Fake(); + _checklistService = A.Fake(); + + _companyRepository = A.Fake(); + _processStepRepository = A.Fake(); + _applicationRepository = A.Fake(); + _networkRepository = A.Fake(); + _identityProviderRepository = A.Fake(); + _countryRepository = A.Fake(); + _consentRepository = A.Fake(); + + var identityService = A.Fake(); + A.CallTo(() => identityService.IdentityData).Returns(_identity); + + A.CallTo(() => _portalRepositories.GetInstance()).Returns(_companyRepository); + A.CallTo(() => _portalRepositories.GetInstance()).Returns(_consentRepository); + A.CallTo(() => _portalRepositories.GetInstance()).Returns(_processStepRepository); + A.CallTo(() => _portalRepositories.GetInstance()).Returns(_applicationRepository); + A.CallTo(() => _portalRepositories.GetInstance()).Returns(_networkRepository); + A.CallTo(() => _portalRepositories.GetInstance()).Returns(_identityProviderRepository); + A.CallTo(() => _portalRepositories.GetInstance()).Returns(_countryRepository); + + _sut = new NetworkBusinessLogic(_portalRepositories, identityService, _checklistService); + + SetupRepos(); + } + + #region Submit + + [Fact] + public async Task Submit_WithNotExistingSubmitData_ThrowsNotFoundException() + { + // Arrange + var data = _fixture.Create(); + A.CallTo(() => _networkRepository.GetSubmitData(_identity.CompanyId)) + .Returns(new ValueTuple>, IEnumerable>>, Guid?>()); + + // Act + async Task Act() => await _sut.Submit(data).ConfigureAwait(false); + + // Assert + var ex = await Assert.ThrowsAsync(Act); + ex.Message.Should().Be($"Company {_identity.CompanyId} not found"); + } + + [Fact] + public async Task Submit_WithoutCompanyApplications_ThrowsConflictException() + { + // Arrange + var data = _fixture.Create(); + A.CallTo(() => _networkRepository.GetSubmitData(_identity.CompanyId)) + .Returns((true, Enumerable.Empty>(), Enumerable.Empty>>(), null)); + + // Act + async Task Act() => await _sut.Submit(data).ConfigureAwait(false); + + // Assert + var ex = await Assert.ThrowsAsync(Act); + ex.Message.Should().Be($"Company {_identity.CompanyId} has no or more than one application"); + } + + [Fact] + public async Task Submit_WithMultipleCompanyApplications_ThrowsConflictException() + { + // Arrange + var data = _fixture.Create(); + A.CallTo(() => _networkRepository.GetSubmitData(_identity.CompanyId)) + .Returns((true, _fixture.CreateMany>(2), Enumerable.Empty>>(), null)); + + // Act + async Task Act() => await _sut.Submit(data).ConfigureAwait(false); + + // Assert + var ex = await Assert.ThrowsAsync(Act); + ex.Message.Should().Be($"Company {_identity.CompanyId} has no or more than one application"); + } + + [Fact] + public async Task Submit_WithWrongApplicationStatus_ThrowsConflictException() + { + // Arrange + var applicationId = Guid.NewGuid(); + var data = _fixture.Create(); + A.CallTo(() => _networkRepository.GetSubmitData(_identity.CompanyId)) + .Returns((true, Enumerable.Repeat>((applicationId, CompanyApplicationStatusId.VERIFY, null), 1), Enumerable.Empty>>(), Guid.NewGuid())); + + // Act + async Task Act() => await _sut.Submit(data).ConfigureAwait(false); + + // Assert + var ex = await Assert.ThrowsAsync(Act); + ex.Message.Should().Be($"Application {applicationId} is not in state CREATED"); + } + + [Fact] + public async Task Submit_WithOneMissingAgreement_ThrowsConflictException() + { + // Arrange + var applicationId = Guid.NewGuid(); + var agreementId = Guid.NewGuid(); + var notExistingAgreementId = Guid.NewGuid(); + var data = new PartnerSubmitData( + new[] { CompanyRoleId.APP_PROVIDER }, + new[] { new AgreementConsentData(agreementId, ConsentStatusId.ACTIVE) }); + var companyRoleIds = new ValueTuple>[] + { + (CompanyRoleId.APP_PROVIDER, new [] {agreementId, notExistingAgreementId}) + }; + A.CallTo(() => _networkRepository.GetSubmitData(_identity.CompanyId)) + .Returns((true, Enumerable.Repeat>((applicationId, CompanyApplicationStatusId.CREATED, null), 1), companyRoleIds, Guid.NewGuid())); + + // Act + async Task Act() => await _sut.Submit(data).ConfigureAwait(false); + + // Assert + var ex = await Assert.ThrowsAsync(Act); + ex.Message.Should().Be($"All Agreements for the company roles must be agreed to, missing agreementIds: {notExistingAgreementId} (Parameter 'Agreements')"); + } + + [Fact] + public async Task Submit_WithOneInactiveAgreement_ThrowsConflictException() + { + // Arrange + var applicationId = Guid.NewGuid(); + var agreementId = Guid.NewGuid(); + var inactiveAgreementId = Guid.NewGuid(); + var data = new PartnerSubmitData( + new[] { CompanyRoleId.APP_PROVIDER }, + new[] + { + new AgreementConsentData(agreementId, ConsentStatusId.ACTIVE), + new AgreementConsentData(inactiveAgreementId, ConsentStatusId.INACTIVE), + }); + var companyRoleIds = new ValueTuple>[] + { + (CompanyRoleId.APP_PROVIDER, new [] {agreementId, inactiveAgreementId}) + }; + A.CallTo(() => _networkRepository.GetSubmitData(_identity.CompanyId)) + .Returns((true, Enumerable.Repeat>((applicationId, CompanyApplicationStatusId.CREATED, null), 1), companyRoleIds, Guid.NewGuid())); + + // Act + async Task Act() => await _sut.Submit(data).ConfigureAwait(false); + + // Assert + var ex = await Assert.ThrowsAsync(Act); + ex.Message.Should().Be($"All agreements must be agreed to. Agreements that are not active: {inactiveAgreementId} (Parameter 'Agreements')"); + } + + [Fact] + public async Task Submit_WithoutProcessId_ThrowsConflictException() + { + // Arrange + var applicationId = Guid.NewGuid(); + var agreementId = Guid.NewGuid(); + var agreementId1 = Guid.NewGuid(); + var data = new PartnerSubmitData( + new[] { CompanyRoleId.APP_PROVIDER }, + new[] + { + new AgreementConsentData(agreementId, ConsentStatusId.ACTIVE), + new AgreementConsentData(agreementId1, ConsentStatusId.ACTIVE), + }); + var companyRoleIds = new ValueTuple>[] + { + (CompanyRoleId.APP_PROVIDER, new [] {agreementId, agreementId1}) + }; + A.CallTo(() => _networkRepository.GetSubmitData(_identity.CompanyId)) + .Returns((true, Enumerable.Repeat>((applicationId, CompanyApplicationStatusId.CREATED, "https://callback.url"), 1), companyRoleIds, null)); + + // Act + async Task Act() => await _sut.Submit(data).ConfigureAwait(false); + + // Assert + var ex = await Assert.ThrowsAsync(Act); + ex.Message.Should().Be("There must be an process"); + } + + [Fact] + public async Task Submit_WithValidData_CallsExpected() + { + // Arrange + var applicationId = Guid.NewGuid(); + var agreementId = Guid.NewGuid(); + var agreementId1 = Guid.NewGuid(); + var processId = Guid.NewGuid(); + var submitProcessId = Guid.NewGuid(); + var processSteps = new List(); + var application = new CompanyApplication(applicationId, _identity.CompanyId, CompanyApplicationStatusId.CREATED, CompanyApplicationTypeId.EXTERNAL, DateTimeOffset.UtcNow); + + var data = new PartnerSubmitData( + new[] { CompanyRoleId.APP_PROVIDER }, + new[] + { + new AgreementConsentData(agreementId, ConsentStatusId.ACTIVE), + new AgreementConsentData(agreementId1, ConsentStatusId.ACTIVE), + }); + var companyRoleIds = new ValueTuple>[] + { + (CompanyRoleId.APP_PROVIDER, new [] {agreementId, agreementId1}) + }; + A.CallTo(() => _networkRepository.GetSubmitData(_identity.CompanyId)) + .Returns((true, Enumerable.Repeat>((applicationId, CompanyApplicationStatusId.CREATED, "https://callback.url"), 1), companyRoleIds, submitProcessId)); + A.CallTo(() => _applicationRepository.AttachAndModifyCompanyApplication(applicationId, A>._)) + .Invokes((Guid _, Action setOptionalFields) => + { + setOptionalFields.Invoke(application); + }); + A.CallTo(() => _processStepRepository.CreateProcessStepRange(A>._)) + .Invokes((IEnumerable<(ProcessStepTypeId ProcessStepTypeId, ProcessStepStatusId ProcessStepStatusId, Guid ProcessId)> steps) => + { + processSteps.AddRange(steps.Select(x => new ProcessStep(Guid.NewGuid(), x.ProcessStepTypeId, x.ProcessStepStatusId, x.ProcessId, DateTimeOffset.UtcNow))); + }); + var consents = new List(); + var now = DateTimeOffset.UtcNow; + A.CallTo(() => _consentRepository.CreateConsents(A>._)) + .Invokes((IEnumerable<(Guid AgreementId, Guid CompanyId, Guid CompanyUserId, ConsentStatusId ConsentStatusId)> agreementConsents) => + { + foreach (var x in agreementConsents) + { + consents.Add(new Consent(Guid.NewGuid(), x.AgreementId, x.CompanyId, x.CompanyUserId, x.ConsentStatusId, now)); + } + }); + A.CallTo(() => _processStepRepository.CreateProcess(ProcessTypeId.APPLICATION_CHECKLIST)) + .ReturnsLazily((ProcessTypeId processTypeId) => new Process(processId, processTypeId, Guid.NewGuid())); + A.CallTo(() => _checklistService.CreateInitialChecklistAsync(applicationId)) + .Returns(new[] + { + (ApplicationChecklistEntryTypeId.REGISTRATION_VERIFICATION, ApplicationChecklistEntryStatusId.TO_DO), + (ApplicationChecklistEntryTypeId.BUSINESS_PARTNER_NUMBER, ApplicationChecklistEntryStatusId.DONE), + (ApplicationChecklistEntryTypeId.IDENTITY_WALLET, ApplicationChecklistEntryStatusId.TO_DO), + (ApplicationChecklistEntryTypeId.SELF_DESCRIPTION_LP, ApplicationChecklistEntryStatusId.TO_DO), + (ApplicationChecklistEntryTypeId.CLEARING_HOUSE, ApplicationChecklistEntryStatusId.TO_DO), + (ApplicationChecklistEntryTypeId.APPLICATION_ACTIVATION, ApplicationChecklistEntryStatusId.TO_DO), + }); + A.CallTo(() => _checklistService.GetInitialProcessStepTypeIds(A>._)) + .Returns(new[] { ProcessStepTypeId.VERIFY_REGISTRATION, ProcessStepTypeId.DECLINE_APPLICATION }); + + // Act + await _sut.Submit(data).ConfigureAwait(false); + + // Assert + application.ApplicationStatusId.Should().Be(CompanyApplicationStatusId.SUBMITTED); + A.CallTo(() => _consentRepository.CreateConsents(A>._)) + .MustHaveHappenedOnceExactly(); + consents.Should().HaveCount(2) + .And.AllSatisfy(x => x.Should().Match(x => + x.CompanyId == _identity.CompanyId && + x.CompanyUserId == _identity.UserId && + x.ConsentStatusId == ConsentStatusId.ACTIVE)) + .And.Satisfy( + x => x.AgreementId == agreementId, + x => x.AgreementId == agreementId1); + A.CallTo(() => _portalRepositories.SaveAsync()) + .MustHaveHappenedOnceExactly(); + A.CallTo(() => _processStepRepository.CreateProcessStepRange(A>._)) + .MustHaveHappenedOnceExactly(); + processSteps.Should().Satisfy( + x => x.ProcessId == processId && x.ProcessStepTypeId == ProcessStepTypeId.VERIFY_REGISTRATION && x.ProcessStepStatusId == ProcessStepStatusId.TODO, + x => x.ProcessId == processId && x.ProcessStepTypeId == ProcessStepTypeId.DECLINE_APPLICATION && x.ProcessStepStatusId == ProcessStepStatusId.TODO, + x => x.ProcessId == submitProcessId && x.ProcessStepTypeId == ProcessStepTypeId.TRIGGER_CALLBACK_OSP_SUBMITTED && x.ProcessStepStatusId == ProcessStepStatusId.TODO); + } + + #endregion + + #region Setup + + private void SetupRepos() + { + A.CallTo(() => _networkRepository.CheckExternalIdExists(ExistingExternalId, A.That.Matches(x => x == _identity.CompanyId || x == NoIdpCompanyId))) + .Returns(true); + A.CallTo(() => _networkRepository.CheckExternalIdExists(A.That.Not.Matches(x => x == ExistingExternalId), A.That.Matches(x => x == _identity.CompanyId || x == NoIdpCompanyId))) + .Returns(false); + + A.CallTo(() => _companyRepository.CheckBpnExists(Bpnl)).Returns(false); + A.CallTo(() => _companyRepository.CheckBpnExists(A.That.Not.Matches(x => x == Bpnl))).Returns(true); + + A.CallTo(() => _countryRepository.CheckCountryExistsByAlpha2CodeAsync("XX")) + .Returns(false); + A.CallTo(() => _countryRepository.CheckCountryExistsByAlpha2CodeAsync(A.That.Not.Matches(x => x == "XX"))) + .Returns(true); + + A.CallTo(() => _companyRepository.GetCompanyNameUntrackedAsync(A.That.Matches(x => x == _identity.CompanyId || x == NoIdpCompanyId))) + .Returns((true, "testCompany")); + A.CallTo(() => _companyRepository.GetCompanyNameUntrackedAsync(A.That.Not.Matches(x => x == _identity.CompanyId))) + .Returns((false, "")); + + A.CallTo(() => _identityProviderRepository.GetSingleManagedIdentityProviderAliasDataUntracked(_identity.CompanyId)) + .Returns((IdpId, (string?)"test-alias")); + + A.CallTo(() => _identityProviderRepository.GetSingleManagedIdentityProviderAliasDataUntracked(NoAliasIdpCompanyId)) + .Returns((IdpId, (string?)null)); + + A.CallTo(() => _identityProviderRepository.GetSingleManagedIdentityProviderAliasDataUntracked(NoIdpCompanyId)) + .Returns(((Guid, string?))default); + + A.CallTo(() => _identityProviderRepository.GetSingleManagedIdentityProviderAliasDataUntracked(MultiIdpCompanyId)) + .Throws(new InvalidOperationException("Sequence contains more than one element.")); + + A.CallTo(() => _identityProviderRepository.GetManagedIdentityProviderAliasDataUntracked(A.That.Matches(x => x == _identity.CompanyId || x == NoIdpCompanyId), A>._)) + .Returns(new[] { (IdpId, (string?)"test-alias") }.ToAsyncEnumerable()); + + A.CallTo(() => _userProvisioningService.GetRoleDatas(A>._)) + .Returns(new[] { new UserRoleData(UserRoleId, "cl1", "Company Admin") }.ToAsyncEnumerable()); + } + + #endregion +} diff --git a/tests/registration/Registration.Service.Tests/BusinessLogic/RegistrationBusinessLogicTest.cs b/tests/registration/Registration.Service.Tests/BusinessLogic/RegistrationBusinessLogicTest.cs index 4e4aea51f6..452e2773ff 100644 --- a/tests/registration/Registration.Service.Tests/BusinessLogic/RegistrationBusinessLogicTest.cs +++ b/tests/registration/Registration.Service.Tests/BusinessLogic/RegistrationBusinessLogicTest.cs @@ -26,7 +26,9 @@ using Microsoft.Extensions.Options; using Org.Eclipse.TractusX.Portal.Backend.Bpdm.Library; using Org.Eclipse.TractusX.Portal.Backend.Bpdm.Library.Models; +using Org.Eclipse.TractusX.Portal.Backend.Framework.DateTimeProvider; using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Linq; using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Configuration; using Org.Eclipse.TractusX.Portal.Backend.Mailing.SendMail; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess; @@ -66,9 +68,7 @@ public class RegistrationBusinessLogicTest private readonly IConsentRepository _consentRepository; private readonly IProcessStepRepository _processStepRepository; private readonly IApplicationChecklistCreationService _checklistService; - private readonly string _iamUserId; - private readonly IdentityData _identity; - private readonly Guid _companyUserId; + private readonly IdentityData _identity = new(Guid.NewGuid().ToString(), Guid.NewGuid(), IdentityTypeId.COMPANY_USER, Guid.NewGuid()); private readonly Guid _existingApplicationId; private readonly string _displayName; private readonly string _alpha2code; @@ -77,6 +77,8 @@ public class RegistrationBusinessLogicTest private readonly IMailingService _mailingService; private readonly IStaticDataRepository _staticDataRepository; private readonly Func _processLine; + private readonly IIdentityService _identityService; + private readonly IDateTimeProvider _dateTimeProvider; public RegistrationBusinessLogicTest() { @@ -101,6 +103,10 @@ public RegistrationBusinessLogicTest() _checklistService = A.Fake(); _staticDataRepository = A.Fake(); _processStepRepository = A.Fake(); + _dateTimeProvider = A.Fake(); + + _identityService = A.Fake(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity); var options = Options.Create(new RegistrationSettings { @@ -114,15 +120,9 @@ public RegistrationBusinessLogicTest() _options = _fixture.Create>(); - _iamUserId = _fixture.Create(); - _companyUserId = _fixture.Create(); _existingApplicationId = _fixture.Create(); _displayName = _fixture.Create(); _alpha2code = "XY"; - _identity = _fixture.Build() - .With(x => x.UserEntityId, _iamUserId) - .With(x => x.UserId, _companyUserId) - .Create(); _error = _fixture.Create(); _processLine = A.Fake>(); @@ -148,7 +148,9 @@ public async Task GetClientRolesCompositeAsync_GetsAllRoles() null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); // Act var result = sut.GetClientRolesCompositeAsync(); @@ -219,7 +221,9 @@ public async Task GetCompanyBpdmDetailDataByBusinessPartnerNumber_WithValidBpn_R null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); // Act var result = await sut.GetCompanyBpdmDetailDataByBusinessPartnerNumber(businessPartnerNumber, token, CancellationToken.None).ConfigureAwait(false); @@ -258,7 +262,9 @@ public async Task GetCompanyBpdmDetailDataByBusinessPartnerNumber_WithValidBpn_T null!, null!, null!, - null!); + null!, + _identityService, + _dateTimeProvider); // Act async Task Act() => await sut.GetCompanyBpdmDetailDataByBusinessPartnerNumber("NotLongEnough", "justatoken", CancellationToken.None).ConfigureAwait(false); @@ -277,9 +283,7 @@ public async Task GetAllApplicationsForUserWithStatus_WithValidUser_GetsAllRoles { //Arrange var userCompanyId = _fixture.Create(); - var identity = _fixture.Build() - .With(x => x.CompanyId, userCompanyId) - .Create(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { CompanyId = userCompanyId }); var sut = new RegistrationBusinessLogic( _options, null!, @@ -288,7 +292,10 @@ public async Task GetAllApplicationsForUserWithStatus_WithValidUser_GetsAllRoles null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); + var resultList = new[]{ new CompanyApplicationWithStatus( _fixture.Create(), @@ -306,7 +313,7 @@ public async Task GetAllApplicationsForUserWithStatus_WithValidUser_GetsAllRoles .Returns(resultList.ToAsyncEnumerable()); // Act - var result = await sut.GetAllApplicationsForUserWithStatus(identity.CompanyId).ToListAsync().ConfigureAwait(false); + var result = await sut.GetAllApplicationsForUserWithStatus().ToListAsync().ConfigureAwait(false); result.Should().ContainSingle(); result.Single().ApplicationStatus.Should().Be(CompanyApplicationStatusId.VERIFY); result.Single().ApplicationChecklist.Should().NotBeNull().And.HaveCount(6).And.Satisfy( @@ -340,13 +347,15 @@ public async Task GetCompanyWithAddressAsync_WithValidApplication_GetsData() null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); A.CallTo(() => _applicationRepository.GetCompanyApplicationDetailDataAsync(applicationId, _identity.CompanyId, null)) .Returns(data); // Act - var result = await sut.GetCompanyDetailData(applicationId, _identity.CompanyId).ConfigureAwait(false); + var result = await sut.GetCompanyDetailData(applicationId).ConfigureAwait(false); // Assert result.Should().NotBeNull(); @@ -367,13 +376,15 @@ public async Task GetCompanyWithAddressAsync_WithInvalidApplication_ThrowsNotFou null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); A.CallTo(() => _applicationRepository.GetCompanyApplicationDetailDataAsync(applicationId, _identity.CompanyId, null)) .Returns((CompanyApplicationDetailData?)null); // Act - async Task Act() => await sut.GetCompanyDetailData(applicationId, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await sut.GetCompanyDetailData(applicationId).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -393,13 +404,15 @@ public async Task GetCompanyWithAddressAsync_WithInvalidUser_ThrowsForbiddenExce null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); A.CallTo(() => _applicationRepository.GetCompanyApplicationDetailDataAsync(applicationId, _identity.CompanyId, null)) .Returns(_fixture.Build().With(x => x.IsUserOfCompany, false).Create()); // Act - async Task Act() => await sut.GetCompanyDetailData(applicationId, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await sut.GetCompanyDetailData(applicationId).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -420,6 +433,7 @@ public async Task GetCompanyWithAddressAsync_WithInvalidUser_ThrowsForbiddenExce public async Task SetCompanyWithAddressAsync_WithMissingData_ThrowsArgumentException(string? name, string? city, string? streetName, string? countryCode, IEnumerable uniqueIdentifierIds, IEnumerable values, string argumentName) { //Arrange + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { CompanyId = Guid.NewGuid() }); var sut = new RegistrationBusinessLogic( _options, null!, @@ -428,13 +442,15 @@ public async Task SetCompanyWithAddressAsync_WithMissingData_ThrowsArgumentExcep null!, null!, null!, - null!); + null!, + _identityService, + _dateTimeProvider); var uniqueIdData = uniqueIdentifierIds.Zip(values, (id, value) => new CompanyUniqueIdData(id, value)); var companyData = new CompanyDetailData(Guid.NewGuid(), name!, city!, streetName!, countryCode!, null, null, null, null, null, null, uniqueIdData); // Act - async Task Act() => await sut.SetCompanyDetailDataAsync(Guid.NewGuid(), companyData, Guid.NewGuid()).ConfigureAwait(false); + async Task Act() => await sut.SetCompanyDetailDataAsync(Guid.NewGuid(), companyData).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -455,7 +471,9 @@ public async Task SetCompanyWithAddressAsync_WithInvalidApplicationId_ThrowsNotF null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); var companyData = new CompanyDetailData(companyId, "name", "munich", "main street", "de", null, null, null, null, null, null, Enumerable.Empty()); @@ -463,7 +481,7 @@ public async Task SetCompanyWithAddressAsync_WithInvalidApplicationId_ThrowsNotF .ReturnsLazily(() => (CompanyApplicationDetailData?)null); // Act - async Task Act() => await sut.SetCompanyDetailDataAsync(applicationId, companyData, _identity.CompanyId).ConfigureAwait(false); + async Task Act() => await sut.SetCompanyDetailDataAsync(applicationId, companyData).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -476,9 +494,7 @@ public async Task SetCompanyWithAddressAsync_WithoutCompanyUserId_ThrowsForbidde //Arrange var applicationId = Guid.NewGuid(); var companyId = Guid.NewGuid(); - var identity = _fixture.Build() - .With(x => x.CompanyId, companyId) - .Create(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { CompanyId = companyId }); var companyData = new CompanyDetailData(companyId, "name", "munich", "main street", "de", null, null, null, null, null, null, Enumerable.Empty()); var sut = new RegistrationBusinessLogic( @@ -489,13 +505,15 @@ public async Task SetCompanyWithAddressAsync_WithoutCompanyUserId_ThrowsForbidde null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); A.CallTo(() => _applicationRepository.GetCompanyApplicationDetailDataAsync(applicationId, A._, companyId)) .ReturnsLazily(() => _fixture.Build().With(x => x.IsUserOfCompany, false).Create()); // Act - async Task Act() => await sut.SetCompanyDetailDataAsync(applicationId, companyData, identity.CompanyId).ConfigureAwait(false); + async Task Act() => await sut.SetCompanyDetailDataAsync(applicationId, companyData).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -508,9 +526,7 @@ public async Task SetCompanyWithAddressAsync_ModifyCompany() //Arrange var applicationId = Guid.NewGuid(); var companyId = Guid.NewGuid(); - var identity = _fixture.Build() - .With(x => x.CompanyId, companyId) - .Create(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { CompanyId = companyId }); var companyData = _fixture.Build() .With(x => x.CompanyId, companyId) .With(x => x.CountryAlpha2Code, _alpha2code) @@ -530,9 +546,11 @@ public async Task SetCompanyWithAddressAsync_ModifyCompany() null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); - A.CallTo(() => _applicationRepository.GetCompanyApplicationDetailDataAsync(applicationId, A._, identity.CompanyId)) + A.CallTo(() => _applicationRepository.GetCompanyApplicationDetailDataAsync(applicationId, A._, companyId)) .Returns(existingData); A.CallTo(() => _companyRepository.AttachAndModifyCompany(A._, A>._, A>._)) @@ -544,7 +562,7 @@ public async Task SetCompanyWithAddressAsync_ModifyCompany() }); // Act - await sut.SetCompanyDetailDataAsync(applicationId, companyData, identity.CompanyId).ConfigureAwait(false); + await sut.SetCompanyDetailDataAsync(applicationId, companyData).ConfigureAwait(false); // Assert A.CallTo(() => _companyRepository.AttachAndModifyCompany(A._, A>._, A>._)) @@ -567,9 +585,7 @@ public async Task SetCompanyWithAddressAsync_WithoutInitialCompanyAddress_Create var companyId = Guid.NewGuid(); var addressId = Guid.NewGuid(); - var identity = _fixture.Build() - .With(x => x.CompanyId, companyId) - .Create(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { CompanyId = companyId }); var companyData = _fixture.Build() .With(x => x.CompanyId, companyId) .With(x => x.CountryAlpha2Code, _alpha2code) @@ -599,7 +615,9 @@ public async Task SetCompanyWithAddressAsync_WithoutInitialCompanyAddress_Create null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); A.CallTo(() => _applicationRepository.GetCompanyApplicationDetailDataAsync(applicationId, A._, companyId)) .Returns(existingData); @@ -621,7 +639,7 @@ public async Task SetCompanyWithAddressAsync_WithoutInitialCompanyAddress_Create }); // Act - await sut.SetCompanyDetailDataAsync(applicationId, companyData, identity.CompanyId).ConfigureAwait(false); + await sut.SetCompanyDetailDataAsync(applicationId, companyData).ConfigureAwait(false); // Assert A.CallTo(() => _companyRepository.CreateAddress(A._, A._, A._, A>._)) @@ -659,10 +677,8 @@ public async Task SetCompanyWithAddressAsync_WithInitialCompanyAddress_ModifyAdd //Arrange var applicationId = Guid.NewGuid(); var companyId = Guid.NewGuid(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { CompanyId = companyId }); - var identity = _fixture.Build() - .With(x => x.CompanyId, companyId) - .Create(); var companyData = _fixture.Build() .With(x => x.CompanyId, companyId) .With(x => x.CountryAlpha2Code, _alpha2code) @@ -684,9 +700,11 @@ public async Task SetCompanyWithAddressAsync_WithInitialCompanyAddress_ModifyAdd null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); - A.CallTo(() => _applicationRepository.GetCompanyApplicationDetailDataAsync(applicationId, A._, identity.CompanyId)) + A.CallTo(() => _applicationRepository.GetCompanyApplicationDetailDataAsync(applicationId, A._, companyId)) .Returns(existingData); A.CallTo(() => _companyRepository.AttachAndModifyCompany(A._, A>._, A>._)) @@ -706,7 +724,7 @@ public async Task SetCompanyWithAddressAsync_WithInitialCompanyAddress_ModifyAdd }); // Act - await sut.SetCompanyDetailDataAsync(applicationId, companyData, identity.CompanyId).ConfigureAwait(false); + await sut.SetCompanyDetailDataAsync(applicationId, companyData).ConfigureAwait(false); // Assert A.CallTo(() => _companyRepository.CreateAddress(A._, A._, A._, A?>._)) @@ -740,10 +758,9 @@ public async Task SetCompanyWithAddressAsync_WithUniqueIdentifiers_CreateModifyD //Arrange var applicationId = Guid.NewGuid(); var companyId = Guid.NewGuid(); + var now = DateTimeOffset.Now; - var identity = _fixture.Build() - .With(x => x.CompanyId, companyId) - .Create(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { CompanyId = companyId }); var uniqueIdentifiers = _fixture.CreateMany(4); var firstIdData = _fixture.Build().With(x => x.UniqueIdentifierId, uniqueIdentifiers.First()).Create(); // shall not modify @@ -763,6 +780,9 @@ public async Task SetCompanyWithAddressAsync_WithUniqueIdentifiers_CreateModifyD (uniqueIdentifiers.ElementAt(3), _fixture.Create()) }) // shall be deleted .With(x => x.IsUserOfCompany, true) .Create(); + var application = _fixture.Build() + .With(x => x.Id, applicationId) + .Create(); IEnumerable<(UniqueIdentifierId UniqueIdentifierId, string Value)>? initialIdentifiers = null; IEnumerable<(UniqueIdentifierId UniqueIdentifierId, string Value)>? modifiedIdentifiers = null; @@ -775,8 +795,11 @@ public async Task SetCompanyWithAddressAsync_WithUniqueIdentifiers_CreateModifyD null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); + A.CallTo(() => _dateTimeProvider.OffsetNow).Returns(now); A.CallTo(() => _applicationRepository.GetCompanyApplicationDetailDataAsync(applicationId, A._, companyId)) .Returns(existingData); @@ -786,19 +809,26 @@ public async Task SetCompanyWithAddressAsync_WithUniqueIdentifiers_CreateModifyD initialIdentifiers = initial; modifiedIdentifiers = modified; }); + A.CallTo(() => _applicationRepository.AttachAndModifyCompanyApplication(applicationId, A>._)) + .Invokes((Guid _, Action setOptionalFields) => + { + setOptionalFields.Invoke(application); + }); // Act - await sut.SetCompanyDetailDataAsync(applicationId, companyData, identity.CompanyId).ConfigureAwait(false); + await sut.SetCompanyDetailDataAsync(applicationId, companyData).ConfigureAwait(false); // Assert A.CallTo(() => _companyRepository.CreateUpdateDeleteIdentifiers(companyId, A>._, A>._)).MustHaveHappenedOnceExactly(); A.CallTo(() => _companyRepository.CreateUpdateDeleteIdentifiers(A.That.Not.IsEqualTo(companyId), A>._, A>._)).MustNotHaveHappened(); + A.CallTo(() => _applicationRepository.AttachAndModifyCompanyApplication(applicationId, A>._)).MustHaveHappenedOnceExactly(); A.CallTo(() => _portalRepositories.SaveAsync()).MustHaveHappenedOnceExactly(); initialIdentifiers.Should().NotBeNull(); modifiedIdentifiers.Should().NotBeNull(); initialIdentifiers.Should().ContainInOrder(existingData.UniqueIds); modifiedIdentifiers.Should().ContainInOrder((firstIdData.UniqueIdentifierId, firstIdData.Value), (secondIdData.UniqueIdentifierId, secondIdData.Value), (thirdIdData.UniqueIdentifierId, thirdIdData.Value)); + application.DateLastChanged.Should().Be(now); } [Fact] @@ -808,6 +838,7 @@ public async Task SetCompanyWithAddressAsync_WithInvalidCountryCode_Throws() var companyData = _fixture.Build() .With(x => x.CountryAlpha2Code, _alpha2code) .Create(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { CompanyId = Guid.NewGuid() }); var sut = new RegistrationBusinessLogic( _options, @@ -817,13 +848,15 @@ public async Task SetCompanyWithAddressAsync_WithInvalidCountryCode_Throws() null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); A.CallTo(() => _countryRepository.GetCountryAssignedIdentifiers(A._, A>._)) .Returns((false, null!)); // Act - var Act = () => sut.SetCompanyDetailDataAsync(Guid.NewGuid(), companyData, Guid.NewGuid()); + var Act = () => sut.SetCompanyDetailDataAsync(Guid.NewGuid(), companyData); //Assert var result = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -835,6 +868,7 @@ public async Task SetCompanyWithAddressAsync_WithInvalidUniqueIdentifiers_Throws { //Arrange var identifiers = _fixture.CreateMany(2); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { CompanyId = Guid.NewGuid() }); var companyData = _fixture.Build() .With(x => x.CountryAlpha2Code, _alpha2code) @@ -849,13 +883,15 @@ public async Task SetCompanyWithAddressAsync_WithInvalidUniqueIdentifiers_Throws null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); A.CallTo(() => _countryRepository.GetCountryAssignedIdentifiers(_alpha2code, A>._)) .Returns((true, new[] { identifiers.First() })); // Act - var Act = () => sut.SetCompanyDetailDataAsync(Guid.NewGuid(), companyData, Guid.NewGuid()); + var Act = () => sut.SetCompanyDetailDataAsync(Guid.NewGuid(), companyData); //Assert var result = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -871,6 +907,7 @@ public async Task SetOwnCompanyApplicationStatusAsync_WithInvalidStatus_ThrowsCo { //Arrange var applicationId = _fixture.Create(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { CompanyId = Guid.NewGuid() }); var sut = new RegistrationBusinessLogic( _options, null!, @@ -879,10 +916,12 @@ public async Task SetOwnCompanyApplicationStatusAsync_WithInvalidStatus_ThrowsCo null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); // Act - async Task Act() => await sut.SetOwnCompanyApplicationStatusAsync(applicationId, 0, Guid.NewGuid()).ConfigureAwait(false); + async Task Act() => await sut.SetOwnCompanyApplicationStatusAsync(applicationId, 0).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -894,6 +933,7 @@ public async Task SetOwnCompanyApplicationStatusAsync_WithInvalidApplication_Thr { //Arrange var applicationId = _fixture.Create(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { CompanyId = Guid.NewGuid() }); var sut = new RegistrationBusinessLogic( _options, null!, @@ -902,12 +942,15 @@ public async Task SetOwnCompanyApplicationStatusAsync_WithInvalidApplication_Thr null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); + A.CallTo(() => _applicationRepository.GetOwnCompanyApplicationUserDataAsync(A._, A._)) .ReturnsLazily(() => new ValueTuple()); // Act - async Task Act() => await sut.SetOwnCompanyApplicationStatusAsync(applicationId, CompanyApplicationStatusId.VERIFY, Guid.NewGuid()).ConfigureAwait(false); + async Task Act() => await sut.SetOwnCompanyApplicationStatusAsync(applicationId, CompanyApplicationStatusId.VERIFY).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -919,6 +962,7 @@ public async Task SetOwnCompanyApplicationStatusAsync_WithInvalidStatus_ThrowsAr { //Arrange var applicationId = _fixture.Create(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { CompanyId = Guid.NewGuid() }); var sut = new RegistrationBusinessLogic( _options, null!, @@ -927,12 +971,15 @@ public async Task SetOwnCompanyApplicationStatusAsync_WithInvalidStatus_ThrowsAr null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); + A.CallTo(() => _applicationRepository.GetOwnCompanyApplicationUserDataAsync(A._, A._)) .ReturnsLazily(() => new ValueTuple(true, CompanyApplicationStatusId.CREATED)); // Act - async Task Act() => await sut.SetOwnCompanyApplicationStatusAsync(applicationId, CompanyApplicationStatusId.VERIFY, Guid.NewGuid()).ConfigureAwait(false); + async Task Act() => await sut.SetOwnCompanyApplicationStatusAsync(applicationId, CompanyApplicationStatusId.VERIFY).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -943,7 +990,18 @@ public async Task SetOwnCompanyApplicationStatusAsync_WithInvalidStatus_ThrowsAr public async Task SetOwnCompanyApplicationStatusAsync_WithValidData_SavesChanges() { //Arrange + var now = DateTimeOffset.Now; var applicationId = _fixture.Create(); + var application = _fixture.Build() + .With(x => x.Id, applicationId) + .Create(); + A.CallTo(() => _dateTimeProvider.OffsetNow).Returns(now); + A.CallTo(() => _applicationRepository.AttachAndModifyCompanyApplication(applicationId, A>._)) + .Invokes((Guid _, Action setOptionalFields) => + { + setOptionalFields.Invoke(application); + }); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { CompanyId = Guid.NewGuid() }); var sut = new RegistrationBusinessLogic( _options, null!, @@ -952,15 +1010,20 @@ public async Task SetOwnCompanyApplicationStatusAsync_WithValidData_SavesChanges null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); + A.CallTo(() => _applicationRepository.GetOwnCompanyApplicationUserDataAsync(A._, A._)) .ReturnsLazily(() => new ValueTuple(true, CompanyApplicationStatusId.VERIFY)); // Act - await sut.SetOwnCompanyApplicationStatusAsync(applicationId, CompanyApplicationStatusId.SUBMITTED, Guid.NewGuid()).ConfigureAwait(false); + await sut.SetOwnCompanyApplicationStatusAsync(applicationId, CompanyApplicationStatusId.SUBMITTED).ConfigureAwait(false); // Assert A.CallTo(() => _portalRepositories.SaveAsync()).MustHaveHappenedOnceExactly(); + A.CallTo(() => _applicationRepository.AttachAndModifyCompanyApplication(applicationId, A>._)).MustHaveHappenedOnceExactly(); + application.DateLastChanged.Should().Be(now); } #endregion @@ -984,7 +1047,10 @@ public async Task GetCompanyRolesAsync_() null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); + // Act var result = await sut.GetCompanyRoles().ToListAsync().ConfigureAwait(false); @@ -1036,9 +1102,13 @@ public async Task GetInvitedUsersDetail_ThrowException_WhenIdIsNull() public async Task UploadDocumentAsync_WithValidData_CreatesDocument() { // Arrange + var now = DateTimeOffset.Now; var documentId = Guid.NewGuid(); var file = FormFileHelper.GetFormFile("this is just a test", "superFile.pdf", "application/pdf"); var documents = new List(); + var application = _fixture.Build() + .With(x => x.Id, _existingApplicationId) + .Create(); var settings = new RegistrationSettings { DocumentTypeIds = new[]{ @@ -1046,6 +1116,7 @@ public async Task UploadDocumentAsync_WithValidData_CreatesDocument() DocumentTypeId.COMMERCIAL_REGISTER_EXTRACT } }; + A.CallTo(() => _dateTimeProvider.OffsetNow).Returns(now); A.CallTo(() => _documentRepository.CreateDocument(A._, A._, A._, A._, A._, A?>._)) .Invokes((string documentName, byte[] documentContent, byte[] hash, MediaTypeId mediaTypeId, DocumentTypeId documentTypeId, Action? action) => { @@ -1053,7 +1124,11 @@ public async Task UploadDocumentAsync_WithValidData_CreatesDocument() action?.Invoke(document); documents.Add(document); }); - + A.CallTo(() => _applicationRepository.AttachAndModifyCompanyApplication(_existingApplicationId, A>._)) + .Invokes((Guid _, Action setOptionalFields) => + { + setOptionalFields.Invoke(application); + }); var sut = new RegistrationBusinessLogic( Options.Create(settings), null!, @@ -1062,14 +1137,18 @@ public async Task UploadDocumentAsync_WithValidData_CreatesDocument() null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); // Act - await sut.UploadDocumentAsync(_existingApplicationId, file, DocumentTypeId.CX_FRAME_CONTRACT, (_identity.UserId, _identity.CompanyId), CancellationToken.None); + await sut.UploadDocumentAsync(_existingApplicationId, file, DocumentTypeId.CX_FRAME_CONTRACT, CancellationToken.None); // Assert A.CallTo(() => _portalRepositories.SaveAsync()).MustHaveHappenedOnceExactly(); + A.CallTo(() => _applicationRepository.AttachAndModifyCompanyApplication(_existingApplicationId, A>._)).MustHaveHappenedOnceExactly(); documents.Should().HaveCount(1); + application.DateLastChanged.Should().Be(now); } [Fact] @@ -1080,7 +1159,7 @@ public async Task UploadDocumentAsync_WithJsonDocument_ThrowsException() var sut = _fixture.Create(); // Act - async Task Action() => await sut.UploadDocumentAsync(_existingApplicationId, file, DocumentTypeId.ADDITIONAL_DETAILS, (_identity.UserId, _identity.CompanyId), CancellationToken.None).ConfigureAwait(false); + async Task Action() => await sut.UploadDocumentAsync(_existingApplicationId, file, DocumentTypeId.ADDITIONAL_DETAILS, CancellationToken.None).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Action); @@ -1095,7 +1174,7 @@ public async Task UploadDocumentAsync_WithEmptyTitle_ThrowsException() var sut = _fixture.Create(); // Act - async Task Action() => await sut.UploadDocumentAsync(_existingApplicationId, file, DocumentTypeId.ADDITIONAL_DETAILS, (_identity.UserId, _identity.CompanyId), CancellationToken.None); + async Task Action() => await sut.UploadDocumentAsync(_existingApplicationId, file, DocumentTypeId.ADDITIONAL_DETAILS, CancellationToken.None); // Assert var ex = await Assert.ThrowsAsync(Action); @@ -1122,11 +1201,13 @@ public async Task UploadDocumentAsync_WithNotExistingApplicationId_ThrowsExcepti null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); var notExistingId = Guid.NewGuid(); // Act - async Task Action() => await sut.UploadDocumentAsync(notExistingId, file, DocumentTypeId.CX_FRAME_CONTRACT, (_identity.UserId, _identity.CompanyId), CancellationToken.None); + async Task Action() => await sut.UploadDocumentAsync(notExistingId, file, DocumentTypeId.CX_FRAME_CONTRACT, CancellationToken.None); // Assert var ex = await Assert.ThrowsAsync(Action); @@ -1156,11 +1237,13 @@ public async Task UploadDocumentAsync_WithNotExistingIamUser_ThrowsException() null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); var identity = _fixture.Create(); // Act - async Task Action() => await sut.UploadDocumentAsync(_existingApplicationId, file, DocumentTypeId.CX_FRAME_CONTRACT, (_identity.UserId, _identity.CompanyId), CancellationToken.None); + async Task Action() => await sut.UploadDocumentAsync(_existingApplicationId, file, DocumentTypeId.CX_FRAME_CONTRACT, CancellationToken.None); // Assert var ex = await Assert.ThrowsAsync(Action); @@ -1189,9 +1272,11 @@ public async Task UploadDocumentAsync_WithInvalidDocumentTypeId_ThrowsException( null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); // Act - async Task Action() => await sut.UploadDocumentAsync(_existingApplicationId, file, DocumentTypeId.ADDITIONAL_DETAILS, (_identity.UserId, _identity.CompanyId), CancellationToken.None); + async Task Action() => await sut.UploadDocumentAsync(_existingApplicationId, file, DocumentTypeId.ADDITIONAL_DETAILS, CancellationToken.None); // Assert var ex = await Assert.ThrowsAsync(Action); @@ -1207,7 +1292,17 @@ public async Task TestInviteNewUserAsyncSuccess() { SetupFakesForInvitation(); + var now = DateTimeOffset.Now; var userCreationInfo = _fixture.Create(); + var application = _fixture.Build() + .With(x => x.Id, _existingApplicationId) + .Create(); + A.CallTo(() => _dateTimeProvider.OffsetNow).Returns(now); + A.CallTo(() => _applicationRepository.AttachAndModifyCompanyApplication(_existingApplicationId, A>._)) + .Invokes((Guid _, Action setOptionalFields) => + { + setOptionalFields.Invoke(application); + }); var sut = new RegistrationBusinessLogic( _options, @@ -1217,14 +1312,18 @@ public async Task TestInviteNewUserAsyncSuccess() _userProvisioningService, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); - await sut.InviteNewUserAsync(_existingApplicationId, userCreationInfo, (_identity.UserId, _identity.CompanyId)).ConfigureAwait(false); + await sut.InviteNewUserAsync(_existingApplicationId, userCreationInfo).ConfigureAwait(false); A.CallTo(() => _userProvisioningService.CreateOwnCompanyIdpUsersAsync(A._, A>._, A._)).MustHaveHappened(); A.CallTo(() => _applicationRepository.CreateInvitation(A.That.IsEqualTo(_existingApplicationId), A._)).MustHaveHappened(); + A.CallTo(() => _applicationRepository.AttachAndModifyCompanyApplication(_existingApplicationId, A>._)).MustHaveHappenedOnceExactly(); A.CallTo(() => _portalRepositories.SaveAsync()).MustHaveHappened(); A.CallTo(() => _mailingService.SendMails(A.That.IsEqualTo(userCreationInfo.eMail), A>.That.Matches(x => x["companyName"] == _displayName), A>._)).MustHaveHappened(); + application.DateLastChanged.Should().Be(now); } [Fact] @@ -1246,9 +1345,11 @@ public async Task TestInviteNewUserEmptyEmailThrows() _userProvisioningService, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); - Task Act() => sut.InviteNewUserAsync(_existingApplicationId, userCreationInfo, (_identity.UserId, _identity.CompanyId)); + Task Act() => sut.InviteNewUserAsync(_existingApplicationId, userCreationInfo); var error = await Assert.ThrowsAsync(Act).ConfigureAwait(false); error.Message.Should().Be("email must not be empty"); @@ -1274,9 +1375,11 @@ public async Task TestInviteNewUserUserAlreadyExistsThrows() _userProvisioningService, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); - Task Act() => sut.InviteNewUserAsync(_existingApplicationId, userCreationInfo, (_identity.UserId, _identity.CompanyId)); + Task Act() => sut.InviteNewUserAsync(_existingApplicationId, userCreationInfo); var error = await Assert.ThrowsAsync(Act).ConfigureAwait(false); error.Message.Should().Be($"user with email {userCreationInfo.eMail} does already exist"); @@ -1307,9 +1410,11 @@ public async Task TestInviteNewUserAsyncCreationErrorThrows() _userProvisioningService, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); - Task Act() => sut.InviteNewUserAsync(_existingApplicationId, userCreationInfo, (_identity.UserId, _identity.CompanyId)); + Task Act() => sut.InviteNewUserAsync(_existingApplicationId, userCreationInfo); var error = await Assert.ThrowsAsync(Act).ConfigureAwait(false); error.Message.Should().Be(_error.Message); @@ -1330,6 +1435,7 @@ public async Task GetUploadedDocumentsAsync_ReturnsExpectedOutput() // Arrange var applicationId = _fixture.Create(); var identity = _fixture.Create(); + A.CallTo(() => _identityService.IdentityData).Returns(identity); var uploadDocuments = _fixture.CreateMany(3); A.CallTo(() => _documentRepository.GetUploadedDocumentsAsync(applicationId, DocumentTypeId.APP_CONTRACT, identity.UserId)) @@ -1343,9 +1449,11 @@ public async Task GetUploadedDocumentsAsync_ReturnsExpectedOutput() null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); // Act - var result = await sut.GetUploadedDocumentsAsync(applicationId, DocumentTypeId.APP_CONTRACT, identity.UserId).ConfigureAwait(false); + var result = await sut.GetUploadedDocumentsAsync(applicationId, DocumentTypeId.APP_CONTRACT).ConfigureAwait(false); // Assert result.Should().NotBeNull(); @@ -1359,6 +1467,7 @@ public async Task GetUploadedDocumentsAsync_InvalidApplication_ThrowsNotFound() // Arrange var applicationId = _fixture.Create(); var identity = _fixture.Create(); + A.CallTo(() => _identityService.IdentityData).Returns(identity); A.CallTo(() => _documentRepository.GetUploadedDocumentsAsync(applicationId, DocumentTypeId.APP_CONTRACT, identity.UserId)) .Returns(((bool, IEnumerable))default); @@ -1371,9 +1480,11 @@ public async Task GetUploadedDocumentsAsync_InvalidApplication_ThrowsNotFound() null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); - Task Act() => sut.GetUploadedDocumentsAsync(applicationId, DocumentTypeId.APP_CONTRACT, identity.UserId); + Task Act() => sut.GetUploadedDocumentsAsync(applicationId, DocumentTypeId.APP_CONTRACT); // Act var error = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -1388,6 +1499,7 @@ public async Task GetUploadedDocumentsAsync_InvalidUser_ThrowsForbidden() // Arrange var applicationId = _fixture.Create(); var identity = _fixture.Create(); + A.CallTo(() => _identityService.IdentityData).Returns(identity); A.CallTo(() => _documentRepository.GetUploadedDocumentsAsync(applicationId, DocumentTypeId.APP_CONTRACT, identity.UserId)) .Returns((false, Enumerable.Empty())); @@ -1400,9 +1512,11 @@ public async Task GetUploadedDocumentsAsync_InvalidUser_ThrowsForbidden() null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); - Task Act() => sut.GetUploadedDocumentsAsync(applicationId, DocumentTypeId.APP_CONTRACT, identity.UserId); + Task Act() => sut.GetUploadedDocumentsAsync(applicationId, DocumentTypeId.APP_CONTRACT); // Act var error = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -1422,10 +1536,10 @@ public async Task SubmitRoleConsentsAsync_WithNotExistingApplication_ThrowsNotFo var notExistingId = _fixture.Create(); A.CallTo(() => _companyRolesRepository.GetCompanyRoleAgreementConsentDataAsync(notExistingId)) .ReturnsLazily(() => (CompanyRoleAgreementConsentData?)null); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); // Act - async Task Act() => await sut.SubmitRoleConsentAsync(notExistingId, _fixture.Create(), _identity.UserId, _identity.CompanyId) + async Task Act() => await sut.SubmitRoleConsentAsync(notExistingId, _fixture.Create()) .ConfigureAwait(false); // Arrange @@ -1442,10 +1556,10 @@ public async Task SubmitRoleConsentsAsync_WithWrongCompanyUser_ThrowsForbiddenEx var data = new CompanyRoleAgreementConsentData(Guid.NewGuid(), applicationStatusId, _fixture.CreateMany(2), _fixture.CreateMany(5)); A.CallTo(() => _companyRolesRepository.GetCompanyRoleAgreementConsentDataAsync(applicationId)) .ReturnsLazily(() => data); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); // Act - async Task Act() => await sut.SubmitRoleConsentAsync(applicationId, _fixture.Create(), _identity.UserId, _identity.CompanyId) + async Task Act() => await sut.SubmitRoleConsentAsync(applicationId, _fixture.Create()) .ConfigureAwait(false); // Arrange @@ -1472,10 +1586,10 @@ public async Task SubmitRoleConsentsAsync_WithInvalidRoles_ThrowsControllerArgum .ReturnsLazily(() => data); A.CallTo(() => _companyRolesRepository.GetAgreementAssignedCompanyRolesUntrackedAsync(roleIds)) .Returns(companyRoleAssignedAgreements.ToAsyncEnumerable()); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); // Act - async Task Act() => await sut.SubmitRoleConsentAsync(applicationId, _fixture.Create(), _identity.UserId, _identity.CompanyId) + async Task Act() => await sut.SubmitRoleConsentAsync(applicationId, _fixture.Create()) .ConfigureAwait(false); // Arrange @@ -1513,10 +1627,10 @@ 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!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); // Act - async Task Act() => await sut.SubmitRoleConsentAsync(applicationId, consents, _identity.UserId, _identity.CompanyId) + async Task Act() => await sut.SubmitRoleConsentAsync(applicationId, consents) .ConfigureAwait(false); // Arrange @@ -1532,6 +1646,7 @@ public async Task SubmitRoleConsentsAsync_WithValidData_CallsExpected() var agreementId_3 = _fixture.Create(); var consentId = _fixture.Create(); + var now = DateTimeOffset.Now; IEnumerable? removedCompanyRoleIds = null; @@ -1548,6 +1663,10 @@ public async Task SubmitRoleConsentsAsync_WithValidData_CallsExpected() }); var applicationId = _fixture.Create(); var applicationStatusId = CompanyApplicationStatusId.INVITE_USER; + var application = _fixture.Build() + .With(x => x.Id, applicationId) + .With(x => x.ApplicationStatusId, applicationStatusId) + .Create(); var data = new CompanyRoleAgreementConsentData( _identity.CompanyId, applicationStatusId, @@ -1565,6 +1684,7 @@ public async Task SubmitRoleConsentsAsync_WithValidData_CallsExpected() new ValueTuple>(CompanyRoleId.ACTIVE_PARTICIPANT, new [] { agreementId_1 }), new ValueTuple>(CompanyRoleId.SERVICE_PROVIDER, new [] { agreementId_1, agreementId_3 }), }; + A.CallTo(() => _dateTimeProvider.OffsetNow).Returns(now); A.CallTo(() => _companyRolesRepository.GetCompanyRoleAgreementConsentDataAsync(applicationId)) .Returns(data); A.CallTo(() => _companyRolesRepository.GetAgreementAssignedCompanyRolesUntrackedAsync(A>._)) @@ -1581,8 +1701,7 @@ public async Task SubmitRoleConsentsAsync_WithValidData_CallsExpected() A.CallTo(() => _applicationRepository.AttachAndModifyCompanyApplication(A._, A>._)) .Invokes((Guid companyApplicationId, Action setOptionalParameters) => { - var companyApplication = new CompanyApplication(companyApplicationId, Guid.Empty, default!, default!, default!); - setOptionalParameters.Invoke(companyApplication); + setOptionalParameters.Invoke(application); }); A.CallTo(() => _companyRolesRepository.RemoveCompanyAssignedRoles(_identity.CompanyId, A>._)) .Invokes((Guid _, IEnumerable companyRoleIds) => @@ -1590,10 +1709,10 @@ public async Task SubmitRoleConsentsAsync_WithValidData_CallsExpected() removedCompanyRoleIds = companyRoleIds; }); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); // Act - await sut.SubmitRoleConsentAsync(applicationId, consents, _identity.UserId, _identity.CompanyId).ConfigureAwait(false); + await sut.SubmitRoleConsentAsync(applicationId, consents).ConfigureAwait(false); // Arrange A.CallTo(() => _consentRepository.AttachAndModifiesConsents(A>._, A>._)).MustHaveHappened(2, Times.Exactly); @@ -1603,9 +1722,12 @@ public async Task SubmitRoleConsentsAsync_WithValidData_CallsExpected() A.CallTo(() => _companyRolesRepository.CreateCompanyAssignedRole(A._, A.That.Not.IsEqualTo(CompanyRoleId.ACTIVE_PARTICIPANT))).MustNotHaveHappened(); A.CallTo(() => _companyRolesRepository.RemoveCompanyAssignedRoles(_identity.CompanyId, A>._)).MustHaveHappenedOnceExactly(); A.CallTo(() => _companyRolesRepository.RemoveCompanyAssignedRoles(A.That.Not.IsEqualTo(_identity.CompanyId), A>._)).MustNotHaveHappened(); + A.CallTo(() => _applicationRepository.AttachAndModifyCompanyApplication(A._, A>._)).MustHaveHappenedOnceExactly(); removedCompanyRoleIds.Should().NotBeNull(); removedCompanyRoleIds.Should().ContainSingle(x => x == CompanyRoleId.SERVICE_PROVIDER); A.CallTo(() => _portalRepositories.SaveAsync()).MustHaveHappenedOnceExactly(); + application.DateLastChanged.Should().Be(now); + application.ApplicationStatusId.Should().Be(CompanyApplicationStatusId.UPLOAD_DOCUMENTS); } #endregion @@ -1625,10 +1747,10 @@ public async Task SubmitRegistrationAsync_WithNotExistingApplication_ThrowsNotFo }; A.CallTo(() => _applicationRepository.GetOwnCompanyApplicationUserEmailDataAsync(A._, A._, A>._)) .Returns((CompanyApplicationUserEmailData?)null); - var sut = new RegistrationBusinessLogic(Options.Create(settings), _mailingService, null!, null!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(Options.Create(settings), _mailingService, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); // Act - async Task Act() => await sut.SubmitRegistrationAsync(notExistingId, _identity.UserId) + async Task Act() => await sut.SubmitRegistrationAsync(notExistingId) .ConfigureAwait(false); // Assert @@ -1643,6 +1765,7 @@ public async Task SubmitRegistrationAsync_WithDocumentId_Success() { // Arrange var applicationId = _fixture.Create(); + var now = DateTimeOffset.Now; var documents = new DocumentStatusData[] { new(Guid.NewGuid(),DocumentStatusId.PENDING), new(Guid.NewGuid(),DocumentStatusId.INACTIVE) @@ -1656,6 +1779,7 @@ public async Task SubmitRegistrationAsync_WithDocumentId_Success() new ValueTuple(Guid.NewGuid(), ConsentStatusId.ACTIVE), }; var companyData = new CompanyData("Test Company", Guid.NewGuid(), "Strabe Street", "Munich", "Germany", uniqueIds, companyRoleIds); + A.CallTo(() => _dateTimeProvider.OffsetNow).Returns(now); A.CallTo(() => _applicationRepository.GetOwnCompanyApplicationUserEmailDataAsync(A._, A._, A>._)) .Returns(new CompanyApplicationUserEmailData(CompanyApplicationStatusId.VERIFY, true, "test@mail.de", documents, companyData, agreementConsents)); @@ -1714,10 +1838,10 @@ public async Task SubmitRegistrationAsync_WithDocumentId_Success() DocumentTypeId.COMMERCIAL_REGISTER_EXTRACT } }; - var sut = new RegistrationBusinessLogic(Options.Create(settings), _mailingService, null!, null!, null!, null!, _portalRepositories, _checklistService); + var sut = new RegistrationBusinessLogic(Options.Create(settings), _mailingService, null!, null!, null!, null!, _portalRepositories, _checklistService, _identityService, _dateTimeProvider); // Act - await sut.SubmitRegistrationAsync(applicationId, _identity.UserId); + await sut.SubmitRegistrationAsync(applicationId); // Assert A.CallTo(() => _applicationRepository.GetOwnCompanyApplicationUserEmailDataAsync(applicationId, _identity.UserId, A>.That.IsSameSequenceAs(new[] { DocumentTypeId.COMMERCIAL_REGISTER_EXTRACT }))) @@ -1749,6 +1873,7 @@ public async Task SubmitRegistrationAsync_WithDocumentId_Success() application.Should().NotBeNull(); application!.ChecklistProcessId.Should().Be(process!.Id); application.ApplicationStatusId.Should().Be(CompanyApplicationStatusId.SUBMITTED); + application.DateLastChanged.Should().Be(now); A.CallTo(() => _processStepRepository.CreateProcessStepRange(A>._)) .MustHaveHappenedOnceExactly(); @@ -1779,6 +1904,7 @@ public async Task SubmitRegistrationAsync_InvalidStatus_ThrowsForbiddenException { // Arrange var userId = Guid.NewGuid(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { UserId = userId }); var applicationId = _fixture.Create(); var uniqueIds = _fixture.CreateMany(3).ToImmutableArray(); var companyRoleIds = _fixture.CreateMany(3).ToImmutableArray(); @@ -1799,10 +1925,10 @@ 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), _mailingService, null!, null!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(Options.Create(settings), _mailingService, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); // Act - async Task Act() => await sut.SubmitRegistrationAsync(applicationId, userId) + async Task Act() => await sut.SubmitRegistrationAsync(applicationId) .ConfigureAwait(false); // Assert @@ -1820,6 +1946,7 @@ public async Task SubmitRegistrationAsync_AlreadyClosed_ThrowsForbiddenException { // Arrange var userId = Guid.NewGuid(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { UserId = userId }); var applicationId = _fixture.Create(); var uniqueIds = _fixture.CreateMany(3).ToImmutableArray(); var companyRoleIds = _fixture.CreateMany(3).ToImmutableArray(); @@ -1840,10 +1967,10 @@ 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), _mailingService, null!, null!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(Options.Create(settings), _mailingService, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); // Act - async Task Act() => await sut.SubmitRegistrationAsync(applicationId, userId) + async Task Act() => await sut.SubmitRegistrationAsync(applicationId) .ConfigureAwait(false); // Assert @@ -1858,6 +1985,7 @@ public async Task SubmitRegistrationAsync_WithNotExistingCompanyUser_ThrowsForbi { // Arrange var userId = Guid.NewGuid(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { UserId = userId }); var applicationId = _fixture.Create(); var uniqueIds = _fixture.CreateMany(3).ToImmutableArray(); var companyRoleIds = _fixture.CreateMany(3).ToImmutableArray(); @@ -1874,10 +2002,10 @@ 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), _mailingService, null!, null!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(Options.Create(settings), _mailingService, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); // Act - async Task Act() => await sut.SubmitRegistrationAsync(applicationId, userId) + async Task Act() => await sut.SubmitRegistrationAsync(applicationId) .ConfigureAwait(false); // Assert @@ -1892,6 +2020,7 @@ public async Task SubmitRegistrationAsync_WithNotExistingStreetName_ThrowsConfli { // Arrange var userId = Guid.NewGuid(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { UserId = userId }); var applicationId = _fixture.Create(); var uniqueIds = _fixture.CreateMany(3).ToImmutableArray(); var companyRoleIds = _fixture.CreateMany(3).ToImmutableArray(); @@ -1908,10 +2037,10 @@ 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), _mailingService, null!, null!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(Options.Create(settings), _mailingService, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); // Act - async Task Act() => await sut.SubmitRegistrationAsync(applicationId, userId) + async Task Act() => await sut.SubmitRegistrationAsync(applicationId) .ConfigureAwait(false); // Assert @@ -1924,6 +2053,7 @@ public async Task SubmitRegistrationAsync_WithNotExistingAddressId_ThrowsConflic { // Arrange var userId = Guid.NewGuid(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { UserId = userId }); var applicationId = _fixture.Create(); var uniqueIds = _fixture.CreateMany(3).ToImmutableArray(); var companyRoleIds = _fixture.CreateMany(3).ToImmutableArray(); @@ -1934,10 +2064,10 @@ 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>._)) .ReturnsLazily(() => new CompanyApplicationUserEmailData(CompanyApplicationStatusId.VERIFY, true, _fixture.Create(), Enumerable.Empty(), companyData, agreementConsents)); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), _mailingService, null!, null!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), _mailingService, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); // Act - async Task Act() => await sut.SubmitRegistrationAsync(applicationId, userId) + async Task Act() => await sut.SubmitRegistrationAsync(applicationId) .ConfigureAwait(false); // Assert @@ -1950,6 +2080,7 @@ public async Task SubmitRegistrationAsync_WithNotExistingCompanyName_ThrowsConfl { // Arrange var userId = Guid.NewGuid(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { UserId = userId }); var applicationId = _fixture.Create(); var uniqueIds = _fixture.CreateMany(3).ToImmutableArray(); var companyRoleIds = _fixture.CreateMany(3).ToImmutableArray(); @@ -1960,10 +2091,10 @@ 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()), _mailingService, null!, null!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), _mailingService, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); // Act - async Task Act() => await sut.SubmitRegistrationAsync(applicationId, userId) + async Task Act() => await sut.SubmitRegistrationAsync(applicationId) .ConfigureAwait(false); // Assert @@ -1976,6 +2107,7 @@ public async Task SubmitRegistrationAsync_WithNotExistingUniqueId_ThrowsConflict { // Arrange var userId = Guid.NewGuid(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { UserId = userId }); var applicationId = _fixture.Create(); var companyRoleIds = _fixture.CreateMany(3).ToImmutableArray(); var agreementConsents = new List<(Guid AgreementId, ConsentStatusId ConsentStatusId)> @@ -1986,10 +2118,10 @@ 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>._)) .ReturnsLazily(() => new CompanyApplicationUserEmailData(CompanyApplicationStatusId.VERIFY, true, _fixture.Create(), Enumerable.Empty(), companyData, agreementConsents)); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), _mailingService, null!, null!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), _mailingService, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); // Act - async Task Act() => await sut.SubmitRegistrationAsync(applicationId, userId) + async Task Act() => await sut.SubmitRegistrationAsync(applicationId) .ConfigureAwait(false); // Assert @@ -2002,6 +2134,7 @@ public async Task SubmitRegistrationAsync_WithNotExistingCompanyRoleId_ThrowsCon { // Arrange var userId = Guid.NewGuid(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { UserId = userId }); var applicationId = _fixture.Create(); var uniqueIds = _fixture.CreateMany(3).ToImmutableArray(); var agreementConsents = new List<(Guid AgreementId, ConsentStatusId ConsentStatusId)> @@ -2012,10 +2145,10 @@ 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>._)) .ReturnsLazily(() => new CompanyApplicationUserEmailData(CompanyApplicationStatusId.VERIFY, true, _fixture.Create(), Enumerable.Empty(), companyData, agreementConsents)); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), _mailingService, null!, null!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), _mailingService, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); // Act - async Task Act() => await sut.SubmitRegistrationAsync(applicationId, userId) + async Task Act() => await sut.SubmitRegistrationAsync(applicationId) .ConfigureAwait(false); // Assert @@ -2028,6 +2161,7 @@ public async Task SubmitRegistrationAsync_WithNotExistingAgreementandConsent_Thr { // Arrange var userId = Guid.NewGuid(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { UserId = userId }); var applicationId = _fixture.Create(); var uniqueIds = _fixture.CreateMany(3).ToImmutableArray(); var companyRoleIds = _fixture.CreateMany(3).ToImmutableArray(); @@ -2035,10 +2169,10 @@ 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>._)) .ReturnsLazily(() => new CompanyApplicationUserEmailData(CompanyApplicationStatusId.VERIFY, true, _fixture.Create(), Enumerable.Empty(), companyData, agreementConsents)); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), _mailingService, null!, null!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), _mailingService, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); // Act - async Task Act() => await sut.SubmitRegistrationAsync(applicationId, userId) + async Task Act() => await sut.SubmitRegistrationAsync(applicationId) .ConfigureAwait(false); // Assert @@ -2051,6 +2185,7 @@ public async Task SubmitRegistrationAsync_WithNotExistingCity_ThrowsConflictExce { // Arrange var userId = Guid.NewGuid(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { UserId = userId }); var applicationId = _fixture.Create(); var uniqueIds = _fixture.CreateMany(3).ToImmutableArray(); var companyRoleIds = _fixture.CreateMany(3).ToImmutableArray(); @@ -2061,10 +2196,10 @@ 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>._)) .ReturnsLazily(() => new CompanyApplicationUserEmailData(CompanyApplicationStatusId.VERIFY, true, _fixture.Create(), Enumerable.Empty(), companyData, agreementConsents)); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), _mailingService, null!, null!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), _mailingService, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); // Act - async Task Act() => await sut.SubmitRegistrationAsync(applicationId, userId) + async Task Act() => await sut.SubmitRegistrationAsync(applicationId) .ConfigureAwait(false); // Assert @@ -2077,6 +2212,7 @@ public async Task SubmitRegistrationAsync_WithNotExistingCountry_ThrowsConflictE { // Arrange var userId = Guid.NewGuid(); + A.CallTo(() => _identityService.IdentityData).Returns(_identity with { UserId = userId }); var applicationId = _fixture.Create(); var uniqueIds = _fixture.CreateMany(3).ToImmutableArray(); var companyRoleIds = _fixture.CreateMany(3).ToImmutableArray(); @@ -2088,10 +2224,10 @@ 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>._)) .ReturnsLazily(() => new CompanyApplicationUserEmailData(CompanyApplicationStatusId.VERIFY, true, _fixture.Create(), Enumerable.Empty(), companyData, agreementConsents)); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), _mailingService, null!, null!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), _mailingService, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); // Act - async Task Act() => await sut.SubmitRegistrationAsync(applicationId, userId) + async Task Act() => await sut.SubmitRegistrationAsync(applicationId) .ConfigureAwait(false); // Assert @@ -2104,6 +2240,7 @@ public async Task SubmitRegistrationAsync_WithUserEmail_SendsMail() { // Arrange var applicationId = _fixture.Create(); + var now = DateTimeOffset.Now; var uniqueIds = _fixture.CreateMany(3).ToImmutableArray(); var companyRoleIds = _fixture.CreateMany(3).ToImmutableArray(); var agreementConsents = new List<(Guid AgreementId, ConsentStatusId ConsentStatusId)> @@ -2121,20 +2258,31 @@ public async Task SubmitRegistrationAsync_WithUserEmail_SendsMail() DocumentTypeId.COMMERCIAL_REGISTER_EXTRACT } }; + var application = _fixture.Build() + .With(x => x.Id, applicationId) + .Create(); + A.CallTo(() => _dateTimeProvider.OffsetNow).Returns(now); A.CallTo(() => _applicationRepository.GetOwnCompanyApplicationUserEmailDataAsync(A._, A._, A>._)) .Returns(new CompanyApplicationUserEmailData(CompanyApplicationStatusId.VERIFY, true, "test@mail.de", documents, companyData, agreementConsents)); - var sut = new RegistrationBusinessLogic(Options.Create(settings), _mailingService, null!, null!, null!, null!, _portalRepositories, _checklistService); + A.CallTo(() => _applicationRepository.AttachAndModifyCompanyApplication(applicationId, A>._)) + .Invokes((Guid _, Action setOptionalFields) => + { + setOptionalFields.Invoke(application); + }); + var sut = new RegistrationBusinessLogic(Options.Create(settings), _mailingService, null!, null!, null!, null!, _portalRepositories, _checklistService, _identityService, _dateTimeProvider); // Act - var result = await sut.SubmitRegistrationAsync(applicationId, _identity.UserId) + var result = await sut.SubmitRegistrationAsync(applicationId) .ConfigureAwait(false); // Assert A.CallTo(() => _applicationRepository.GetOwnCompanyApplicationUserEmailDataAsync(applicationId, _identity.UserId, A>.That.IsSameSequenceAs(new[] { DocumentTypeId.COMMERCIAL_REGISTER_EXTRACT }))) .MustHaveHappenedOnceExactly(); + A.CallTo(() => _applicationRepository.AttachAndModifyCompanyApplication(applicationId, A>._)).MustHaveHappenedOnceExactly(); A.CallTo(() => _checklistService.CreateInitialChecklistAsync(applicationId)).MustHaveHappenedOnceExactly(); A.CallTo(() => _mailingService.SendMails(A._, A>._, A>._)).MustHaveHappened(); result.Should().BeTrue(); + application.DateLastChanged.Should().Be(now); } [Fact] @@ -2142,6 +2290,7 @@ public async Task SubmitRegistrationAsync_WithoutUserEmail_DoesntSendMail() { // Arrange var applicationId = _fixture.Create(); + var now = DateTimeOffset.Now; var uniqueIds = _fixture.CreateMany(3).ToImmutableArray(); var companyRoleIds = _fixture.CreateMany(3).ToImmutableArray(); var agreementConsents = new List<(Guid AgreementId, ConsentStatusId ConsentStatusId)> @@ -2159,20 +2308,31 @@ public async Task SubmitRegistrationAsync_WithoutUserEmail_DoesntSendMail() DocumentTypeId.COMMERCIAL_REGISTER_EXTRACT } }; + var application = _fixture.Build() + .With(x => x.Id, applicationId) + .Create(); + A.CallTo(() => _dateTimeProvider.OffsetNow).Returns(now); A.CallTo(() => _applicationRepository.GetOwnCompanyApplicationUserEmailDataAsync(A._, A._, A>._)) .Returns(new CompanyApplicationUserEmailData(CompanyApplicationStatusId.VERIFY, true, null, documents, companyData, agreementConsents)); - var sut = new RegistrationBusinessLogic(Options.Create(settings), _mailingService, null!, null!, null!, A.Fake>(), _portalRepositories, _checklistService); + A.CallTo(() => _applicationRepository.AttachAndModifyCompanyApplication(applicationId, A>._)) + .Invokes((Guid _, Action setOptionalFields) => + { + setOptionalFields.Invoke(application); + }); + var sut = new RegistrationBusinessLogic(Options.Create(settings), _mailingService, null!, null!, null!, A.Fake>(), _portalRepositories, _checklistService, _identityService, _dateTimeProvider); // Act - var result = await sut.SubmitRegistrationAsync(applicationId, _identity.UserId) + var result = await sut.SubmitRegistrationAsync(applicationId) .ConfigureAwait(false); // Assert A.CallTo(() => _applicationRepository.GetOwnCompanyApplicationUserEmailDataAsync(applicationId, _identity.UserId, A>.That.IsSameSequenceAs(new[] { DocumentTypeId.COMMERCIAL_REGISTER_EXTRACT }))) .MustHaveHappenedOnceExactly(); + A.CallTo(() => _applicationRepository.AttachAndModifyCompanyApplication(applicationId, A>._)).MustHaveHappenedOnceExactly(); A.CallTo(() => _checklistService.CreateInitialChecklistAsync(applicationId)).MustHaveHappenedOnceExactly(); A.CallTo(() => _mailingService.SendMails(A._, A>._, A>._)).MustNotHaveHappened(); result.Should().BeTrue(); + application.DateLastChanged.Should().Be(now); } #endregion @@ -2196,7 +2356,10 @@ public async Task GetCompanyIdentifiers_ReturnsExpectedOutput() null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); + // Act var result = await sut.GetCompanyIdentifiers(_fixture.Create()).ConfigureAwait(false); @@ -2225,7 +2388,9 @@ public async Task GetCompanyIdentifiers_InvalidCountry_Throws() null!, null!, _portalRepositories, - null!); + null!, + _identityService, + _dateTimeProvider); var countryCode = _fixture.Create(); @@ -2249,10 +2414,10 @@ 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!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); // Act - var result = await sut.GetRegistrationDataAsync(_existingApplicationId, _identity.CompanyId).ConfigureAwait(false); + var result = await sut.GetRegistrationDataAsync(_existingApplicationId).ConfigureAwait(false); // Assert result.Should().NotBeNull(); @@ -2294,10 +2459,10 @@ 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!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); // Act - var Act = () => sut.GetRegistrationDataAsync(applicationId, _identity.CompanyId); + var Act = () => sut.GetRegistrationDataAsync(applicationId); // Assert var result = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -2313,10 +2478,10 @@ 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!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); // Act - var Act = () => sut.GetRegistrationDataAsync(applicationId, _identity.CompanyId); + var Act = () => sut.GetRegistrationDataAsync(applicationId); // Assert var result = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -2332,10 +2497,10 @@ 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!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); // Act - var Act = () => sut.GetRegistrationDataAsync(applicationId, _identity.CompanyId); + var Act = () => sut.GetRegistrationDataAsync(applicationId); // Assert var result = await Assert.ThrowsAsync(Act).ConfigureAwait(false); @@ -2352,7 +2517,7 @@ public async Task GetRegistrationDocumentAsync_ReturnsExpectedResult() var content = new byte[7]; A.CallTo(() => _documentRepository.GetDocumentAsync(documentId, A>._)) .ReturnsLazily(() => new ValueTuple(content, "test.json", true, MediaTypeId.JSON)); - var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); //Act var result = await sut.GetRegistrationDocumentAsync(documentId).ConfigureAwait(false); @@ -2371,7 +2536,7 @@ public async Task GetRegistrationDocumentAsync_WithInvalidDocumentTypeId_ThrowsN var content = new byte[7]; A.CallTo(() => _documentRepository.GetDocumentAsync(documentId, A>._)) .ReturnsLazily(() => new ValueTuple(content, "test.json", false, MediaTypeId.JSON)); - var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); //Act var Act = () => sut.GetRegistrationDocumentAsync(documentId); @@ -2389,7 +2554,7 @@ public async Task GetRegistrationDocumentAsync_WithInvalidDocumentId_ThrowsNotFo var content = new byte[7]; A.CallTo(() => _documentRepository.GetDocumentAsync(documentId, A>._)) .ReturnsLazily(() => new ValueTuple()); - var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); //Act var Act = () => sut.GetRegistrationDocumentAsync(documentId); @@ -2411,10 +2576,10 @@ public async Task GetDocumentAsync_WithValidData_ReturnsExpected() .ReturnsLazily(() => new ValueTuple(documentId, true)); A.CallTo(() => _documentRepository.GetDocumentByIdAsync(documentId)) .ReturnsLazily(() => 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!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); // Act - var result = await sut.GetDocumentContentAsync(documentId, _identity.UserId).ConfigureAwait(false); + var result = await sut.GetDocumentContentAsync(documentId).ConfigureAwait(false); // Assert result.Should().NotBeNull(); @@ -2430,10 +2595,10 @@ public async Task GetDocumentAsync_WithoutDocument_ThrowsNotFoundException() var content = new byte[7]; A.CallTo(() => _documentRepository.GetDocumentIdWithCompanyUserCheckAsync(documentId, _identity.UserId)) .ReturnsLazily(() => new ValueTuple(Guid.Empty, false)); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); // Act - async Task Act() => await sut.GetDocumentContentAsync(documentId, _identity.UserId).ConfigureAwait(false); + async Task Act() => await sut.GetDocumentContentAsync(documentId).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -2447,10 +2612,10 @@ public async Task GetDocumentAsync_WithWrongUser_ThrowsForbiddenException() var documentId = Guid.NewGuid(); A.CallTo(() => _documentRepository.GetDocumentIdWithCompanyUserCheckAsync(documentId, _identity.UserId)) .ReturnsLazily(() => new ValueTuple(documentId, false)); - var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, null!, _portalRepositories, null!); + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); // Act - async Task Act() => await sut.GetDocumentContentAsync(documentId, _identity.UserId).ConfigureAwait(false); + async Task Act() => await sut.GetDocumentContentAsync(documentId).ConfigureAwait(false); // Assert var ex = await Assert.ThrowsAsync(Act); @@ -2459,6 +2624,275 @@ public async Task GetDocumentAsync_WithWrongUser_ThrowsForbiddenException() #endregion + #region SetInvitationStatus + + [Fact] + public async Task SetInvitationStatusAsync_ReturnsExpected() + { + // Arrange + var now = DateTimeOffset.Now; + var invitation = _fixture.Build() + .With(x => x.InvitationStatusId, InvitationStatusId.PENDING) + .Create(); + var application = _fixture.Build() + .With(x => x.Id, _existingApplicationId) + .Create(); + + A.CallTo(() => _dateTimeProvider.OffsetNow).Returns(now); + A.CallTo(() => _invitationRepository.GetInvitationStatusAsync(_identity.UserId)) + .Returns(invitation); + A.CallTo(() => _applicationRepository.AttachAndModifyCompanyApplication(A._, A>._)) + .Invokes((Guid _, Action setOptionalFields) => + { + setOptionalFields.Invoke(application); + }); + var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); + + // Act + var result = await sut.SetInvitationStatusAsync().ConfigureAwait(false); + + // Assert + A.CallTo(() => _invitationRepository.GetInvitationStatusAsync(_identity.UserId)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _applicationRepository.AttachAndModifyCompanyApplication(A._, A>._)).MustHaveHappenedOnceExactly(); + invitation.InvitationStatusId.Should().Be(InvitationStatusId.ACCEPTED); + application.DateLastChanged.Should().Be(now); + } + + [Fact] + public async Task SetInvitationStatusAsync_Throws_ForbiddenException() + { + // Arrange + A.CallTo(() => _invitationRepository.GetInvitationStatusAsync(A._)) + .Returns((Invitation)null!); + var sut = new RegistrationBusinessLogic(_options, null!, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); + + //Act + var Act = async () => await sut.SetInvitationStatusAsync().ConfigureAwait(false); + + // Assert + var result = await Assert.ThrowsAsync(Act).ConfigureAwait(false); + result.Message.Should().Be("user is not associated with invitation"); + } + + #endregion + + #region DeleteRegistrationDocument + + [Fact] + public async Task DeleteRegistrationDocumentAsync_ReturnsExpected() + { + // Arrange + var now = DateTimeOffset.Now; + var documentId = _fixture.Create(); + var applicationIds = new[] { + _fixture.Create(), + _fixture.Create() + }; + var modifiedApplication = new List<(CompanyApplication Initial, CompanyApplication Modified)>(); + var settings = new RegistrationSettings + { + ApplicationStatusIds = new[]{ + CompanyApplicationStatusId.CONFIRMED, + CompanyApplicationStatusId.SUBMITTED, + CompanyApplicationStatusId.DECLINED + }, + DocumentTypeIds = new[]{ + DocumentTypeId.CX_FRAME_CONTRACT, + DocumentTypeId.COMMERCIAL_REGISTER_EXTRACT + } + }; + A.CallTo(() => _dateTimeProvider.OffsetNow).Returns(now); + + A.CallTo(() => _applicationRepository.AttachAndModifyCompanyApplications(A?, Action)>>._)) + .Invokes((IEnumerable<(Guid CompanyApplicationId, Action? Initialize, Action Modify)> companyApplicationKeyActions) => + { + foreach (var x in companyApplicationKeyActions) + { + var initial = new CompanyApplication(x.CompanyApplicationId, Guid.Empty, default, default, default); + x.Initialize?.Invoke(initial); + var modified = new CompanyApplication(x.CompanyApplicationId, Guid.Empty, default, default, default); + x.Modify(modified); + modifiedApplication.Add((initial, modified)); + } + }); + 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!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); + + // Act + var result = await sut.DeleteRegistrationDocumentAsync(documentId).ConfigureAwait(false); + + // Assert + A.CallTo(() => _documentRepository.GetDocumentDetailsForApplicationUntrackedAsync(documentId, _identity.CompanyId, settings.ApplicationStatusIds)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _documentRepository.RemoveDocument(documentId)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _applicationRepository.AttachAndModifyCompanyApplications(A?, Action)>>.That.Matches(x => x.Count() == 2))).MustHaveHappenedOnceExactly(); + A.CallTo(() => _portalRepositories.SaveAsync()).MustHaveHappenedOnceExactly(); + result.Should().BeTrue(); + modifiedApplication.Should().HaveCount(2).And.Satisfy( + x => x.Modified.DateLastChanged == now && x.Initial.Id == applicationIds[0], + x => x.Modified.DateLastChanged == now && x.Initial.Id == applicationIds[1] + ); + + } + + [Fact] + public async Task DeleteRegistrationDocumentAsync_DocumentTypeId_ConflictException() + { + // Arrange + var documentId = _fixture.Create(); + var applicationId = _fixture.CreateMany(); + var settings = new RegistrationSettings + { + ApplicationStatusIds = new[]{ + CompanyApplicationStatusId.CONFIRMED, + CompanyApplicationStatusId.SUBMITTED, + CompanyApplicationStatusId.DECLINED + }, + DocumentTypeIds = new[]{ + DocumentTypeId.CX_FRAME_CONTRACT, + DocumentTypeId.COMMERCIAL_REGISTER_EXTRACT + } + }; + 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!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); + + // Act + var Act = async () => await sut.DeleteRegistrationDocumentAsync(documentId).ConfigureAwait(false); + + // Assert + var result = await Assert.ThrowsAsync(Act).ConfigureAwait(false); + result.Message.Should().Be($"Document deletion is not allowed. DocumentType must be either :{string.Join(",", settings.DocumentTypeIds)}"); + } + + [Fact] + public async Task DeleteRegistrationDocumentAsync_Throws_NotFoundException() + { + // Arrange; + A.CallTo(() => _documentRepository.GetDocumentDetailsForApplicationUntrackedAsync(A._, _identity.CompanyId, A>._)) + .Returns(new ValueTuple>()); + + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); + + // Act + var Act = async () => await sut.DeleteRegistrationDocumentAsync(_fixture.Create()).ConfigureAwait(false); + + // Assert + var result = await Assert.ThrowsAsync(Act).ConfigureAwait(false); + result.Message.Should().Be("Document does not exist."); + } + + [Fact] + public async Task DeleteRegistrationDocumentAsync_Throws_ConflictException() + { + // Arrange; + var documentId = _fixture.Create(); + var applicationId = _fixture.CreateMany(); + var settings = new RegistrationSettings + { + ApplicationStatusIds = new[]{ + CompanyApplicationStatusId.CONFIRMED, + CompanyApplicationStatusId.SUBMITTED, + CompanyApplicationStatusId.DECLINED + }, + DocumentTypeIds = new[]{ + DocumentTypeId.CX_FRAME_CONTRACT, + DocumentTypeId.COMMERCIAL_REGISTER_EXTRACT + } + }; + 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!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); + + // Act + var Act = async () => await sut.DeleteRegistrationDocumentAsync(documentId).ConfigureAwait(false); + + // Assert + var result = await Assert.ThrowsAsync(Act).ConfigureAwait(false); + result.Message.Should().Be("Document deletion is not allowed. Application is already closed."); + } + + [Fact] + public async Task DeleteRegistrationDocumentAsync_Throws_ForbiddenException() + { + // Arrange; + var documentId = _fixture.Create(); + var applicationId = _fixture.CreateMany(); + var settings = new RegistrationSettings + { + ApplicationStatusIds = new[]{ + CompanyApplicationStatusId.CONFIRMED, + CompanyApplicationStatusId.SUBMITTED, + CompanyApplicationStatusId.DECLINED + }, + DocumentTypeIds = new[]{ + DocumentTypeId.CX_FRAME_CONTRACT, + DocumentTypeId.COMMERCIAL_REGISTER_EXTRACT + } + }; + 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!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); + + // Act + var Act = async () => await sut.DeleteRegistrationDocumentAsync(documentId).ConfigureAwait(false); + + // Assert + var result = await Assert.ThrowsAsync(Act).ConfigureAwait(false); + result.Message.Should().Be("User is not allowed to delete this document"); + } + + [Fact] + public async Task DeleteRegistrationDocumentAsync_DocumentStatusId_Throws_ConflictException() + { + // Arrange; + var documentId = _fixture.Create(); + var applicationId = _fixture.CreateMany(); + var settings = new RegistrationSettings + { + ApplicationStatusIds = new[]{ + CompanyApplicationStatusId.CONFIRMED, + CompanyApplicationStatusId.SUBMITTED, + CompanyApplicationStatusId.DECLINED + }, + DocumentTypeIds = new[]{ + DocumentTypeId.CX_FRAME_CONTRACT, + DocumentTypeId.COMMERCIAL_REGISTER_EXTRACT + } + }; + 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!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); + + // Act + var Act = async () => await sut.DeleteRegistrationDocumentAsync(documentId).ConfigureAwait(false); + + // Assert + var result = await Assert.ThrowsAsync(Act).ConfigureAwait(false); + result.Message.Should().Be("Document deletion is not allowed. The document is locked."); + } + + [Fact] + public async Task DeleteRegistrationDocumentAsync_Throws_ControllerArgumentException() + { + // Arrange; + var sut = new RegistrationBusinessLogic(Options.Create(new RegistrationSettings()), null!, null!, null!, null!, null!, _portalRepositories, null!, _identityService, _dateTimeProvider); + + // Act + var Act = async () => await sut.DeleteRegistrationDocumentAsync(default).ConfigureAwait(false); + + // Assert + var result = await Assert.ThrowsAsync(Act).ConfigureAwait(false); + result.Message.Should().Be("documentId must not be empty"); + } + + #endregion + #region Setup private void SetupRepositories() diff --git a/tests/registration/Registration.Service.Tests/Controller/NetworkControllerTests.cs b/tests/registration/Registration.Service.Tests/Controller/NetworkControllerTests.cs new file mode 100644 index 0000000000..a606c4aa70 --- /dev/null +++ b/tests/registration/Registration.Service.Tests/Controller/NetworkControllerTests.cs @@ -0,0 +1,57 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 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 AutoFixture; +using FakeItEasy; +using FluentAssertions; +using Org.Eclipse.TractusX.Portal.Backend.Registration.Service.BusinessLogic; +using Org.Eclipse.TractusX.Portal.Backend.Registration.Service.Controllers; +using Org.Eclipse.TractusX.Portal.Backend.Registration.Service.Model; +using Xunit; + +namespace Org.Eclipse.TractusX.Portal.Backend.Registration.Service.Tests.Controller; + +public class NetworkControllerTests +{ + private readonly INetworkBusinessLogic _logic; + private readonly NetworkController _controller; + private readonly Fixture _fixture; + + public NetworkControllerTests() + { + _fixture = new Fixture(); + _logic = A.Fake(); + this._controller = new NetworkController(_logic); + } + + [Fact] + public async Task Submit_ReturnsExpected() + { + // Arrange + var data = _fixture.Create(); + + // Act + var result = await this._controller.Submit(data).ConfigureAwait(false); + + // Assert + result.StatusCode.Should().Be(204); + A.CallTo(() => _logic.Submit(A._)) + .MustHaveHappenedOnceExactly(); + } +} diff --git a/tests/registration/Registration.Service.Tests/Controller/RegistrationControllerTest.cs b/tests/registration/Registration.Service.Tests/Controller/RegistrationControllerTest.cs index 49636663fc..384b1c7d36 100644 --- a/tests/registration/Registration.Service.Tests/Controller/RegistrationControllerTest.cs +++ b/tests/registration/Registration.Service.Tests/Controller/RegistrationControllerTest.cs @@ -96,14 +96,14 @@ public async Task GetUploadedDocumentsAsync_ReturnsExpectedResult() var applicationId = _fixture.Create(); var uploadDocuments = _fixture.CreateMany(3); - A.CallTo(() => _registrationBusinessLogicFake.GetUploadedDocumentsAsync(applicationId, DocumentTypeId.APP_CONTRACT, _identity.UserId)) + A.CallTo(() => _registrationBusinessLogicFake.GetUploadedDocumentsAsync(applicationId, DocumentTypeId.APP_CONTRACT)) .Returns(uploadDocuments); //Act var result = await _controller.GetUploadedDocumentsAsync(applicationId, DocumentTypeId.APP_CONTRACT).ConfigureAwait(false); //Assert - A.CallTo(() => _registrationBusinessLogicFake.GetUploadedDocumentsAsync(applicationId, DocumentTypeId.APP_CONTRACT, _identity.UserId)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _registrationBusinessLogicFake.GetUploadedDocumentsAsync(applicationId, DocumentTypeId.APP_CONTRACT)).MustHaveHappenedOnceExactly(); result.Should().HaveSameCount(uploadDocuments); result.Should().ContainInOrder(uploadDocuments); @@ -115,14 +115,14 @@ public async Task SubmitCompanyRoleConsentToAgreementsAsync_WithValidData_Return // Arrange var applicationId = _fixture.Create(); var data = _fixture.Create(); - A.CallTo(() => _registrationBusinessLogicFake.SubmitRoleConsentAsync(applicationId, data, _identity.UserId, _identity.CompanyId)) + A.CallTo(() => _registrationBusinessLogicFake.SubmitRoleConsentAsync(applicationId, data)) .Returns(1); //Act var result = await this._controller.SubmitCompanyRoleConsentToAgreementsAsync(applicationId, data).ConfigureAwait(false); // Assert - A.CallTo(() => _registrationBusinessLogicFake.SubmitRoleConsentAsync(applicationId, data, _identity.UserId, _identity.CompanyId)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _registrationBusinessLogicFake.SubmitRoleConsentAsync(applicationId, data)).MustHaveHappenedOnceExactly(); result.Should().Be(1); } @@ -155,14 +155,14 @@ public async Task GetDocumentContentFileAsync_WithValidData_ReturnsOk() const string contentType = "application/pdf"; var id = Guid.NewGuid(); var content = Encoding.UTF8.GetBytes("This is just test content"); - A.CallTo(() => _registrationBusinessLogicFake.GetDocumentContentAsync(id, _identity.UserId)) + A.CallTo(() => _registrationBusinessLogicFake.GetDocumentContentAsync(id)) .Returns((fileName, content, contentType)); //Act var result = await this._controller.GetDocumentContentFileAsync(id).ConfigureAwait(false); //Assert - A.CallTo(() => _registrationBusinessLogicFake.GetDocumentContentAsync(id, _identity.UserId)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _registrationBusinessLogicFake.GetDocumentContentAsync(id)).MustHaveHappenedOnceExactly(); result.Should().BeOfType(); ((FileContentResult)result).ContentType.Should().Be(contentType); } @@ -191,14 +191,14 @@ public async Task InviteNewUserAsync_WithValidData_ReturnsExpected() var applicationId = _fixture.Create(); var creationInfo = _fixture.Create(); - A.CallTo(() => _registrationBusinessLogicFake.InviteNewUserAsync(A._, A._, A<(Guid, Guid)>._)) + A.CallTo(() => _registrationBusinessLogicFake.InviteNewUserAsync(A._, A._)) .Returns(1); //Act var result = await this._controller.InviteNewUserAsync(applicationId, creationInfo).ConfigureAwait(false); // Assert - A.CallTo(() => _registrationBusinessLogicFake.InviteNewUserAsync(applicationId, creationInfo, new(_identity.UserId, _identity.CompanyId))).MustHaveHappenedOnceExactly(); + A.CallTo(() => _registrationBusinessLogicFake.InviteNewUserAsync(applicationId, creationInfo)).MustHaveHappenedOnceExactly(); result.Should().Be(1); } @@ -207,14 +207,14 @@ public async Task GetApplicationsWithStatusAsync_WithValidData_ReturnsExpected() { // Arrange var companyApplicationWithStatus = _fixture.CreateMany(2); - A.CallTo(() => _registrationBusinessLogicFake.GetAllApplicationsForUserWithStatus(_identity.CompanyId)) + A.CallTo(() => _registrationBusinessLogicFake.GetAllApplicationsForUserWithStatus()) .Returns(companyApplicationWithStatus.ToAsyncEnumerable()); //Act var result = await this._controller.GetApplicationsWithStatusAsync().ToListAsync().ConfigureAwait(false); // Assert - A.CallTo(() => _registrationBusinessLogicFake.GetAllApplicationsForUserWithStatus(_identity.CompanyId)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _registrationBusinessLogicFake.GetAllApplicationsForUserWithStatus()).MustHaveHappenedOnceExactly(); result.Should().HaveCount(2); } } diff --git a/tests/registration/Registration.Service.Tests/Registration.Service.Tests.csproj b/tests/registration/Registration.Service.Tests/Registration.Service.Tests.csproj index 131544a1bc..8ae32c1fe9 100644 --- a/tests/registration/Registration.Service.Tests/Registration.Service.Tests.csproj +++ b/tests/registration/Registration.Service.Tests/Registration.Service.Tests.csproj @@ -1,55 +1,56 @@ - - - - - - Org.Eclipse.TractusX.Portal.Backend.Registration.Service.Tests - net7.0 - enable - enable - false - - - - - - - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - - - - + + + + + + Org.Eclipse.TractusX.Portal.Backend.Registration.Service.Tests + Org.Eclipse.TractusX.Portal.Backend.Registration.Service.Tests + net7.0 + enable + enable + false + + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + +