diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ee9a165cc..61ae33f47d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,16 @@ New features, fixed bugs, known defects and other noteworthy changes to each release of the Catena-X Portal Backend. +## 2.0.0-RC5 + +### Changes +* **Administration Service** +* adjusted POST: api/administration/companydata/useCaseParticipation to create framework credentials with the ssi credential issuer + +### Bugfix +* **Process Worker** +* adjusted technical user creation process + ## 2.0.0-RC4 ### Changes diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 0b9efcbb0d..82e213dee9 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -20,6 +20,6 @@ 2.0.0 - RC4 + RC5 diff --git a/src/administration/Administration.Service/BusinessLogic/CompanyDataBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/CompanyDataBusinessLogic.cs index 064c5d2fb8..bbcd40dede 100644 --- a/src/administration/Administration.Service/BusinessLogic/CompanyDataBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/CompanyDataBusinessLogic.cs @@ -27,6 +27,7 @@ using Org.Eclipse.TractusX.Portal.Backend.Framework.Linq; using Org.Eclipse.TractusX.Portal.Backend.Framework.Models; using Org.Eclipse.TractusX.Portal.Backend.Framework.Web; +using Org.Eclipse.TractusX.Portal.Backend.IssuerComponent.Library.BusinessLogic; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Extensions; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; @@ -40,41 +41,25 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLogic; -public class CompanyDataBusinessLogic : ICompanyDataBusinessLogic +public class CompanyDataBusinessLogic( + IPortalRepositories portalRepositories, + ICustodianService custodianService, + IDateTimeProvider dateTimeProvider, + IIdentityService identityService, + IMailingProcessCreation mailingProcessCreation, + IIssuerComponentBusinessLogic _issuerComponentBusinessLogic, + IOptions options) : ICompanyDataBusinessLogic { private static readonly JsonSerializerOptions Options = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; - private readonly IPortalRepositories _portalRepositories; - private readonly ICustodianService _custodianService; - private readonly IDateTimeProvider _dateTimeProvider; - private readonly IIdentityData _identityData; - private readonly IMailingProcessCreation _mailingProcessCreation; - private readonly CompanyDataSettings _settings; - - /// - /// Constructor - /// - /// - /// - /// - /// - /// - /// - public CompanyDataBusinessLogic(IPortalRepositories portalRepositories, ICustodianService custodianService, IDateTimeProvider dateTimeProvider, IIdentityService identityService, IMailingProcessCreation mailingProcessCreation, IOptions options) - { - _portalRepositories = portalRepositories; - _custodianService = custodianService; - _dateTimeProvider = dateTimeProvider; - _identityData = identityService.IdentityData; - _mailingProcessCreation = mailingProcessCreation; - _settings = options.Value; - } + private readonly IIdentityData _identityData = identityService.IdentityData; + private readonly CompanyDataSettings _settings = options.Value; /// public async Task GetCompanyDetailsAsync() { var companyId = _identityData.CompanyId; - var result = await _portalRepositories.GetInstance().GetCompanyDetailsAsync(companyId) + var result = await portalRepositories.GetInstance().GetCompanyDetailsAsync(companyId) .ConfigureAwait(ConfigureAwaitOptions.None); if (result == null) { @@ -86,14 +71,14 @@ public async Task GetCompanyDetailsAsync() /// public IAsyncEnumerable GetCompanyAssigendUseCaseDetailsAsync() => - _portalRepositories.GetInstance() + portalRepositories.GetInstance() .GetCompanyAssigendUseCaseDetailsAsync(_identityData.CompanyId); /// public async Task CreateCompanyAssignedUseCaseDetailsAsync(Guid useCaseId) { var companyId = _identityData.CompanyId; - var companyRepositories = _portalRepositories.GetInstance(); + var companyRepositories = portalRepositories.GetInstance(); var useCaseDetails = await companyRepositories.GetCompanyStatusAndUseCaseIdAsync(companyId, useCaseId) .ConfigureAwait(ConfigureAwaitOptions.None); if (!useCaseDetails.IsActiveCompanyStatus) @@ -107,7 +92,7 @@ public async Task CreateCompanyAssignedUseCaseDetailsAsync(Guid useCaseId) } companyRepositories.CreateCompanyAssignedUseCase(companyId, useCaseId); - await _portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); + await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); return true; } @@ -115,7 +100,7 @@ public async Task CreateCompanyAssignedUseCaseDetailsAsync(Guid useCaseId) public async Task RemoveCompanyAssignedUseCaseDetailsAsync(Guid useCaseId) { var companyId = _identityData.CompanyId; - var companyRepositories = _portalRepositories.GetInstance(); + var companyRepositories = portalRepositories.GetInstance(); var useCaseDetails = await companyRepositories.GetCompanyStatusAndUseCaseIdAsync(companyId, useCaseId) .ConfigureAwait(ConfigureAwaitOptions.None); if (!useCaseDetails.IsActiveCompanyStatus) @@ -129,18 +114,18 @@ public async Task RemoveCompanyAssignedUseCaseDetailsAsync(Guid useCaseId) } companyRepositories.RemoveCompanyAssignedUseCase(companyId, useCaseId); - await _portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); + await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); } public async IAsyncEnumerable GetCompanyRoleAndConsentAgreementDetailsAsync(string? languageShortName) { var companyId = _identityData.CompanyId; - if (languageShortName != null && !await _portalRepositories.GetInstance().IsValidLanguageCode(languageShortName).ConfigureAwait(ConfigureAwaitOptions.None)) + if (languageShortName != null && !await portalRepositories.GetInstance().IsValidLanguageCode(languageShortName).ConfigureAwait(ConfigureAwaitOptions.None)) { throw new ControllerArgumentException($"language {languageShortName} is not a valid languagecode"); } - var companyRepositories = _portalRepositories.GetInstance(); + var companyRepositories = portalRepositories.GetInstance(); var statusData = await companyRepositories.GetCompanyStatusDataAsync(companyId).ConfigureAwait(ConfigureAwaitOptions.None); if (statusData == default) { @@ -180,7 +165,7 @@ public async Task CreateCompanyRoleAndConsentAgreementDetailsAsync(IEnumerable(); + var companyRepositories = portalRepositories.GetInstance(); var result = await companyRepositories .GetCompanyRolesDataAsync(_identityData.CompanyId, companyRoleConsentDetails.Select(x => x.CompanyRole)) .ConfigureAwait(ConfigureAwaitOptions.None); @@ -239,15 +224,15 @@ public async Task CreateCompanyRoleAndConsentAgreementDetailsAsync(IEnumerable $"{x.CompanyRoleId}: [{string.Join(", ", x.ExtraAgreementIds)}]"))}]"); } - _portalRepositories.GetInstance().AddAttachAndModifyConsents( + portalRepositories.GetInstance().AddAttachAndModifyConsents( result.ConsentStatusDetails, joined.SelectMany(x => x.Agreements).DistinctBy(active => active.AgreementId) .Select(active => (active.AgreementId, active.ConsentStatus)).ToList(), _identityData.CompanyId, _identityData.IdentityId, - _dateTimeProvider.OffsetNow); + dateTimeProvider.OffsetNow); - var companyRolesRepository = _portalRepositories.GetInstance(); + var companyRolesRepository = portalRepositories.GetInstance(); companyRolesRepository.CreateCompanyAssignedRoles(_identityData.CompanyId, joined.Where(j => j.AllActiveAgreements && !result.CompanyRoleIds.Contains(j.CompanyRoleId)) @@ -256,12 +241,12 @@ public async Task CreateCompanyRoleAndConsentAgreementDetailsAsync(IEnumerable j.AllInActiveAgreements && result.CompanyRoleIds.Contains(j.CompanyRoleId)) .Select(x => x.CompanyRoleId)); - await _portalRepositories.SaveAsync(); + await portalRepositories.SaveAsync(); } /// public async Task> GetUseCaseParticipationAsync(string? language) => - await _portalRepositories + await portalRepositories .GetInstance() .GetUseCaseParticipationForCompany(_identityData.CompanyId, language ?? Constants.DefaultLanguage) .Select(x => new UseCaseParticipationData( @@ -287,7 +272,7 @@ await _portalRepositories /// public async Task> GetSsiCertificatesAsync() => - await _portalRepositories + await portalRepositories .GetInstance() .GetSsiCertificates(_identityData.CompanyId) .Select(x => new SsiCertificateData( @@ -302,20 +287,8 @@ await _portalRepositories .ConfigureAwait(false); /// - public async Task CreateUseCaseParticipation(UseCaseParticipationCreationData data, CancellationToken cancellationToken) - { - var (verifiedCredentialExternalTypeDetailId, credentialTypeId, document) = data; - var documentContentType = document.ContentType.ParseMediaTypeId(); - documentContentType.CheckDocumentContentType(_settings.UseCaseParticipationMediaTypes); - - var companyCredentialDetailsRepository = _portalRepositories.GetInstance(); - if (!await companyCredentialDetailsRepository.CheckCredentialTypeIdExistsForExternalTypeDetailVersionId(verifiedCredentialExternalTypeDetailId, credentialTypeId).ConfigureAwait(ConfigureAwaitOptions.None)) - { - throw new ControllerArgumentException($"VerifiedCredentialExternalTypeDetail {verifiedCredentialExternalTypeDetailId} does not exist"); - } - - await HandleSsiCreationAsync(credentialTypeId, VerifiedCredentialTypeKindId.USE_CASE, verifiedCredentialExternalTypeDetailId, document, documentContentType, companyCredentialDetailsRepository, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); - } + public Task CreateUseCaseParticipation(UseCaseParticipationCreationData data, CancellationToken cancellationToken) => + _issuerComponentBusinessLogic.CreateFrameworkCredentialData(data.VerifiedCredentialExternalTypeDetailId, data.Framework, _identityData.IdentityId, cancellationToken); /// public async Task CreateSsiCertificate(SsiCertificateCreationData data, CancellationToken cancellationToken) @@ -324,7 +297,7 @@ public async Task CreateSsiCertificate(SsiCertificateCreationData data, Cancella var documentContentType = document.ContentType.ParseMediaTypeId(); documentContentType.CheckDocumentContentType(_settings.SsiCertificateMediaTypes); - var companyCredentialDetailsRepository = _portalRepositories.GetInstance(); + var companyCredentialDetailsRepository = portalRepositories.GetInstance(); if (!await companyCredentialDetailsRepository.CheckSsiCertificateType(credentialTypeId).ConfigureAwait(ConfigureAwaitOptions.None)) { throw new ControllerArgumentException($"{credentialTypeId} is not assigned to a certificate"); @@ -348,7 +321,7 @@ private async Task HandleSsiCreationAsync( } var (documentContent, hash) = await document.GetContentAndHash(cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); - var doc = _portalRepositories.GetInstance().CreateDocument(document.FileName, documentContent, + var doc = portalRepositories.GetInstance().CreateDocument(document.FileName, documentContent, hash, mediaTypeId, DocumentTypeId.PRESENTATION, x => { x.CompanyUserId = _identityData.IdentityId; @@ -363,7 +336,7 @@ private async Task HandleSsiCreationAsync( } }); - await _portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); + await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); } /// @@ -372,7 +345,7 @@ public async Task CreateCompanyCertificate(CompanyCertificateCreationData data, var documentContentType = data.Document.ContentType.ParseMediaTypeId(); documentContentType.CheckDocumentContentType(_settings.CompanyCertificateMediaTypes); - var companyCertificateRepository = _portalRepositories.GetInstance(); + var companyCertificateRepository = portalRepositories.GetInstance(); if (!await companyCertificateRepository.CheckCompanyCertificateType(data.CertificateType).ConfigureAwait(ConfigureAwaitOptions.None)) { throw new ControllerArgumentException($"{data.CertificateType} is not assigned to a certificate"); @@ -389,7 +362,7 @@ private async Task HandleCompanyCertificateCreationAsync(CompanyCertificateTypeI CancellationToken cancellationToken) { var (documentContent, hash) = await document.GetContentAndHash(cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); - var doc = _portalRepositories.GetInstance().CreateDocument(document.FileName, documentContent, + var doc = portalRepositories.GetInstance().CreateDocument(document.FileName, documentContent, hash, mediaTypeId, DocumentTypeId.COMPANY_CERTIFICATE, x => { x.CompanyUserId = _identityData.IdentityId; @@ -402,13 +375,13 @@ private async Task HandleCompanyCertificateCreationAsync(CompanyCertificateTypeI x.ValidTill = expiryDate?.ToUniversalTime(); }); - await _portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); + await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); } /// public Task> GetCredentials(int page, int size, CompanySsiDetailStatusId? companySsiDetailStatusId, VerifiedCredentialTypeId? credentialTypeId, string? companyName, CompanySsiDetailSorting? sorting) { - var query = _portalRepositories + var query = portalRepositories .GetInstance() .GetAllCredentialDetails(companySsiDetailStatusId, credentialTypeId, companyName); var sortedQuery = sorting switch @@ -450,7 +423,7 @@ private async Task HandleCompanyCertificateCreationAsync(CompanyCertificateTypeI /// public async Task ApproveCredential(Guid credentialId, CancellationToken cancellationToken) { - var companySsiRepository = _portalRepositories.GetInstance(); + var companySsiRepository = portalRepositories.GetInstance(); var userId = _identityData.IdentityId; var (exists, data) = await companySsiRepository.GetSsiApprovalData(credentialId).ConfigureAwait(ConfigureAwaitOptions.None); if (!exists) @@ -475,7 +448,7 @@ public async Task ApproveCredential(Guid credentialId, CancellationToken cancell var typeValue = data.Type.GetEnumValue() ?? throw new UnexpectedConditionException($"VerifiedCredentialType {data.Type} does not exists"); var content = JsonSerializer.Serialize(new { Type = data.Type, CredentialId = credentialId }, Options); - _portalRepositories.GetInstance().CreateNotification(data.RequesterData.RequesterId, NotificationTypeId.CREDENTIAL_APPROVAL, false, n => + portalRepositories.GetInstance().CreateNotification(data.RequesterData.RequesterId, NotificationTypeId.CREDENTIAL_APPROVAL, false, n => { n.CreatorUserId = userId; n.Content = content; @@ -488,17 +461,17 @@ public async Task ApproveCredential(Guid credentialId, CancellationToken cancell c => { c.CompanySsiDetailStatusId = CompanySsiDetailStatusId.ACTIVE; - c.DateLastChanged = _dateTimeProvider.OffsetNow; + c.DateLastChanged = dateTimeProvider.OffsetNow; }); switch (data.Kind) { case VerifiedCredentialTypeKindId.USE_CASE: - await _custodianService.TriggerFrameworkAsync(data.Bpn, data.UseCaseDetailData!, cancellationToken) + await custodianService.TriggerFrameworkAsync(data.Bpn, data.UseCaseDetailData!, cancellationToken) .ConfigureAwait(ConfigureAwaitOptions.None); break; case VerifiedCredentialTypeKindId.CERTIFICATE: - await _custodianService.TriggerDismantlerAsync(data.Bpn, data.Type, cancellationToken) + await custodianService.TriggerDismantlerAsync(data.Bpn, data.Type, cancellationToken) .ConfigureAwait(ConfigureAwaitOptions.None); break; default: @@ -518,15 +491,15 @@ await _custodianService.TriggerDismantlerAsync(data.Bpn, data.Type, cancellation "expiryDate", data.ExpiryDate == null ? string.Empty : data.ExpiryDate.Value.ToString("o", CultureInfo.InvariantCulture) ) }); - _mailingProcessCreation.CreateMailProcess(data.RequesterData.RequesterEmail, "CredentialApproval", mailParameters); + mailingProcessCreation.CreateMailProcess(data.RequesterData.RequesterEmail, "CredentialApproval", mailParameters); } - await _portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); + await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); } /// public async Task RejectCredential(Guid credentialId) { - var companySsiRepository = _portalRepositories.GetInstance(); + var companySsiRepository = portalRepositories.GetInstance(); var userId = _identityData.IdentityId; var (exists, status, type, requesterId, requesterEmail, requesterFirstname, requesterLastname) = await companySsiRepository.GetSsiRejectionData(credentialId).ConfigureAwait(ConfigureAwaitOptions.None); if (!exists) @@ -541,7 +514,7 @@ public async Task RejectCredential(Guid credentialId) var typeValue = type.GetEnumValue() ?? throw new UnexpectedConditionException($"VerifiedCredentialType {type} does not exists"); var content = JsonSerializer.Serialize(new { Type = type, CredentialId = credentialId }, Options); - _portalRepositories.GetInstance().CreateNotification(requesterId, NotificationTypeId.CREDENTIAL_REJECTED, false, n => + portalRepositories.GetInstance().CreateNotification(requesterId, NotificationTypeId.CREDENTIAL_REJECTED, false, n => { n.CreatorUserId = userId; n.Content = content; @@ -554,7 +527,7 @@ public async Task RejectCredential(Guid credentialId) c => { c.CompanySsiDetailStatusId = CompanySsiDetailStatusId.INACTIVE; - c.DateLastChanged = _dateTimeProvider.OffsetNow; + c.DateLastChanged = dateTimeProvider.OffsetNow; }); if (!string.IsNullOrWhiteSpace(requesterEmail)) @@ -565,14 +538,14 @@ public async Task RejectCredential(Guid credentialId) KeyValuePair.Create("userName", !string.IsNullOrWhiteSpace(userName) ? userName : requesterEmail), KeyValuePair.Create("requestName", typeValue) }); - _mailingProcessCreation.CreateMailProcess(requesterEmail, "CredentialRejected", mailParameters); + mailingProcessCreation.CreateMailProcess(requesterEmail, "CredentialRejected", mailParameters); } - await _portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); + await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); } /// public IAsyncEnumerable GetCertificateTypes() => - _portalRepositories.GetInstance().GetCertificateTypes(_identityData.CompanyId); + portalRepositories.GetInstance().GetCertificateTypes(_identityData.CompanyId); /// public async IAsyncEnumerable GetCompanyCertificatesByBpn(string businessPartnerNumber) @@ -582,7 +555,7 @@ public async IAsyncEnumerable GetCompanyCertificatesB throw new ControllerArgumentException("businessPartnerNumber must not be empty"); } - var companyCertificateRepository = _portalRepositories.GetInstance(); + var companyCertificateRepository = portalRepositories.GetInstance(); var companyId = await companyCertificateRepository.GetCompanyIdByBpn(businessPartnerNumber).ConfigureAwait(ConfigureAwaitOptions.None); if (companyId == Guid.Empty) @@ -601,18 +574,18 @@ public async IAsyncEnumerable GetCompanyCertificatesB page, size, _settings.MaxPageSize, - _portalRepositories.GetInstance().GetActiveCompanyCertificatePaginationSource(sorting, certificateStatus, certificateType, _identityData.CompanyId)); + portalRepositories.GetInstance().GetActiveCompanyCertificatePaginationSource(sorting, certificateStatus, certificateType, _identityData.CompanyId)); public async Task GetDimServiceUrls() => new( - $"{await _portalRepositories.GetInstance().GetWalletServiceUrl(_identityData.CompanyId).ConfigureAwait(ConfigureAwaitOptions.None)}/oauth/token", + $"{await portalRepositories.GetInstance().GetWalletServiceUrl(_identityData.CompanyId).ConfigureAwait(ConfigureAwaitOptions.None)}/oauth/token", _settings.DecentralIdentityManagementAuthUrl ); /// public async Task DeleteCompanyCertificateAsync(Guid documentId) { - var companyCertificateRepository = _portalRepositories.GetInstance(); + var companyCertificateRepository = portalRepositories.GetInstance(); var details = await companyCertificateRepository.GetCompanyCertificateDocumentDetailsForIdUntrackedAsync(documentId, _identityData.CompanyId).ConfigureAwait(ConfigureAwaitOptions.None); @@ -635,7 +608,7 @@ public async Task DeleteCompanyCertificateAsync(Guid documentId) companyCertificateRepository.AttachAndModifyCompanyCertificateDocumentDetails(documentId, null, c => { c.DocumentStatusId = DocumentStatusId.INACTIVE; - c.DateLastChanged = _dateTimeProvider.OffsetNow; + c.DateLastChanged = dateTimeProvider.OffsetNow; }); if (certificateCount == 1) @@ -646,13 +619,13 @@ public async Task DeleteCompanyCertificateAsync(Guid documentId) }); } - return await _portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); + return await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); } /// public async Task<(string FileName, byte[] Content, string MediaType)> GetCompanyCertificateDocumentByCompanyIdAsync(Guid documentId) { - var documentDetails = await _portalRepositories.GetInstance() + var documentDetails = await portalRepositories.GetInstance() .GetCompanyCertificateDocumentByCompanyIdDataAsync(documentId, _identityData.CompanyId, DocumentTypeId.COMPANY_CERTIFICATE) .ConfigureAwait(ConfigureAwaitOptions.None); @@ -667,7 +640,7 @@ public async Task DeleteCompanyCertificateAsync(Guid documentId) /// public async Task<(string FileName, byte[] Content, string MediaType)> GetCompanyCertificateDocumentAsync(Guid documentId) { - var documentDetails = await _portalRepositories.GetInstance() + var documentDetails = await portalRepositories.GetInstance() .GetCompanyCertificateDocumentDataAsync(documentId, DocumentTypeId.COMPANY_CERTIFICATE) .ConfigureAwait(ConfigureAwaitOptions.None); diff --git a/src/administration/Administration.Service/BusinessLogic/ICompanyDataBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/ICompanyDataBusinessLogic.cs index 3c4c09443e..7d401ef57b 100644 --- a/src/administration/Administration.Service/BusinessLogic/ICompanyDataBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/ICompanyDataBusinessLogic.cs @@ -43,7 +43,7 @@ public interface ICompanyDataBusinessLogic Task> GetSsiCertificatesAsync(); - Task CreateUseCaseParticipation(UseCaseParticipationCreationData data, CancellationToken cancellationToken); + Task CreateUseCaseParticipation(UseCaseParticipationCreationData data, CancellationToken cancellationToken); Task CreateSsiCertificate(SsiCertificateCreationData data, CancellationToken cancellationToken); Task> GetCredentials(int page, int size, CompanySsiDetailStatusId? companySsiDetailStatusId, VerifiedCredentialTypeId? credentialTypeId, string? companyName, CompanySsiDetailSorting? sorting); diff --git a/src/administration/Administration.Service/BusinessLogic/ServiceAccountBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/ServiceAccountBusinessLogic.cs index 5a624f579e..49ca020a5f 100644 --- a/src/administration/Administration.Service/BusinessLogic/ServiceAccountBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/ServiceAccountBusinessLogic.cs @@ -36,6 +36,7 @@ using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Enums; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Models; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Service; +using ServiceAccountData = Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models.ServiceAccountData; namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLogic; @@ -318,10 +319,10 @@ public async Task HandleServiceAccountCreationCallback(Guid processId, Authentic switch (processData.ProcessTypeId) { case ProcessTypeId.OFFER_SUBSCRIPTION: - HandleOfferSubscriptionTechnicalUserCallback(processId, callbackData, context, processData.SubscriptionData ?? throw new UnexpectedConditionException("subcriptionData should never be null here")); + await HandleOfferSubscriptionTechnicalUserCallback(processId, callbackData, context, processData.SubscriptionData ?? throw new UnexpectedConditionException("subcriptionData should never be null here")).ConfigureAwait(false); break; case ProcessTypeId.DIM_TECHNICAL_USER: - HandleDimTechnicalUserCallback(callbackData, processData.ServiceAccountData ?? throw new UnexpectedConditionException("serviceAccountData should never be null here")); + await HandleDimTechnicalUserCallback(callbackData, processData.ServiceAccountData ?? throw new UnexpectedConditionException("serviceAccountData should never be null here")).ConfigureAwait(false); break; default: throw new ControllerArgumentException($"process {processId} has invalid processType {processData.ProcessTypeId}"); @@ -331,7 +332,7 @@ public async Task HandleServiceAccountCreationCallback(Guid processId, Authentic await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); } - private void HandleOfferSubscriptionTechnicalUserCallback(Guid processId, AuthenticationDetail callbackData, ManualProcessStepData context, (Guid? OfferSubscriptionId, Guid? CompanyId, string? OfferName) subscriptionData) + private async Task HandleOfferSubscriptionTechnicalUserCallback(Guid processId, AuthenticationDetail callbackData, ManualProcessStepData context, SubscriptionData subscriptionData) { if (subscriptionData.OfferSubscriptionId is null) { @@ -349,11 +350,11 @@ private void HandleOfferSubscriptionTechnicalUserCallback(Guid processId, Authen } var name = $"sa-{subscriptionData.OfferName}-{subscriptionData.OfferSubscriptionId}"; - CreateDimServiceAccount(callbackData, subscriptionData.CompanyId.Value, name, CompanyServiceAccountTypeId.MANAGED, x => x.OfferSubscriptionId = subscriptionData.OfferSubscriptionId); + await CreateDimServiceAccount(callbackData, subscriptionData.CompanyId.Value, name, CompanyServiceAccountTypeId.MANAGED, x => x.OfferSubscriptionId = subscriptionData.OfferSubscriptionId).ConfigureAwait(false); context.ScheduleProcessSteps([ProcessStepTypeId.TRIGGER_ACTIVATE_SUBSCRIPTION]); } - private void HandleDimTechnicalUserCallback(AuthenticationDetail callbackData, (string? ServiceAccountName, Guid? CompanyId) serviceAccountData) + private async Task HandleDimTechnicalUserCallback(AuthenticationDetail callbackData, ServiceAccountData serviceAccountData) { if (serviceAccountData.ServiceAccountName is null) { @@ -366,10 +367,10 @@ private void HandleDimTechnicalUserCallback(AuthenticationDetail callbackData, ( } var name = $"dim-{serviceAccountData.ServiceAccountName}"; - CreateDimServiceAccount(callbackData, serviceAccountData.CompanyId.Value, name, CompanyServiceAccountTypeId.OWN, null); + await CreateDimServiceAccount(callbackData, serviceAccountData.CompanyId.Value, name, CompanyServiceAccountTypeId.OWN, null).ConfigureAwait(false); } - private void CreateDimServiceAccount(AuthenticationDetail callbackData, Guid companyId, string name, CompanyServiceAccountTypeId serviceAccountTypeId, Action? setOptionalParameters) + private async Task CreateDimServiceAccount(AuthenticationDetail callbackData, Guid companyId, string name, CompanyServiceAccountTypeId serviceAccountTypeId, Action? setOptionalParameters) { var identity = portalRepositories.GetInstance().CreateIdentity(companyId, UserStatusId.ACTIVE, IdentityTypeId.COMPANY_SERVICE_ACCOUNT, null); var serviceAccountRepository = portalRepositories.GetInstance(); @@ -381,6 +382,13 @@ private void CreateDimServiceAccount(AuthenticationDetail callbackData, Guid com serviceAccountTypeId, setOptionalParameters); + var userRolesRepository = portalRepositories.GetInstance(); + var userRoleData = await userRolesRepository.GetUserRoleDataUntrackedAsync(_settings.DimCreationRoles).ToListAsync().ConfigureAwait(false); + foreach (var roleData in userRoleData) + { + userRolesRepository.CreateIdentityAssignedRole(serviceAccount.Id, roleData.UserRoleId); + } + var cryptoConfig = _settings.EncryptionConfigs.SingleOrDefault(x => x.Index == _settings.EncryptionConfigIndex) ?? throw new ConfigurationException($"EncryptionModeIndex {_settings.EncryptionConfigIndex} is not configured"); var (secret, initializationVector) = CryptoHelper.Encrypt(callbackData.ClientSecret, Convert.FromHexString(cryptoConfig.EncryptionKey), cryptoConfig.CipherMode, cryptoConfig.PaddingMode); diff --git a/src/administration/Administration.Service/Controllers/CompanyDataController.cs b/src/administration/Administration.Service/Controllers/CompanyDataController.cs index f53213157f..05ef342cc1 100644 --- a/src/administration/Administration.Service/Controllers/CompanyDataController.cs +++ b/src/administration/Administration.Service/Controllers/CompanyDataController.cs @@ -236,11 +236,8 @@ public IAsyncEnumerable GetCertificateTypes() => [Route("useCaseParticipation")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)] - public async Task CreateUseCaseParticipation([FromForm] UseCaseParticipationCreationData data, CancellationToken cancellationToken) - { - await _logic.CreateUseCaseParticipation(data, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); - return NoContent(); - } + public Task CreateUseCaseParticipation([FromForm] UseCaseParticipationCreationData data, CancellationToken cancellationToken) => + _logic.CreateUseCaseParticipation(data, cancellationToken); /// /// Creates the SSI Certificate request diff --git a/src/administration/Administration.Service/Controllers/ServiceAccountController.cs b/src/administration/Administration.Service/Controllers/ServiceAccountController.cs index 56d81c17f0..1f3afcafe6 100644 --- a/src/administration/Administration.Service/Controllers/ServiceAccountController.cs +++ b/src/administration/Administration.Service/Controllers/ServiceAccountController.cs @@ -196,12 +196,12 @@ public IAsyncEnumerable GetServiceAccountRolesAsync(str /// /// The processId that was passed as externalId with the request for creation of the technical user. /// Information of the technical user which was created. - /// Example: POST: api/administration/serviceaccount/cllback/{externalId} + /// Example: POST: api/administration/serviceaccount/callback/{externalId} /// returns all service account roles [HttpPost] [Authorize(Roles = "technical_roles_management")] - [Authorize(Policy = PolicyTypes.ValidCompany)] - [Route("callback/{externalId}")] + [Authorize(Policy = PolicyTypes.ServiceAccount)] + [Route("callback/{processId}")] public async Task ServiceAccountCreationCallback([FromRoute] Guid processId, [FromBody] AuthenticationDetail callbackData) { await _logic.HandleServiceAccountCreationCallback(processId, callbackData).ConfigureAwait(ConfigureAwaitOptions.None); diff --git a/src/administration/Administration.Service/Models/UseCaseParticipationCreationData.cs b/src/administration/Administration.Service/Models/UseCaseParticipationCreationData.cs index 382cc86e42..1d5db4cf11 100644 --- a/src/administration/Administration.Service/Models/UseCaseParticipationCreationData.cs +++ b/src/administration/Administration.Service/Models/UseCaseParticipationCreationData.cs @@ -18,6 +18,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +using Org.Eclipse.TractusX.Portal.Backend.IssuerComponent.Library.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models; @@ -25,8 +26,8 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models; public record UseCaseParticipationCreationData ( Guid VerifiedCredentialExternalTypeDetailId, - VerifiedCredentialTypeId CredentialType, - IFormFile Document + UseCaseFrameworkId Framework, + IFormFile? Document ); public record SsiCertificateCreationData diff --git a/src/externalsystems/IssuerComponent.Library/BusinessLogic/IIssuerComponentBusinessLogic.cs b/src/externalsystems/IssuerComponent.Library/BusinessLogic/IIssuerComponentBusinessLogic.cs index 64658ba54f..bfa8d5210d 100644 --- a/src/externalsystems/IssuerComponent.Library/BusinessLogic/IIssuerComponentBusinessLogic.cs +++ b/src/externalsystems/IssuerComponent.Library/BusinessLogic/IIssuerComponentBusinessLogic.cs @@ -28,4 +28,5 @@ public interface IIssuerComponentBusinessLogic Task StoreBpnlCredentialResponse(Guid applicationId, IssuerResponseData data); Task CreateMembershipCredential(IApplicationChecklistService.WorkerChecklistProcessStepData context, CancellationToken cancellationToken); Task StoreMembershipCredentialResponse(Guid applicationId, IssuerResponseData data); + Task CreateFrameworkCredentialData(Guid useCaseFrameworkVersionId, UseCaseFrameworkId frameworkId, Guid identityId, CancellationToken cancellationToken); } diff --git a/src/externalsystems/IssuerComponent.Library/BusinessLogic/IssuerComponentBusinessLogic.cs b/src/externalsystems/IssuerComponent.Library/BusinessLogic/IssuerComponentBusinessLogic.cs index 92db73c0e7..0d6d2f5e6d 100644 --- a/src/externalsystems/IssuerComponent.Library/BusinessLogic/IssuerComponentBusinessLogic.cs +++ b/src/externalsystems/IssuerComponent.Library/BusinessLogic/IssuerComponentBusinessLogic.cs @@ -174,4 +174,29 @@ public async Task StoreMembershipCredentialResponse(Guid applicationId, IssuerRe ? [ProcessStepTypeId.START_CLEARING_HOUSE] : null); } + + public async Task CreateFrameworkCredentialData(Guid useCaseFrameworkVersionId, UseCaseFrameworkId frameworkId, Guid identityId, CancellationToken cancellationToken) + { + var (holder, businessPartnerNumber, walletInformation) = await repositories.GetInstance().GetWalletData(identityId).ConfigureAwait(false); + if (holder is null) + { + throw new ConflictException("The holder must be set"); + } + + if (businessPartnerNumber is null) + { + throw new ConflictException("The bpn must be set"); + } + + if (walletInformation is null) + { + throw new ConflictException("The wallet information must be set"); + } + + var cryptoConfig = _settings.EncryptionConfigs.SingleOrDefault(x => x.Index == walletInformation.EncryptionMode) ?? throw new ConfigurationException($"EncryptionModeIndex {walletInformation.EncryptionMode} is not configured"); + var secret = CryptoHelper.Decrypt(walletInformation.ClientSecret, walletInformation.InitializationVector, Convert.FromHexString(cryptoConfig.EncryptionKey), cryptoConfig.CipherMode, cryptoConfig.PaddingMode); + + var data = new CreateFrameworkCredentialRequest(holder, businessPartnerNumber, frameworkId, useCaseFrameworkVersionId, new TechnicalUserDetails(walletInformation.WalletUrl, walletInformation.ClientId, secret), null); + return await service.CreateFrameworkCredential(data, cancellationToken).ConfigureAwait(false); + } } diff --git a/src/externalsystems/IssuerComponent.Library/Models/CreateFrameworkCredentialRequest.cs b/src/externalsystems/IssuerComponent.Library/Models/CreateFrameworkCredentialRequest.cs new file mode 100644 index 0000000000..7dcbd1086d --- /dev/null +++ b/src/externalsystems/IssuerComponent.Library/Models/CreateFrameworkCredentialRequest.cs @@ -0,0 +1,31 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using System.Text.Json.Serialization; + +namespace Org.Eclipse.TractusX.Portal.Backend.IssuerComponent.Library.Models; + +public record CreateFrameworkCredentialRequest( + [property: JsonPropertyName("holder")] string Holder, + [property: JsonPropertyName("businessPartnerNumber")] string HolderBpn, + [property: JsonPropertyName("useCaseFrameworkId")] UseCaseFrameworkId UseCaseFrameworkId, + [property: JsonPropertyName("useCaseFrameworkVersionId")] Guid UseCaseFrameworkVersionId, + [property: JsonPropertyName("technicalUserDetails")] TechnicalUserDetails? TechnicalUserDetails, + [property: JsonPropertyName("callbackUrl")] string? CallbackUrl +); diff --git a/src/externalsystems/IssuerComponent.Library/Models/UseCaseFrameworkId.cs b/src/externalsystems/IssuerComponent.Library/Models/UseCaseFrameworkId.cs new file mode 100644 index 0000000000..0400f68193 --- /dev/null +++ b/src/externalsystems/IssuerComponent.Library/Models/UseCaseFrameworkId.cs @@ -0,0 +1,55 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using System.Runtime.Serialization; + +namespace Org.Eclipse.TractusX.Portal.Backend.IssuerComponent.Library.Models; + +public enum UseCaseFrameworkId +{ + [EnumMember(Value = "TraceabilityCredential")] + TRACEABILITY_CREDENTIAL = 1, + + [EnumMember(Value = "PcfCredential")] + PCF_CREDENTIAL = 2, + + [EnumMember(Value = "BehaviorTwinCredential")] + BEHAVIOR_TWIN_CREDENTIAL = 3, + + [EnumMember(Value = "vehicleDismantle")] + VEHICLE_DISMANTLE = 4, + + [EnumMember(Value = "CircularEconomyCredential")] + CIRCULAR_ECONOMY = 5, + + [EnumMember(Value = "QualityCredential")] + QUALITY_CREDENTIAL = 6, + + [EnumMember(Value = "BusinessPartnerCredential")] + BUSINESS_PARTNER_NUMBER = 7, + + [EnumMember(Value = "DemandCapacityCredential")] + DEMAND_AND_CAPACITY_MANAGEMENT = 8, + + [EnumMember(Value = "DemandCapacityCredential")] + DEMAND_AND_CAPACITY_MANAGEMENT_PURIS = 9, + + [EnumMember(Value = "BusinessPartnerCredential")] + BUSINESS_PARTNER_DATA_MANAGEMENT = 10 +} diff --git a/src/externalsystems/IssuerComponent.Library/Service/IIssuerComponentService.cs b/src/externalsystems/IssuerComponent.Library/Service/IIssuerComponentService.cs index 6793bb9bde..a2c7973c27 100644 --- a/src/externalsystems/IssuerComponent.Library/Service/IIssuerComponentService.cs +++ b/src/externalsystems/IssuerComponent.Library/Service/IIssuerComponentService.cs @@ -25,4 +25,5 @@ public interface IIssuerComponentService { Task CreateBpnlCredential(CreateBpnCredentialRequest data, CancellationToken cancellationToken); Task CreateMembershipCredential(CreateMembershipCredentialRequest data, CancellationToken cancellationToken); + Task CreateFrameworkCredential(CreateFrameworkCredentialRequest data, CancellationToken cancellationToken); } diff --git a/src/externalsystems/IssuerComponent.Library/Service/IssuerComponentService.cs b/src/externalsystems/IssuerComponent.Library/Service/IssuerComponentService.cs index 5d217a91ee..db6b7d8dad 100644 --- a/src/externalsystems/IssuerComponent.Library/Service/IssuerComponentService.cs +++ b/src/externalsystems/IssuerComponent.Library/Service/IssuerComponentService.cs @@ -48,4 +48,12 @@ await httpClient.PostAsJsonAsync("/api/issuer/membership", data, Options, cancel .CatchingIntoServiceExceptionFor("issuer-component-membership-post", HttpAsyncResponseMessageExtension.RecoverOptions.INFRASTRUCTURE).ConfigureAwait(false); return true; } + + public async Task CreateFrameworkCredential(CreateFrameworkCredentialRequest data, CancellationToken cancellationToken) + { + var httpClient = await tokenService.GetAuthorizedClient(_settings, cancellationToken).ConfigureAwait(false); + var result = await httpClient.PostAsJsonAsync("/api/issuer/framework", data, Options, cancellationToken) + .CatchingIntoServiceExceptionFor("issuer-component-framework-post", HttpAsyncResponseMessageExtension.RecoverOptions.INFRASTRUCTURE).ConfigureAwait(false); + return await result.Content.ReadFromJsonAsync(cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); + } } diff --git a/src/marketplace/Offers.Library/Service/OfferSetupService.cs b/src/marketplace/Offers.Library/Service/OfferSetupService.cs index 2240f873b6..a063fc0788 100644 --- a/src/marketplace/Offers.Library/Service/OfferSetupService.cs +++ b/src/marketplace/Offers.Library/Service/OfferSetupService.cs @@ -582,7 +582,7 @@ await _notificationService.CreateNotifications( await _dimService.CreateTechnicalUser(bpn, new TechnicalUserData(processId.Value, $"sa-{offerName}-{offerSubscriptionId}"), cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); return new ValueTuple?, ProcessStepStatusId, bool, string?>( [ - ProcessStepTypeId.AWAIT_DIM_RESPONSE + ProcessStepTypeId.AWAIT_CREATE_DIM_TECHNICAL_USER_RESPONSE ], ProcessStepStatusId.DONE, true, diff --git a/src/portalbackend/PortalBackend.DBAccess/Models/ServiceAccountData.cs b/src/portalbackend/PortalBackend.DBAccess/Models/ServiceAccountData.cs new file mode 100644 index 0000000000..4822b34d31 --- /dev/null +++ b/src/portalbackend/PortalBackend.DBAccess/Models/ServiceAccountData.cs @@ -0,0 +1,22 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +namespace Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; + +public record ServiceAccountData(string? ServiceAccountName, Guid? CompanyId); diff --git a/src/portalbackend/PortalBackend.DBAccess/Models/SubscriptionData.cs b/src/portalbackend/PortalBackend.DBAccess/Models/SubscriptionData.cs new file mode 100644 index 0000000000..688a5caa82 --- /dev/null +++ b/src/portalbackend/PortalBackend.DBAccess/Models/SubscriptionData.cs @@ -0,0 +1,22 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +namespace Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; + +public record SubscriptionData(Guid? OfferSubscriptionId, Guid? CompanyId, string? OfferName); diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/CompanyRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/CompanyRepository.cs index 1749ca24d4..0d7dd9cbf5 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/CompanyRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/CompanyRepository.cs @@ -28,19 +28,9 @@ namespace Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; /// -public class CompanyRepository : ICompanyRepository +public class CompanyRepository(PortalDbContext context) + : ICompanyRepository { - private readonly PortalDbContext _context; - - /// - /// Constructor. - /// - /// Portal DB context. - public CompanyRepository(PortalDbContext portalDbContext) - { - _context = portalDbContext; - } - /// Company ICompanyRepository.CreateCompany(string companyName, Action? setOptionalParameters) { @@ -50,14 +40,14 @@ Company ICompanyRepository.CreateCompany(string companyName, Action? se CompanyStatusId.PENDING, DateTimeOffset.UtcNow); setOptionalParameters?.Invoke(company); - return _context.Companies.Add(company).Entity; + return context.Companies.Add(company).Entity; } public void AttachAndModifyCompany(Guid companyId, Action? initialize, Action modify) { var company = new Company(companyId, null!, default, default); initialize?.Invoke(company); - _context.Attach(company); + context.Attach(company); modify(company); } @@ -71,19 +61,19 @@ public Address CreateAddress(string city, string streetname, string countryAlpha DateTimeOffset.UtcNow ); setOptionalParameters?.Invoke(address); - return _context.Addresses.Add(address).Entity; + return context.Addresses.Add(address).Entity; } public void AttachAndModifyAddress(Guid addressId, Action
? initialize, Action
modify) { var address = new Address(addressId, null!, null!, null!, default); initialize?.Invoke(address); - _context.Attach(address); + context.Attach(address); modify(address); } public void CreateUpdateDeleteIdentifiers(Guid companyId, IEnumerable<(UniqueIdentifierId UniqueIdentifierId, string Value)> initialItems, IEnumerable<(UniqueIdentifierId UniqueIdentifierId, string Value)> modifiedItems) => - _context.AddAttachRemoveRange( + context.AddAttachRemoveRange( initialItems, modifiedItems, initial => initial.UniqueIdentifierId, @@ -94,13 +84,13 @@ public void CreateUpdateDeleteIdentifiers(Guid companyId, IEnumerable<(UniqueIde (entity, modified) => entity.Value = modified.Value); public Task<(bool IsValidCompany, string CompanyName)> GetCompanyNameUntrackedAsync(Guid companyId) => - _context.Companies + context.Companies .Where(x => x.Id == companyId) .Select(company => new ValueTuple(true, company.Name)) .SingleOrDefaultAsync(); public Task<(string? Bpn, IEnumerable TechnicalUserRoleIds)> GetBpnAndTechnicalUserRoleIds(Guid companyId, string technicalUserClientId) => - _context.Companies + context.Companies .AsNoTracking() .Where(company => company.Id == companyId) .Select(company => new ValueTuple>( @@ -109,7 +99,7 @@ public void CreateUpdateDeleteIdentifiers(Guid companyId, IEnumerable<(UniqueIde .SingleOrDefaultAsync(); public IAsyncEnumerable GetAllMemberCompaniesBPNAsync(IEnumerable? bpnIds) => - _context.Companies + context.Companies .AsNoTracking() .Where(company => company.CompanyStatusId == CompanyStatusId.ACTIVE && (bpnIds == null || bpnIds.Contains(company.BusinessPartnerNumber) && @@ -118,7 +108,7 @@ public IAsyncEnumerable GetAllMemberCompaniesBPNAsync(IEnumerable GetCompanyDetailsAsync(Guid companyId) => - _context.Companies + context.Companies .AsNoTracking() .Where(company => company.Id == companyId) .Select(company => new CompanyAddressDetailData( @@ -139,7 +129,7 @@ public IAsyncEnumerable GetAllMemberCompaniesBPNAsync(IEnumerable public Task<(bool IsValidCompanyId, bool IsCompanyRoleOwner)> IsValidCompanyRoleOwner(Guid companyId, IEnumerable companyRoleIds) => - _context.Companies.AsNoTracking() + context.Companies.AsNoTracking() .Where(company => company.Id == companyId) .Select(company => new ValueTuple( true, @@ -149,7 +139,7 @@ public IAsyncEnumerable GetAllMemberCompaniesBPNAsync(IEnumerable public Task<(Guid ProviderCompanyDetailId, string Url)> GetProviderCompanyDetailsExistsForUser(Guid companyId) => - _context.ProviderCompanyDetails.AsNoTracking() + context.ProviderCompanyDetails.AsNoTracking() .Where(details => details.CompanyId == companyId) .Select(details => new ValueTuple(details.Id, details.AutoSetupUrl)) .SingleOrDefaultAsync(); @@ -159,12 +149,12 @@ ProviderCompanyDetail ICompanyRepository.CreateProviderCompanyDetail(Guid compan { var providerCompanyDetail = new ProviderCompanyDetail(Guid.NewGuid(), companyId, dataUrl, DateTimeOffset.UtcNow); setOptionalParameter?.Invoke(providerCompanyDetail); - return _context.ProviderCompanyDetails.Add(providerCompanyDetail).Entity; + return context.ProviderCompanyDetails.Add(providerCompanyDetail).Entity; } /// public Task<(ProviderDetailReturnData ProviderDetailReturnData, bool IsProviderCompany)> GetProviderCompanyDetailAsync(CompanyRoleId companyRoleId, Guid companyId) => - _context.Companies + context.Companies .Where(company => company.Id == companyId) .Select(company => new ValueTuple( new ProviderDetailReturnData( @@ -179,20 +169,20 @@ public void AttachAndModifyProviderCompanyDetails(Guid providerCompanyDetailId, { var details = new ProviderCompanyDetail(providerCompanyDetailId, Guid.Empty, null!, default); initialize(details); - _context.Attach(details); + context.Attach(details); modify(details); } /// public Task<(string? Bpn, Guid? SelfDescriptionDocumentId)> GetCompanyBpnAndSelfDescriptionDocumentByIdAsync(Guid companyId) => - _context.Companies.AsNoTracking() + context.Companies.AsNoTracking() .Where(x => x.Id == companyId) .Select(x => new ValueTuple(x.BusinessPartnerNumber, x.SelfDescriptionDocumentId)) .SingleOrDefaultAsync(); /// public IAsyncEnumerable GetCompanyAssigendUseCaseDetailsAsync(Guid userCompanyId) => - _context.Companies + context.Companies .Where(company => company.Id == userCompanyId) .SelectMany(company => company.CompanyAssignedUseCase) .Select(cauc => new CompanyAssignedUseCaseData( @@ -202,7 +192,7 @@ public IAsyncEnumerable GetCompanyAssigendUseCaseDet /// public Task<(bool IsUseCaseIdExists, bool IsActiveCompanyStatus, bool IsValidCompany)> GetCompanyStatusAndUseCaseIdAsync(Guid companyId, Guid useCaseId) => - _context.Companies + context.Companies .Where(company => company.Id == companyId) .Select(company => new ValueTuple( company.CompanyAssignedUseCase.Any(cauc => cauc.UseCaseId == useCaseId), @@ -212,15 +202,15 @@ public IAsyncEnumerable GetCompanyAssigendUseCaseDet /// public CompanyAssignedUseCase CreateCompanyAssignedUseCase(Guid companyId, Guid useCaseId) => - _context.CompanyAssignedUseCases.Add(new CompanyAssignedUseCase(companyId, useCaseId)).Entity; + context.CompanyAssignedUseCases.Add(new CompanyAssignedUseCase(companyId, useCaseId)).Entity; /// public void RemoveCompanyAssignedUseCase(Guid companyId, Guid useCaseId) => - _context.CompanyAssignedUseCases.Remove(new CompanyAssignedUseCase(companyId, useCaseId)); + context.CompanyAssignedUseCases.Remove(new CompanyAssignedUseCase(companyId, useCaseId)); /// public IAsyncEnumerable GetCompanyRoleAndConsentAgreementDataAsync(Guid companyId, string languageShortName) => - _context.CompanyRoles + context.CompanyRoles .AsSplitQuery() .Where(companyRole => companyRole.CompanyRoleRegistrationData!.IsRegistrationRole) .Select(companyRole => new CompanyRoleConsentData( @@ -241,7 +231,7 @@ public IAsyncEnumerable GetCompanyRoleAndConsentAgreemen /// public Task<(bool IsValidCompany, bool IsCompanyActive, IEnumerable? CompanyRoleIds, IEnumerable? ConsentStatusDetails)> GetCompanyRolesDataAsync(Guid companyId, IEnumerable companyRoleIds) => - _context.Companies + context.Companies .AsNoTracking() .AsSplitQuery() .Where(company => company.Id == companyId) @@ -268,7 +258,7 @@ public IAsyncEnumerable GetCompanyRoleAndConsentAgreemen /// public IAsyncEnumerable<(AgreementStatusData agreementStatusData, CompanyRoleId CompanyRoleId)> GetAgreementAssignedRolesDataAsync(IEnumerable companyRoleIds) => - _context.AgreementAssignedCompanyRoles + context.AgreementAssignedCompanyRoles .Where(assigned => companyRoleIds.Contains(assigned.CompanyRoleId)) .OrderBy(assigned => assigned.CompanyRoleId) .Select(assigned => new ValueTuple( @@ -278,7 +268,7 @@ public IAsyncEnumerable GetCompanyRoleAndConsentAgreemen /// public Task<(bool IsActive, bool IsValid)> GetCompanyStatusDataAsync(Guid companyId) => - _context.Companies + context.Companies .Where(company => company.Id == companyId) .Select(company => new ValueTuple( company.CompanyStatusId == CompanyStatusId.ACTIVE, @@ -286,7 +276,7 @@ public IAsyncEnumerable GetCompanyRoleAndConsentAgreemen )).SingleOrDefaultAsync(); public Task GetOwnCompanyInformationAsync(Guid companyId, Guid companyUserId) => - _context.Companies + context.Companies .AsNoTracking() .Where(c => c.Id == companyId) .Select(company => new CompanyInformationData( @@ -300,14 +290,14 @@ public IAsyncEnumerable GetCompanyRoleAndConsentAgreemen /// public IAsyncEnumerable GetOwnCompanyRolesAsync(Guid companyId) => - _context.CompanyAssignedRoles + context.CompanyAssignedRoles .Where(x => x.CompanyId == companyId) .Select(x => x.CompanyRoleId) .AsAsyncEnumerable(); /// public IAsyncEnumerable GetOperatorBpns() => - _context.Companies + context.Companies .Where(x => x.CompanyAssignedRoles.Any(car => car.CompanyRoleId == CompanyRoleId.OPERATOR) && !string.IsNullOrWhiteSpace(x.BusinessPartnerNumber)) @@ -317,7 +307,7 @@ public IAsyncEnumerable GetOperatorBpns() => .AsAsyncEnumerable(); public Task<(bool IsValidCompany, string CompanyName, bool IsAllowed)> CheckCompanyAndCompanyRolesAsync(Guid companyId, IEnumerable companyRoles) => - _context.Companies + context.Companies .Where(x => x.Id == companyId) .Select(x => new ValueTuple( true, @@ -327,7 +317,7 @@ public IAsyncEnumerable GetOperatorBpns() => .SingleOrDefaultAsync(); public Task GetCallbackData(Guid companyId) => - _context.Companies.Where(c => c.Id == companyId) + context.Companies.Where(c => c.Id == companyId) .Select(c => new OnboardingServiceProviderCallbackResponseData( c.OnboardingServiceProviderDetail!.CallbackUrl, c.OnboardingServiceProviderDetail.AuthUrl, @@ -336,7 +326,7 @@ public Task GetCallbackData(Guid .SingleAsync(); public Task<(bool HasCompanyRole, Guid? OnboardingServiceProviderDetailId, OspDetails? OspDetails)> GetCallbackEditData(Guid companyId, CompanyRoleId companyRoleId) => - _context.Companies.Where(c => c.Id == companyId) + context.Companies.Where(c => c.Id == companyId) .Select(c => new ValueTuple( c.CompanyAssignedRoles.Any(role => role.CompanyRoleId == companyRoleId), c.OnboardingServiceProviderDetail!.Id, @@ -356,29 +346,29 @@ public void AttachAndModifyOnboardingServiceProvider(Guid onboardingServiceProvi { var ospDetails = new OnboardingServiceProviderDetail(onboardingServiceProviderDetailId, Guid.Empty, null!, null!, null!, null!, null, default); initialize?.Invoke(ospDetails); - _context.OnboardingServiceProviderDetails.Attach(ospDetails); + context.OnboardingServiceProviderDetails.Attach(ospDetails); setOptionalFields.Invoke(ospDetails); } public OnboardingServiceProviderDetail CreateOnboardingServiceProviderDetails(Guid companyId, string callbackUrl, string authUrl, string clientId, byte[] clientSecret, byte[]? initializationVector, int encryptionMode) => - _context.OnboardingServiceProviderDetails.Add(new OnboardingServiceProviderDetail(Guid.NewGuid(), companyId, callbackUrl, authUrl, clientId, clientSecret, initializationVector, encryptionMode)).Entity; + context.OnboardingServiceProviderDetails.Add(new OnboardingServiceProviderDetail(Guid.NewGuid(), companyId, callbackUrl, authUrl, clientId, clientSecret, initializationVector, encryptionMode)).Entity; /// public Task CheckBpnExists(string bpn) => - _context.Companies + context.Companies .AnyAsync(x => x.BusinessPartnerNumber == bpn); public void CreateWalletData(Guid companyId, string did, JsonDocument didDocument, string clientId, byte[] clientSecret, byte[]? initializationVector, int encryptionMode, string authenticationServiceUrl) => - _context.CompanyWalletDatas.Add(new CompanyWalletData(Guid.NewGuid(), companyId, did, didDocument, clientId, clientSecret, initializationVector, encryptionMode, authenticationServiceUrl)); + context.CompanyWalletDatas.Add(new CompanyWalletData(Guid.NewGuid(), companyId, did, didDocument, clientId, clientSecret, initializationVector, encryptionMode, authenticationServiceUrl)); public Task<(bool Exists, JsonDocument DidDocument)> GetDidDocumentById(string bpn) => - _context.CompanyWalletDatas + context.CompanyWalletDatas .Where(x => x.Company!.BusinessPartnerNumber == bpn) .Select(x => new ValueTuple(true, x.DidDocument)) .SingleOrDefaultAsync(); public Task<(bool Exists, Guid CompanyId, IEnumerable SubmittedCompanyApplicationId)> GetCompanyIdByBpn(string bpn) => - _context.Companies + context.Companies .Where(x => x.BusinessPartnerNumber == bpn) .Select(x => new ValueTuple>( true, @@ -389,7 +379,29 @@ public void CreateWalletData(Guid companyId, string did, JsonDocument didDocumen .SingleOrDefaultAsync(); public Task GetWalletServiceUrl(Guid companyId) => - _context.Companies.Where(x => x.Id == companyId) + context.Companies.Where(x => x.Id == companyId) .Select(x => x.CompanyWalletData!.AuthenticationServiceUrl) .SingleOrDefaultAsync(); + + public Task<(string? Holder, string? BusinessPartnerNumber, WalletInformation? WalletInformation)> GetWalletData(Guid identityId) => + context.Identities + .Where(ca => ca.Id == identityId) + .Select(ca => new + { + Company = ca.Company!, + Wallet = ca.Company!.CompanyWalletData + }) + .Select(c => new ValueTuple( + c.Company.DidDocumentLocation, + c.Company.BusinessPartnerNumber, + c.Wallet == null ? + null : + new WalletInformation( + c.Wallet.ClientId, + c.Wallet.ClientSecret, + c.Wallet.InitializationVector, + c.Wallet.EncryptionMode, + c.Wallet.AuthenticationServiceUrl + ))) + .SingleOrDefaultAsync(); } diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/ICompanyRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/ICompanyRepository.cs index 1cc7ac40a4..282894381e 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/ICompanyRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/ICompanyRepository.cs @@ -177,4 +177,5 @@ public interface ICompanyRepository Task<(bool Exists, JsonDocument DidDocument)> GetDidDocumentById(string bpn); Task<(bool Exists, Guid CompanyId, IEnumerable SubmittedCompanyApplicationId)> GetCompanyIdByBpn(string bpn); Task GetWalletServiceUrl(Guid companyId); + Task<(string? Holder, string? BusinessPartnerNumber, WalletInformation? WalletInformation)> GetWalletData(Guid identityId); } diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/IProcessStepRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/IProcessStepRepository.cs index 2c1105c444..2a2422efaf 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/IProcessStepRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/IProcessStepRepository.cs @@ -36,5 +36,5 @@ public interface IProcessStepRepository IAsyncEnumerable GetActiveProcesses(IEnumerable processTypeIds, IEnumerable processStepTypeIds, DateTimeOffset lockExpiryDate); IAsyncEnumerable<(Guid ProcessStepId, ProcessStepTypeId ProcessStepTypeId)> GetProcessStepData(Guid processId); public Task<(bool ProcessExists, VerifyProcessData ProcessData)> IsValidProcess(Guid processId, ProcessTypeId processTypeId, IEnumerable processStepTypeIds); - Task<(ProcessTypeId ProcessTypeId, VerifyProcessData ProcessData, (Guid? OfferSubscriptionId, Guid? CompanyId, string? OfferName)? SubscriptionData, (string? ServiceAccountName, Guid? CompanyId)? ServiceAccountData)> GetProcessDataForServiceAccountCallback(Guid processId, IEnumerable processStepTypeIds); + Task<(ProcessTypeId ProcessTypeId, VerifyProcessData ProcessData, SubscriptionData? SubscriptionData, ServiceAccountData? ServiceAccountData)> GetProcessDataForServiceAccountCallback(Guid processId, IEnumerable processStepTypeIds); } diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/ProcessStepRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/ProcessStepRepository.cs index d68a079f90..64c24c5ad9 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/ProcessStepRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/ProcessStepRepository.cs @@ -113,10 +113,11 @@ public IAsyncEnumerable GetActiveProcesses(IEnumerable p )) .SingleOrDefaultAsync(); - public Task<(ProcessTypeId ProcessTypeId, VerifyProcessData ProcessData, (Guid? OfferSubscriptionId, Guid? CompanyId, string? OfferName)? SubscriptionData, (string? ServiceAccountName, Guid? CompanyId)? ServiceAccountData)> GetProcessDataForServiceAccountCallback(Guid processId, IEnumerable processStepTypeIds) => + public Task<(ProcessTypeId ProcessTypeId, VerifyProcessData ProcessData, SubscriptionData? SubscriptionData, ServiceAccountData? ServiceAccountData)> GetProcessDataForServiceAccountCallback(Guid processId, IEnumerable processStepTypeIds) => _context.Processes + .AsNoTracking() .Where(x => x.Id == processId) - .Select(x => new ValueTuple?, ValueTuple?>( + .Select(x => new ValueTuple( x.ProcessTypeId, new VerifyProcessData( x, @@ -125,14 +126,14 @@ public IAsyncEnumerable GetActiveProcesses(IEnumerable p processStepTypeIds.Contains(step.ProcessStepTypeId) && step.ProcessStepStatusId == ProcessStepStatusId.TODO)), x.ProcessTypeId == ProcessTypeId.OFFER_SUBSCRIPTION - ? new ValueTuple( + ? new( x.OfferSubscription!.Id, x.OfferSubscription.CompanyId, x.OfferSubscription.Offer!.Name ) : null, x.ProcessTypeId == ProcessTypeId.DIM_TECHNICAL_USER - ? new ValueTuple( + ? new( x.DimUserCreationData!.ServiceAccount!.Name, x.DimUserCreationData.ServiceAccount.Identity!.CompanyId ) diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/ServiceAccountRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/ServiceAccountRepository.cs index c7f0b6bc36..f2e7ebe6bc 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/ServiceAccountRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/ServiceAccountRepository.cs @@ -212,12 +212,12 @@ public void CreateDimUserCreationData(Guid serviceAccountId, Guid processId) => _dbContext.DimUserCreationData.Add(new DimUserCreationData(Guid.NewGuid(), serviceAccountId, processId)); public Task<(bool IsValid, string? Bpn, string? ServiceAccountName)> GetDimServiceAccountData(Guid dimServiceAccountId) => - _dbContext.DimCompanyServiceAccounts + _dbContext.DimUserCreationData .Where(x => x.Id == dimServiceAccountId) .Select(x => new ValueTuple( true, - x.CompanyServiceAccount!.Identity!.Company!.BusinessPartnerNumber, - x.CompanyServiceAccount!.Name)) + x.ServiceAccount!.Identity!.Company!.BusinessPartnerNumber, + x.ServiceAccount!.Name)) .SingleOrDefaultAsync(); public Task GetDimServiceAccountIdForProcess(Guid processId) => diff --git a/src/processes/Processes.Worker/Processes.Worker.csproj b/src/processes/Processes.Worker/Processes.Worker.csproj index d241653f45..136f2b6392 100644 --- a/src/processes/Processes.Worker/Processes.Worker.csproj +++ b/src/processes/Processes.Worker/Processes.Worker.csproj @@ -44,6 +44,7 @@ + diff --git a/src/processes/Processes.Worker/Program.cs b/src/processes/Processes.Worker/Program.cs index da2df5adec..cb315bf525 100644 --- a/src/processes/Processes.Worker/Program.cs +++ b/src/processes/Processes.Worker/Program.cs @@ -30,6 +30,7 @@ using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess; using Org.Eclipse.TractusX.Portal.Backend.Processes.ApplicationChecklist.Config; using Org.Eclipse.TractusX.Portal.Backend.Processes.ApplicationChecklist.Executor; +using Org.Eclipse.TractusX.Portal.Backend.Processes.DimUserCreationProcess.Executor.DependencyInjection; using Org.Eclipse.TractusX.Portal.Backend.Processes.Invitation.Executor.DependencyInjection; using Org.Eclipse.TractusX.Portal.Backend.Processes.Mailing.Executor.DependencyInjection; using Org.Eclipse.TractusX.Portal.Backend.Processes.Mailing.Library.DependencyInjection; @@ -63,7 +64,8 @@ .AddNetworkRegistrationProcessExecutor(hostContext.Configuration) .AddMailingProcessExecutor() .AddInvitationProcessExecutor(hostContext.Configuration) - .AddMailingProcessCreation(hostContext.Configuration.GetSection("MailingProcessCreation")); + .AddMailingProcessCreation(hostContext.Configuration.GetSection("MailingProcessCreation")) + .AddDimUserCreationProcessExecutor(hostContext.Configuration.GetSection("ApplicationChecklist")); if (hostContext.HostingEnvironment.IsDevelopment()) { diff --git a/src/provisioning/Provisioning.Library/Service/IServiceAccountCreation.cs b/src/provisioning/Provisioning.Library/Service/IServiceAccountCreation.cs index 51d8cbe4cd..ed014630a2 100644 --- a/src/provisioning/Provisioning.Library/Service/IServiceAccountCreation.cs +++ b/src/provisioning/Provisioning.Library/Service/IServiceAccountCreation.cs @@ -22,6 +22,7 @@ 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; +using ServiceAccountData = Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Models.ServiceAccountData; namespace Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Service; diff --git a/src/provisioning/Provisioning.Library/Service/ServiceAccountCreation.cs b/src/provisioning/Provisioning.Library/Service/ServiceAccountCreation.cs index 1f8a176fd9..da80beede8 100644 --- a/src/provisioning/Provisioning.Library/Service/ServiceAccountCreation.cs +++ b/src/provisioning/Provisioning.Library/Service/ServiceAccountCreation.cs @@ -27,6 +27,7 @@ using Org.Eclipse.TractusX.Portal.Backend.Provisioning.DBAccess; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.ErrorHandling; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Models; +using ServiceAccountData = Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Models.ServiceAccountData; namespace Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Service; diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/CompanyDataBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/CompanyDataBusinessLogicTests.cs index 691b1bb7fa..27b4ea480b 100644 --- a/tests/administration/Administration.Service.Tests/BusinessLogic/CompanyDataBusinessLogicTests.cs +++ b/tests/administration/Administration.Service.Tests/BusinessLogic/CompanyDataBusinessLogicTests.cs @@ -24,6 +24,8 @@ using Org.Eclipse.TractusX.Portal.Backend.Framework.DateTimeProvider; using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; using Org.Eclipse.TractusX.Portal.Backend.Framework.Models; +using Org.Eclipse.TractusX.Portal.Backend.IssuerComponent.Library.BusinessLogic; +using Org.Eclipse.TractusX.Portal.Backend.IssuerComponent.Library.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Extensions; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; @@ -60,6 +62,7 @@ public class CompanyDataBusinessLogicTests private readonly IDateTimeProvider _dateTimeProvider; private readonly CompanyDataBusinessLogic _sut; private readonly IIdentityService _identityService; + private readonly IIssuerComponentBusinessLogic _issuerComponentBusinessLogic; public CompanyDataBusinessLogicTests() { @@ -77,6 +80,7 @@ public CompanyDataBusinessLogicTests() _companySsiDetailsRepository = A.Fake(); _companyCertificateRepository = A.Fake(); _mailingProcessCreation = A.Fake(); + _issuerComponentBusinessLogic = A.Fake(); _custodianService = A.Fake(); _dateTimeProvider = A.Fake(); @@ -98,7 +102,7 @@ public CompanyDataBusinessLogicTests() A.CallTo(() => _identityService.IdentityData).Returns(_identity); var options = Options.Create(new CompanyDataSettings { MaxPageSize = 20, UseCaseParticipationMediaTypes = new[] { MediaTypeId.PDF }, SsiCertificateMediaTypes = new[] { MediaTypeId.PDF }, CompanyCertificateMediaTypes = new[] { MediaTypeId.PDF }, DecentralIdentityManagementAuthUrl = "https://example.org/test" }); - _sut = new CompanyDataBusinessLogic(_portalRepositories, _custodianService, _dateTimeProvider, _identityService, _mailingProcessCreation, options); + _sut = new CompanyDataBusinessLogic(_portalRepositories, _custodianService, _dateTimeProvider, _identityService, _mailingProcessCreation, _issuerComponentBusinessLogic, options); } #region GetOwnCompanyDetails @@ -774,106 +778,19 @@ public async Task GetSsiCertificates_WithValidRequest_ReturnsExpected() #region CreateUseCaseParticipation - [Fact] - public async Task CreateUseCaseParticipation_WithInvalidDocumentContentType_ThrowsUnsupportedMediaTypeException() - { - // Arrange - var file = FormFileHelper.GetFormFile("test content", "test.pdf", MediaTypeId.PNG.MapToMediaType()); - var data = new UseCaseParticipationCreationData(_traceabilityExternalTypeDetailId, VerifiedCredentialTypeId.TRACEABILITY_FRAMEWORK, file); - - // Act - async Task Act() => await _sut.CreateUseCaseParticipation(data, CancellationToken.None); - - // Assert - var ex = await Assert.ThrowsAsync(Act); - ex.Message.Should().Be($"Document type not supported. File must match contentTypes :{MediaTypeId.PDF.MapToMediaType()}"); - } - - [Fact] - public async Task CreateUseCaseParticipation_WithNotExistingDetailId_ThrowsControllerArgumentException() - { - // Arrange - SetupCreateUseCaseParticipation(); - var verifiedCredentialExternalTypeDetailId = Guid.NewGuid(); - var file = FormFileHelper.GetFormFile("test content", "test.pdf", MediaTypeId.PDF.MapToMediaType()); - var data = new UseCaseParticipationCreationData(verifiedCredentialExternalTypeDetailId, VerifiedCredentialTypeId.TRACEABILITY_FRAMEWORK, file); - - // Act - async Task Act() => await _sut.CreateUseCaseParticipation(data, CancellationToken.None); - - // Assert - var ex = await Assert.ThrowsAsync(Act); - ex.Message.Should().Be($"VerifiedCredentialExternalTypeDetail {verifiedCredentialExternalTypeDetailId} does not exist"); - } - - [Fact] - public async Task CreateUseCaseParticipation_WithRequestAlreadyExisting_ThrowsControllerArgumentException() - { - // Arrange - SetupCreateUseCaseParticipation(); - var file = FormFileHelper.GetFormFile("test content", "test.pdf", MediaTypeId.PDF.MapToMediaType()); - var data = new UseCaseParticipationCreationData(_traceabilityExternalTypeDetailId, VerifiedCredentialTypeId.TRACEABILITY_FRAMEWORK, file); - - A.CallTo(() => _companySsiDetailsRepository.CheckSsiDetailsExistsForCompany(_identity.CompanyId, VerifiedCredentialTypeId.TRACEABILITY_FRAMEWORK, VerifiedCredentialTypeKindId.USE_CASE, _traceabilityExternalTypeDetailId)) - .Returns(true); - - // Act - async Task Act() => await _sut.CreateUseCaseParticipation(data, CancellationToken.None); - - // Assert - var ex = await Assert.ThrowsAsync(Act); - ex.Message.Should().Be("Credential request already existing"); - } - [Fact] public async Task CreateUseCaseParticipation_WithValidCall_CreatesExpected() { // Arrange - SetupCreateUseCaseParticipation(); var file = FormFileHelper.GetFormFile("test content", "test.pdf", MediaTypeId.PDF.MapToMediaType()); - var data = new UseCaseParticipationCreationData(_traceabilityExternalTypeDetailId, VerifiedCredentialTypeId.TRACEABILITY_FRAMEWORK, file); - var documentId = Guid.NewGuid(); - var documents = new List(); - var ssiDetails = new List(); - - A.CallTo(() => _companySsiDetailsRepository.CheckSsiDetailsExistsForCompany(_identity.CompanyId, VerifiedCredentialTypeId.TRACEABILITY_FRAMEWORK, VerifiedCredentialTypeKindId.USE_CASE, _traceabilityExternalTypeDetailId)) - .Returns(false); - A.CallTo(() => _companySsiDetailsRepository.CreateSsiDetails(_identity.CompanyId, VerifiedCredentialTypeId.TRACEABILITY_FRAMEWORK, A._, CompanySsiDetailStatusId.PENDING, _identity.IdentityId, A>._)) - .Invokes((Guid companyId, VerifiedCredentialTypeId verifiedCredentialTypeId, Guid docId, CompanySsiDetailStatusId companySsiDetailStatusId, Guid userId, Action? setOptionalFields) => - { - var ssiDetail = new CompanySsiDetail(Guid.NewGuid(), companyId, verifiedCredentialTypeId, companySsiDetailStatusId, docId, userId, DateTimeOffset.UtcNow); - setOptionalFields?.Invoke(ssiDetail); - ssiDetails.Add(ssiDetail); - }); - A.CallTo(() => _documentRepository.CreateDocument(A._, A._, A._, MediaTypeId.PDF, DocumentTypeId.PRESENTATION, A>._)) - .Invokes((string documentName, byte[] documentContent, byte[] hash, MediaTypeId mediaTypeId, DocumentTypeId documentTypeId, Action? setupOptionalFields) => - { - var document = new Document(documentId, documentContent, hash, documentName, mediaTypeId, DateTimeOffset.UtcNow, DocumentStatusId.PENDING, documentTypeId); - setupOptionalFields?.Invoke(document); - documents.Add(document); - }) - .Returns(new Document(documentId, null!, null!, null!, default, default, default, default)); + var data = new UseCaseParticipationCreationData(_traceabilityExternalTypeDetailId, UseCaseFrameworkId.TRACEABILITY_CREDENTIAL, file); // Act await _sut.CreateUseCaseParticipation(data, CancellationToken.None); // Assert - A.CallTo(() => _documentRepository.CreateDocument(A._, A._, A._, MediaTypeId.PDF, DocumentTypeId.PRESENTATION, A>._)) + A.CallTo(() => _issuerComponentBusinessLogic.CreateFrameworkCredentialData(_traceabilityExternalTypeDetailId, UseCaseFrameworkId.TRACEABILITY_CREDENTIAL, _identity.IdentityId, A._)) .MustHaveHappenedOnceExactly(); - documents.Should().ContainSingle(); - var document = documents.Single(); - document.DocumentTypeId.Should().Be(DocumentTypeId.PRESENTATION); - document.CompanyUserId.Should().Be(_identity.IdentityId); - document.DocumentStatusId.Should().Be(DocumentStatusId.PENDING); - A.CallTo(() => _companySsiDetailsRepository.CreateSsiDetails(_identity.CompanyId, VerifiedCredentialTypeId.TRACEABILITY_FRAMEWORK, document.Id, CompanySsiDetailStatusId.PENDING, _identity.IdentityId, A>._)) - .MustHaveHappenedOnceExactly(); - ssiDetails.Should().ContainSingle(); - var detail = ssiDetails.Single(); - detail.CompanySsiDetailStatusId.Should().Be(CompanySsiDetailStatusId.PENDING); - detail.DocumentId.Should().Be(document.Id); - detail.VerifiedCredentialTypeId.Should().Be(VerifiedCredentialTypeId.TRACEABILITY_FRAMEWORK); - detail.ExpiryDate.Should().Be(null); - detail.VerifiedCredentialExternalTypeUseCaseDetailId.Should().Be(_traceabilityExternalTypeDetailId); } #endregion @@ -1841,14 +1758,6 @@ public async Task GetDimServiceUrls_WithDocumentStatusIsNotLocked_ThrowsNotFound #region Setup - private void SetupCreateUseCaseParticipation() - { - A.CallTo(() => _companySsiDetailsRepository.CheckCredentialTypeIdExistsForExternalTypeDetailVersionId(_traceabilityExternalTypeDetailId, VerifiedCredentialTypeId.TRACEABILITY_FRAMEWORK)) - .Returns(true); - A.CallTo(() => _companySsiDetailsRepository.CheckCredentialTypeIdExistsForExternalTypeDetailVersionId(A.That.Not.Matches(x => x == _traceabilityExternalTypeDetailId), A._)) - .Returns(false); - } - private void SetupCreateSsiCertificate() { A.CallTo(() => _companySsiDetailsRepository.CheckSsiCertificateType(VerifiedCredentialTypeId.DISMANTLER_CERTIFICATE)) diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/ServiceAccountBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/ServiceAccountBusinessLogicTests.cs index 0a45054ce7..b374f0eda4 100644 --- a/tests/administration/Administration.Service.Tests/BusinessLogic/ServiceAccountBusinessLogicTests.cs +++ b/tests/administration/Administration.Service.Tests/BusinessLogic/ServiceAccountBusinessLogicTests.cs @@ -37,6 +37,7 @@ using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Models; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Service; using Org.Eclipse.TractusX.Portal.Backend.Tests.Shared.Extensions; +using ServiceAccountData = Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Models.ServiceAccountData; namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Tests.BusinessLogic; @@ -577,7 +578,7 @@ public async Task HandleServiceAccountCreationCallback_WithValidOfferSubscriptio var process = new Process(Guid.NewGuid(), ProcessTypeId.OFFER_SUBSCRIPTION, Guid.NewGuid()); var context = new VerifyProcessData(process, [new ProcessStep(Guid.NewGuid(), stepToTrigger, ProcessStepStatusId.TODO, process.Id, DateTimeOffset.UtcNow)]); A.CallTo(() => _processStepRepository.GetProcessDataForServiceAccountCallback(A._, A>._)) - .Returns((ProcessTypeId.OFFER_SUBSCRIPTION, context, new ValueTuple(Guid.NewGuid(), Guid.NewGuid(), "test"), null)); + .Returns((ProcessTypeId.OFFER_SUBSCRIPTION, context, new SubscriptionData(Guid.NewGuid(), Guid.NewGuid(), "test"), null)); // Act await _sut.HandleServiceAccountCreationCallback(process.Id, _fixture.Create()); @@ -597,7 +598,7 @@ public async Task HandleServiceAccountCreationCallback_WithNotExistingProcess_Th var stepToTrigger = ProcessStepTypeId.AWAIT_CREATE_DIM_TECHNICAL_USER_RESPONSE; var process = new Process(Guid.NewGuid(), processTypeId, Guid.NewGuid()); A.CallTo(() => _processStepRepository.GetProcessDataForServiceAccountCallback(A._, A>._)) - .Returns(default((ProcessTypeId, VerifyProcessData, (Guid?, Guid?, string?)?, (string?, Guid?)?))); + .Returns(new ValueTuple()); async Task Act() => await _sut.HandleServiceAccountCreationCallback(process.Id, _fixture.Create()); // Act @@ -617,7 +618,7 @@ public async Task HandleServiceAccountCreationCallback_WithOfferSubscriptionIdNo var process = new Process(Guid.NewGuid(), ProcessTypeId.OFFER_SUBSCRIPTION, Guid.NewGuid()); var context = new VerifyProcessData(process, [new ProcessStep(Guid.NewGuid(), stepToTrigger, ProcessStepStatusId.TODO, process.Id, DateTimeOffset.UtcNow)]); A.CallTo(() => _processStepRepository.GetProcessDataForServiceAccountCallback(A._, A>._)) - .Returns((ProcessTypeId.OFFER_SUBSCRIPTION, context, default((Guid?, Guid?, string?)), null)); + .Returns((ProcessTypeId.OFFER_SUBSCRIPTION, context, new SubscriptionData(null, null, null), null)); async Task Act() => await _sut.HandleServiceAccountCreationCallback(process.Id, _fixture.Create()); // Act @@ -637,7 +638,7 @@ public async Task HandleServiceAccountCreationCallback_WithoutCompanyId_ThrowsEx var process = new Process(Guid.NewGuid(), ProcessTypeId.OFFER_SUBSCRIPTION, Guid.NewGuid()); var context = new VerifyProcessData(process, [new ProcessStep(Guid.NewGuid(), stepToTrigger, ProcessStepStatusId.TODO, process.Id, DateTimeOffset.UtcNow)]); A.CallTo(() => _processStepRepository.GetProcessDataForServiceAccountCallback(A._, A>._)) - .Returns((ProcessTypeId.OFFER_SUBSCRIPTION, context, (Guid.NewGuid(), null, null), null)); + .Returns((ProcessTypeId.OFFER_SUBSCRIPTION, context, new SubscriptionData(Guid.NewGuid(), null, null), null)); async Task Act() => await _sut.HandleServiceAccountCreationCallback(process.Id, _fixture.Create()); // Act @@ -657,7 +658,7 @@ public async Task HandleServiceAccountCreationCallback_WithoutServiceAccountName var process = new Process(Guid.NewGuid(), ProcessTypeId.OFFER_SUBSCRIPTION, Guid.NewGuid()); var context = new VerifyProcessData(process, [new ProcessStep(Guid.NewGuid(), stepToTrigger, ProcessStepStatusId.TODO, process.Id, DateTimeOffset.UtcNow)]); A.CallTo(() => _processStepRepository.GetProcessDataForServiceAccountCallback(A._, A>._)) - .Returns((ProcessTypeId.OFFER_SUBSCRIPTION, context, (Guid.NewGuid(), Guid.NewGuid(), null), null)); + .Returns((ProcessTypeId.OFFER_SUBSCRIPTION, context, new SubscriptionData(Guid.NewGuid(), Guid.NewGuid(), null), null)); async Task Act() => await _sut.HandleServiceAccountCreationCallback(process.Id, _fixture.Create()); // Act @@ -677,7 +678,7 @@ public async Task HandleServiceAccountCreationCallback_WithoutDimTechnicalUserCo var process = new Process(Guid.NewGuid(), ProcessTypeId.DIM_TECHNICAL_USER, Guid.NewGuid()); var context = new VerifyProcessData(process, [new ProcessStep(Guid.NewGuid(), stepToTrigger, ProcessStepStatusId.TODO, process.Id, DateTimeOffset.UtcNow)]); A.CallTo(() => _processStepRepository.GetProcessDataForServiceAccountCallback(A._, A>._)) - .Returns((ProcessTypeId.DIM_TECHNICAL_USER, context, null, ("test", null))); + .Returns((ProcessTypeId.DIM_TECHNICAL_USER, context, null, new PortalBackend.DBAccess.Models.ServiceAccountData("test", null))); async Task Act() => await _sut.HandleServiceAccountCreationCallback(process.Id, _fixture.Create()); // Act @@ -697,7 +698,7 @@ public async Task HandleServiceAccountCreationCallback_WithoutOfferName_ThrowsEx var process = new Process(Guid.NewGuid(), ProcessTypeId.DIM_TECHNICAL_USER, Guid.NewGuid()); var context = new VerifyProcessData(process, [new ProcessStep(Guid.NewGuid(), stepToTrigger, ProcessStepStatusId.TODO, process.Id, DateTimeOffset.UtcNow)]); A.CallTo(() => _processStepRepository.GetProcessDataForServiceAccountCallback(A._, A>._)) - .Returns((ProcessTypeId.DIM_TECHNICAL_USER, context, null, default((string?, Guid?)))); + .Returns((ProcessTypeId.DIM_TECHNICAL_USER, context, null, new PortalBackend.DBAccess.Models.ServiceAccountData(null, null))); async Task Act() => await _sut.HandleServiceAccountCreationCallback(process.Id, _fixture.Create()); // Act diff --git a/tests/administration/Administration.Service.Tests/Controllers/CompanyDataControllerTests.cs b/tests/administration/Administration.Service.Tests/Controllers/CompanyDataControllerTests.cs index 299bfdb230..b59f753a75 100644 --- a/tests/administration/Administration.Service.Tests/Controllers/CompanyDataControllerTests.cs +++ b/tests/administration/Administration.Service.Tests/Controllers/CompanyDataControllerTests.cs @@ -21,6 +21,7 @@ using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Controllers; using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models; using Org.Eclipse.TractusX.Portal.Backend.Framework.Models; +using Org.Eclipse.TractusX.Portal.Backend.IssuerComponent.Library.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Extensions; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; @@ -201,7 +202,7 @@ public async Task CreateUseCaseParticipation_WithValidRequest_ReturnsExpected() { // Arrange var file = FormFileHelper.GetFormFile("test content", "test.pdf", MediaTypeId.PDF.MapToMediaType()); - var data = new UseCaseParticipationCreationData(Guid.NewGuid(), VerifiedCredentialTypeId.TRACEABILITY_FRAMEWORK, file); + var data = new UseCaseParticipationCreationData(Guid.NewGuid(), UseCaseFrameworkId.TRACEABILITY_CREDENTIAL, file); // Act await _controller.CreateUseCaseParticipation(data, CancellationToken.None); diff --git a/tests/externalsystems/IssuerComponent.Library.Tests/IssuerComponentBusinessLogicTests.cs b/tests/externalsystems/IssuerComponent.Library.Tests/IssuerComponentBusinessLogicTests.cs index 26a6d1b8a0..b6b6509194 100644 --- a/tests/externalsystems/IssuerComponent.Library.Tests/IssuerComponentBusinessLogicTests.cs +++ b/tests/externalsystems/IssuerComponent.Library.Tests/IssuerComponentBusinessLogicTests.cs @@ -42,26 +42,30 @@ public class IssuerComponentBusinessLogicTests private const string ValidBpn = "BPNL123698762345"; private readonly IApplicationRepository _applicationRepository; + private readonly ICompanyRepository _companyRepository; private readonly IPortalRepositories _portalRepositories; private readonly IIssuerComponentService _issuerComponentService; private readonly IApplicationChecklistService _checklistService; private readonly IIssuerComponentBusinessLogic _sut; private readonly IOptions _options; + private readonly IFixture _fixture; public IssuerComponentBusinessLogicTests() { - var fixture = new Fixture().Customize(new AutoFakeItEasyCustomization { ConfigureMembers = true }); - fixture.Behaviors.OfType().ToList() - .ForEach(b => fixture.Behaviors.Remove(b)); - fixture.Behaviors.Add(new OmitOnRecursionBehavior()); + _fixture = new Fixture().Customize(new AutoFakeItEasyCustomization { ConfigureMembers = true }); + _fixture.Behaviors.OfType().ToList() + .ForEach(b => _fixture.Behaviors.Remove(b)); + _fixture.Behaviors.Add(new OmitOnRecursionBehavior()); _applicationRepository = A.Fake(); + _companyRepository = A.Fake(); _portalRepositories = A.Fake(); _issuerComponentService = A.Fake(); _checklistService = A.Fake(); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_applicationRepository); + A.CallTo(() => _portalRepositories.GetInstance()).Returns(_companyRepository); _options = Options.Create(new IssuerComponentSettings { @@ -485,6 +489,91 @@ public async Task StoreMembershipCredential_WithUnsuccessful_UpdatesEntry() #endregion + #region CreateFrameworkCredential + + [Fact] + public async Task CreateFrameworkCredential_WithValid_CallsExpected() + { + // Arrange + var credentialId = Guid.NewGuid(); + var identityId = Guid.NewGuid(); + var useCaseFrameworkVersionId = Guid.NewGuid(); + var cryptoConfig = _options.Value.EncryptionConfigs.First(); + var (secret, vector) = CryptoHelper.Encrypt("test123", Convert.FromHexString(cryptoConfig.EncryptionKey), cryptoConfig.CipherMode, cryptoConfig.PaddingMode); + A.CallTo(() => _companyRepository.GetWalletData(identityId)) + .Returns(new ValueTuple("did:123:testabc", ValidBpn, new WalletInformation("cl1", secret, vector, 0, "https://example.com/wallet")) + ); + A.CallTo(() => _issuerComponentService.CreateFrameworkCredential(A._, A._)) + .Returns(credentialId); + + // Act + var result = await _sut.CreateFrameworkCredentialData(useCaseFrameworkVersionId, UseCaseFrameworkId.TRACEABILITY_CREDENTIAL, identityId, CancellationToken.None); + + // Assert + A.CallTo(() => _issuerComponentService.CreateFrameworkCredential(A._, A._)) + .MustHaveHappenedOnceExactly(); + result.Should().Be(credentialId); + } + + [Fact] + public async Task CreateFrameworkCredentialData_WithHolderNotSet_ThrowsConflictException() + { + // Arrange + var useCaseFrameworkVersionId = Guid.NewGuid(); + var identityId = Guid.NewGuid(); + A.CallTo(() => _companyRepository.GetWalletData(identityId)) + .Returns(new ValueTuple(null, null, null)); + async Task Act() => await _sut.CreateFrameworkCredentialData(useCaseFrameworkVersionId, UseCaseFrameworkId.TRACEABILITY_CREDENTIAL, identityId, CancellationToken.None); + + // Act + var ex = await Assert.ThrowsAsync(Act); + + // Assert + A.CallTo(() => _issuerComponentService.CreateFrameworkCredential(A._, A._)) + .MustNotHaveHappened(); + ex.Message.Should().Be($"The holder must be set"); + } + + [Fact] + public async Task CreateFrameworkCredential_WithBusinessPartnerNumberNotSet_ThrowsConflictException() + { + // Arrange + var useCaseFrameworkVersionId = Guid.NewGuid(); + var identityId = Guid.NewGuid(); + A.CallTo(() => _companyRepository.GetWalletData(identityId)) + .Returns(new ValueTuple("test", null, null)); + async Task Act() => await _sut.CreateFrameworkCredentialData(useCaseFrameworkVersionId, UseCaseFrameworkId.TRACEABILITY_CREDENTIAL, identityId, CancellationToken.None); + + // Act + var ex = await Assert.ThrowsAsync(Act); + + // Assert + A.CallTo(() => _issuerComponentService.CreateFrameworkCredential(A._, A._)) + .MustNotHaveHappened(); + ex.Message.Should().Be("The bpn must be set"); + } + + [Fact] + public async Task CreateFrameworkCredential_WithWalletInformationNotSet_ThrowsConflictException() + { + // Arrange + var useCaseFrameworkVersionId = Guid.NewGuid(); + var identityId = Guid.NewGuid(); + A.CallTo(() => _companyRepository.GetWalletData(identityId)) + .Returns(new ValueTuple("test", "BPNL0000001Test", null)); + async Task Act() => await _sut.CreateFrameworkCredentialData(useCaseFrameworkVersionId, UseCaseFrameworkId.TRACEABILITY_CREDENTIAL, identityId, CancellationToken.None); + + // Act + var ex = await Assert.ThrowsAsync(Act); + + // Assert + A.CallTo(() => _issuerComponentService.CreateFrameworkCredential(A._, A._)) + .MustNotHaveHappened(); + ex.Message.Should().Be("The wallet information must be set"); + } + + #endregion + #region Setup private void SetupForProcessIssuerComponentResponse(ApplicationChecklistEntry applicationChecklistEntry) diff --git a/tests/marketplace/Offers.Library.Tests/Service/OfferSetupServiceTests.cs b/tests/marketplace/Offers.Library.Tests/Service/OfferSetupServiceTests.cs index ada4014657..44141f6409 100644 --- a/tests/marketplace/Offers.Library.Tests/Service/OfferSetupServiceTests.cs +++ b/tests/marketplace/Offers.Library.Tests/Service/OfferSetupServiceTests.cs @@ -37,6 +37,7 @@ using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Service; using Org.Eclipse.TractusX.Portal.Backend.Tests.Shared.Extensions; using System.Collections.Immutable; +using ServiceAccountData = Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Models.ServiceAccountData; using TechnicalUserData = Org.Eclipse.TractusX.Portal.Backend.Dim.Library.Models.TechnicalUserData; namespace Org.Eclipse.TractusX.Portal.Backend.Offers.Library.Tests.Service; @@ -1195,7 +1196,7 @@ public async Task CreateDimTechnicalUser_WithTechnicalUserNeeded_ReturnsExpected var result = await _sut.CreateDimTechnicalUser(offerSubscriptionId, CancellationToken.None); // Assert - result.nextStepTypeIds.Should().ContainSingle().Which.Should().Be(ProcessStepTypeId.AWAIT_DIM_RESPONSE); + result.nextStepTypeIds.Should().ContainSingle().Which.Should().Be(ProcessStepTypeId.AWAIT_CREATE_DIM_TECHNICAL_USER_RESPONSE); result.stepStatusId.Should().Be(ProcessStepStatusId.DONE); result.modified.Should().BeTrue(); result.processMessage.Should().BeNull(); diff --git a/tests/provisioning/Provisioning.Library.Tests/Extensions/ServiceAccountCreationTests.cs b/tests/provisioning/Provisioning.Library.Tests/Extensions/ServiceAccountCreationTests.cs index d0b91d837f..240d4b756e 100644 --- a/tests/provisioning/Provisioning.Library.Tests/Extensions/ServiceAccountCreationTests.cs +++ b/tests/provisioning/Provisioning.Library.Tests/Extensions/ServiceAccountCreationTests.cs @@ -29,6 +29,7 @@ using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.ErrorHandling; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Models; using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Service; +using ServiceAccountData = Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Models.ServiceAccountData; namespace Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Tests.Extensions;