Skip to content

Commit

Permalink
chore(CxMembership): Set Catena-X Membership in BPDM
Browse files Browse the repository at this point in the history
  • Loading branch information
tfjanjua committed Dec 23, 2024
1 parent f36c976 commit d94f222
Show file tree
Hide file tree
Showing 18 changed files with 264 additions and 3 deletions.
34 changes: 34 additions & 0 deletions docs/api/administration-service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4257,6 +4257,38 @@ paths:
description: Internal Server Error
'401':
description: The User is unauthorized
'/api/administration/registration/application/{applicationId}/retrigger-set-cx-membership':
post:
tags:
- Registration
summary: 'Retriggers the last failed step (Authorization required - Roles: approve_new_partner)'
parameters:
- name: applicationId
in: path
description: Id of the application that should be triggered
required: true
schema:
type: string
format: uuid
responses:
'204':
description: Empty response on success.
'400':
description: Either the CompanyApplication is not in status SUBMITTED or the next step can't automatically retriggered.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: No application found for the applicationId.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal Server Error
'401':
description: The User is unauthorized
/api/administration/RegistrationStatus/callback:
get:
tags:
Expand Down Expand Up @@ -7529,6 +7561,8 @@ components:
- RETRIGGER_REMOVE_REGISTRATION_ROLES
- RETRIGGER_SET_THEME
- RETRIGGER_SET_MEMBERSHIP
- SET_CX_MEMBERSHIP_IN_BPDM
- RETRIGGER_SET_CX_MEMBERSHIP_IN_BPDM
- TRIGGER_PROVIDER
- AWAIT_START_AUTOSETUP
- OFFERSUBSCRIPTION_CLIENT_CREATION
Expand Down
2 changes: 2 additions & 0 deletions docs/api/apps-service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3572,6 +3572,8 @@ components:
- RETRIGGER_REMOVE_REGISTRATION_ROLES
- RETRIGGER_SET_THEME
- RETRIGGER_SET_MEMBERSHIP
- SET_CX_MEMBERSHIP_IN_BPDM
- RETRIGGER_SET_CX_MEMBERSHIP_IN_BPDM
- TRIGGER_PROVIDER
- AWAIT_START_AUTOSETUP
- OFFERSUBSCRIPTION_CLIENT_CREATION
Expand Down
2 changes: 2 additions & 0 deletions docs/api/services-service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2143,6 +2143,8 @@ components:
- RETRIGGER_REMOVE_REGISTRATION_ROLES
- RETRIGGER_SET_THEME
- RETRIGGER_SET_MEMBERSHIP
- SET_CX_MEMBERSHIP_IN_BPDM
- RETRIGGER_SET_CX_MEMBERSHIP_IN_BPDM
- TRIGGER_PROVIDER
- AWAIT_START_AUTOSETUP
- OFFERSUBSCRIPTION_CLIENT_CREATION
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -726,5 +726,27 @@ public async Task<NoContentResult> RetriggerSetMembership([FromRoute] Guid appli
await logic.TriggerChecklistAsync(applicationId, ApplicationChecklistEntryTypeId.APPLICATION_ACTIVATION, ProcessStepTypeId.RETRIGGER_SET_MEMBERSHIP).ConfigureAwait(ConfigureAwaitOptions.None);
return NoContent();
}

/// <summary>
/// Retriggers the last failed step
/// </summary>
/// <param name="applicationId" example="">Id of the application that should be triggered</param>
/// <returns>NoContent</returns>
/// Example: POST: api/administration/registration/application/{applicationId}/retrigger-set-cx-membership
/// <response code="204">Empty response on success.</response>
/// <response code="400">Either the CompanyApplication is not in status SUBMITTED or the next step can't automatically retriggered.</response>
/// <response code="404">No application found for the applicationId.</response>
[HttpPost]
[Authorize(Roles = "approve_new_partner")]
[Authorize(Policy = PolicyTypes.CompanyUser)]
[Route("application/{applicationId}/retrigger-set-cx-membership")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)]
public async Task<NoContentResult> RetriggerSetCxMembership([FromRoute] Guid applicationId)
{
await logic.TriggerChecklistAsync(applicationId, ApplicationChecklistEntryTypeId.APPLICATION_ACTIVATION, ProcessStepTypeId.RETRIGGER_SET_CX_MEMBERSHIP_IN_BPDM).ConfigureAwait(ConfigureAwaitOptions.None);
return NoContent();
}
}

20 changes: 20 additions & 0 deletions src/externalsystems/Bpdm.Library/BpdmService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
using Org.Eclipse.TractusX.Portal.Backend.Framework.HttpClientExtensions;
using Org.Eclipse.TractusX.Portal.Backend.Framework.Token;
using System.Net.Http.Json;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;

Expand Down Expand Up @@ -176,4 +177,23 @@ public async Task<BpdmSharingState> GetSharingState(Guid applicationId, Cancella
throw new ServiceException($"Access to sharing state did not return a valid json response: {je.Message}");
}
}

/// <inheritdoc />
public async Task<bool> SetCxMembership(string businessPartnerNumber, CancellationToken cancellationToken)
{
using var httpClient = await _tokenService.GetAuthorizedClient<BpdmService>(_settings, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None);

var requestData = new BpdmCxMembership(
new BpdmCxMembershipDto[]{
new(businessPartnerNumber, true)
}.AsEnumerable()
);

async ValueTask<(bool, string?)> CreateErrorMessage(HttpResponseMessage errorResponse) =>
(false, (await errorResponse.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None)));

await httpClient.PutAsJsonAsync("v6/cx-memberships", requestData, Options, cancellationToken)
.CatchingIntoServiceExceptionFor("bpdm-put-cx-membership", HttpAsyncResponseMessageExtension.RecoverOptions.INFRASTRUCTURE, CreateErrorMessage).ConfigureAwait(false);
return true;
}
}
8 changes: 8 additions & 0 deletions src/externalsystems/Bpdm.Library/IBpdmService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,12 @@ public interface IBpdmService
Task<bool> SetSharingStateToReady(string externalId, CancellationToken cancellationToken);
Task<BpdmLegalEntityOutputData> FetchInputLegalEntity(string externalId, CancellationToken cancellationToken);
Task<BpdmSharingState> GetSharingState(Guid applicationId, CancellationToken cancellationToken);

/// <summary>
/// Send membership information to the BPDM Pool
/// </summary>
/// <param name="businessPartnerNumber">The BPN to set Cx Membership</param>
/// <param name="cancellationToken">Cancellation Token</param>
/// <returns>Returns <c>true</c> if the service call was successful, otherwise <c>false</c></returns>
Task<bool> SetCxMembership(string businessPartnerNumber, CancellationToken cancellationToken);
}
40 changes: 40 additions & 0 deletions src/externalsystems/Bpdm.Library/Models/BpdmCxMembershipDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/********************************************************************************
* Copyright (c) 2022 BMW Group AG
* Copyright (c) 2022 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.Bpdm.Library.Models;

/// <summary>
/// Modal to send multiple data to BPDM.
/// </summary>
/// <param name="Memberships">List of memberships</param>
public record BpdmCxMembership(
[property: JsonPropertyName("memberships")] IEnumerable<BpdmCxMembershipDto> Memberships
);

/// <summary>
/// Modal to send single data to BPDM.
/// </summary>
/// <param name="Bpn">Business Partner Number</param>
/// <param name="IsCatenaXMember">True, if BPN has added for Catena-X mambership</param>
public record BpdmCxMembershipDto(
[property: JsonPropertyName("bpnL")] string Bpn,
[property: JsonPropertyName("isCatenaXMember")] bool IsCatenaXMember
);
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ public enum ProcessStepTypeId
RETRIGGER_REMOVE_REGISTRATION_ROLES = 41,
RETRIGGER_SET_THEME = 42,
RETRIGGER_SET_MEMBERSHIP = 43,
SET_CX_MEMBERSHIP_IN_BPDM = 44,
RETRIGGER_SET_CX_MEMBERSHIP_IN_BPDM = 45,

// OfferSubscriptionProcess
TRIGGER_PROVIDER = 100,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public class ApplicationChecklistHandlerService(
new(ProcessStepTypeId.REMOVE_REGISTRATION_ROLES, new(ApplicationChecklistEntryTypeId.APPLICATION_ACTIVATION, true, applicationActivationService.RemoveRegistrationRoles, (ex, _, _) => checklistService.HandleServiceErrorAsync(ex, ProcessStepTypeId.RETRIGGER_REMOVE_REGISTRATION_ROLES))),
new(ProcessStepTypeId.SET_THEME, new(ApplicationChecklistEntryTypeId.APPLICATION_ACTIVATION, true, applicationActivationService.SetTheme, (ex, _, _) => checklistService.HandleServiceErrorAsync(ex, ProcessStepTypeId.RETRIGGER_SET_THEME))),
new(ProcessStepTypeId.SET_MEMBERSHIP, new(ApplicationChecklistEntryTypeId.APPLICATION_ACTIVATION, true, applicationActivationService.SetMembership, (ex, _, _) => checklistService.HandleServiceErrorAsync(ex, ProcessStepTypeId.RETRIGGER_SET_MEMBERSHIP))),
new(ProcessStepTypeId.SET_CX_MEMBERSHIP_IN_BPDM, new(ApplicationChecklistEntryTypeId.APPLICATION_ACTIVATION, true, applicationActivationService.SetCxMembership, (ex, _, _) => checklistService.HandleServiceErrorAsync(ex, ProcessStepTypeId.RETRIGGER_SET_CX_MEMBERSHIP_IN_BPDM))),
new(ProcessStepTypeId.FINISH_APPLICATION_ACTIVATION, new(ApplicationChecklistEntryTypeId.APPLICATION_ACTIVATION, true, applicationActivationService.SaveApplicationActivationToDatabase, null))
]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public static class ApplicationChecklistEntryTypeIdExtensions
new(ApplicationChecklistEntryTypeId.IDENTITY_WALLET, [ProcessStepTypeId.RETRIGGER_IDENTITY_WALLET, ProcessStepTypeId.RETRIGGER_CREATE_DIM_WALLET, ProcessStepTypeId.RETRIGGER_VALIDATE_DID_DOCUMENT]),
new(ApplicationChecklistEntryTypeId.SELF_DESCRIPTION_LP, [ProcessStepTypeId.RETRIGGER_SELF_DESCRIPTION_LP]),
new(ApplicationChecklistEntryTypeId.BUSINESS_PARTNER_NUMBER, [ProcessStepTypeId.RETRIGGER_BUSINESS_PARTNER_NUMBER_PUSH, ProcessStepTypeId.RETRIGGER_BUSINESS_PARTNER_NUMBER_PULL]),
new(ApplicationChecklistEntryTypeId.APPLICATION_ACTIVATION, [ProcessStepTypeId.RETRIGGER_ASSIGN_INITIAL_ROLES, ProcessStepTypeId.RETRIGGER_ASSIGN_BPN_TO_USERS, ProcessStepTypeId.RETRIGGER_REMOVE_REGISTRATION_ROLES, ProcessStepTypeId.RETRIGGER_SET_THEME, ProcessStepTypeId.RETRIGGER_SET_MEMBERSHIP])
new(ApplicationChecklistEntryTypeId.APPLICATION_ACTIVATION, [ProcessStepTypeId.RETRIGGER_ASSIGN_INITIAL_ROLES, ProcessStepTypeId.RETRIGGER_ASSIGN_BPN_TO_USERS, ProcessStepTypeId.RETRIGGER_REMOVE_REGISTRATION_ROLES, ProcessStepTypeId.RETRIGGER_SET_THEME, ProcessStepTypeId.RETRIGGER_SET_MEMBERSHIP, ProcessStepTypeId.RETRIGGER_SET_CX_MEMBERSHIP_IN_BPDM])
]);

public static IEnumerable<ProcessStepTypeId> GetManualTriggerProcessStepIds(this ApplicationChecklistEntryTypeId entryTypeId) =>
Expand All @@ -56,6 +56,7 @@ public static (ProcessStepTypeId ProcessStepTypeId, ApplicationChecklistEntrySta
ProcessStepTypeId.RETRIGGER_REMOVE_REGISTRATION_ROLES => (ProcessStepTypeId.REMOVE_REGISTRATION_ROLES, ApplicationChecklistEntryStatusId.IN_PROGRESS),
ProcessStepTypeId.RETRIGGER_SET_THEME => (ProcessStepTypeId.SET_THEME, ApplicationChecklistEntryStatusId.IN_PROGRESS),
ProcessStepTypeId.RETRIGGER_SET_MEMBERSHIP => (ProcessStepTypeId.SET_MEMBERSHIP, ApplicationChecklistEntryStatusId.IN_PROGRESS),
ProcessStepTypeId.RETRIGGER_SET_CX_MEMBERSHIP_IN_BPDM => (ProcessStepTypeId.SET_CX_MEMBERSHIP_IN_BPDM, ApplicationChecklistEntryStatusId.IN_PROGRESS),
_ => default,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

<ItemGroup>
<ProjectReference Include="..\..\externalsystems\Custodian.Library\Custodian.Library.csproj" />
<ProjectReference Include="..\..\externalsystems\Bpdm.Library\Bpdm.Library.csproj" />
<ProjectReference Include="..\..\framework\Framework.DateTimeProvider\Framework.DateTimeProvider.csproj" />
<ProjectReference Include="..\..\notifications\Notifications.Library\Notifications.Library.csproj" />
<ProjectReference Include="..\..\processes\Mailing.Library\Mailing.Library.csproj" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

using Microsoft.Extensions.Options;
using Org.Eclipse.TractusX.Portal.Backend.ApplicationActivation.Library.DependencyInjection;
using Org.Eclipse.TractusX.Portal.Backend.Bpdm.Library;
using Org.Eclipse.TractusX.Portal.Backend.Custodian.Library;
using Org.Eclipse.TractusX.Portal.Backend.Framework.Async;
using Org.Eclipse.TractusX.Portal.Backend.Framework.DateTimeProvider;
Expand All @@ -43,6 +44,7 @@ public class ApplicationActivationService(
IProvisioningManager provisioningManager,
IDateTimeProvider dateTime,
ICustodianService custodianService,
IBpdmService bpdmService,
IMailingProcessCreation mailingProcessCreation,
IOptions<ApplicationActivationSettings> options)
: IApplicationActivationService
Expand Down Expand Up @@ -288,6 +290,26 @@ await provisioningManager.DeleteClientRolesFromCentralUserAsync(iamUserId, roleN
{
entry.Comment = resultMessage;
},
Enumerable.Repeat(ProcessStepTypeId.SET_CX_MEMBERSHIP_IN_BPDM, 1),
null,
true,
null);
}

public async Task<IApplicationChecklistService.WorkerChecklistProcessStepExecutionResult> SetCxMembership(IApplicationChecklistService.WorkerChecklistProcessStepData context, CancellationToken cancellationToken)
{
var businessPartnerNumber = await portalRepositories.GetInstance<IApplicationRepository>()
.GetBpnForApplicationIdAsync(context.ApplicationId)
.ConfigureAwait(ConfigureAwaitOptions.None);
if (businessPartnerNumber is null)
{
throw new ConflictException("BusinessPartnerNumber must be set");
}

var resultMessage = await bpdmService.SetCxMembership(businessPartnerNumber, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None);
return new IApplicationChecklistService.WorkerChecklistProcessStepExecutionResult(
ProcessStepStatusId.DONE,
null,
Enumerable.Repeat(ProcessStepTypeId.FINISH_APPLICATION_ACTIVATION, 1),
null,
true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@ public interface IApplicationActivationService
Task<IApplicationChecklistService.WorkerChecklistProcessStepExecutionResult> RemoveRegistrationRoles(IApplicationChecklistService.WorkerChecklistProcessStepData context, CancellationToken cancellationToken);
Task<IApplicationChecklistService.WorkerChecklistProcessStepExecutionResult> SetTheme(IApplicationChecklistService.WorkerChecklistProcessStepData context, CancellationToken cancellationToken);
Task<IApplicationChecklistService.WorkerChecklistProcessStepExecutionResult> SetMembership(IApplicationChecklistService.WorkerChecklistProcessStepData context, CancellationToken cancellationToken);
Task<IApplicationChecklistService.WorkerChecklistProcessStepExecutionResult> SetCxMembership(IApplicationChecklistService.WorkerChecklistProcessStepData context, CancellationToken cancellationToken);
Task<IApplicationChecklistService.WorkerChecklistProcessStepExecutionResult> SaveApplicationActivationToDatabase(IApplicationChecklistService.WorkerChecklistProcessStepData context, CancellationToken cancellationToken);
}
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,7 @@ public async Task TriggerChecklistAsync_WithFailingChecklistServiceCall_ReturnsE
[InlineData(ApplicationChecklistEntryTypeId.APPLICATION_ACTIVATION, ProcessStepTypeId.RETRIGGER_REMOVE_REGISTRATION_ROLES, ProcessStepTypeId.REMOVE_REGISTRATION_ROLES, ApplicationChecklistEntryStatusId.IN_PROGRESS)]
[InlineData(ApplicationChecklistEntryTypeId.APPLICATION_ACTIVATION, ProcessStepTypeId.RETRIGGER_SET_THEME, ProcessStepTypeId.SET_THEME, ApplicationChecklistEntryStatusId.IN_PROGRESS)]
[InlineData(ApplicationChecklistEntryTypeId.APPLICATION_ACTIVATION, ProcessStepTypeId.RETRIGGER_SET_MEMBERSHIP, ProcessStepTypeId.SET_MEMBERSHIP, ApplicationChecklistEntryStatusId.IN_PROGRESS)]
[InlineData(ApplicationChecklistEntryTypeId.APPLICATION_ACTIVATION, ProcessStepTypeId.RETRIGGER_SET_CX_MEMBERSHIP_IN_BPDM, ProcessStepTypeId.SET_CX_MEMBERSHIP_IN_BPDM, ApplicationChecklistEntryStatusId.IN_PROGRESS)]
public async Task TriggerChecklistAsync_WithValidData_ReturnsExpected(ApplicationChecklistEntryTypeId typeId, ProcessStepTypeId stepId, ProcessStepTypeId nextStepId, ApplicationChecklistEntryStatusId statusId)
{
// Arrange
Expand Down Expand Up @@ -789,6 +790,7 @@ public async Task TriggerChecklistAsync_WithWrongProcessStepForChecklist_ThrowsC
[InlineData(ApplicationChecklistEntryTypeId.APPLICATION_ACTIVATION, ProcessStepTypeId.RETRIGGER_REMOVE_REGISTRATION_ROLES)]
[InlineData(ApplicationChecklistEntryTypeId.APPLICATION_ACTIVATION, ProcessStepTypeId.RETRIGGER_SET_THEME)]
[InlineData(ApplicationChecklistEntryTypeId.APPLICATION_ACTIVATION, ProcessStepTypeId.RETRIGGER_SET_MEMBERSHIP)]
[InlineData(ApplicationChecklistEntryTypeId.APPLICATION_ACTIVATION, ProcessStepTypeId.RETRIGGER_SET_CX_MEMBERSHIP_IN_BPDM)]
public async Task TriggerChecklistAsync_Success(ApplicationChecklistEntryTypeId typeId, ProcessStepTypeId stepId)
{
// Arrange
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -359,4 +359,18 @@ public async Task RetriggerDeleteCentralUser_ReturnsExpectedResult()
A.CallTo(() => _logic.RetriggerDeleteCentralUser(processId)).MustHaveHappenedOnceExactly();
result.Should().BeOfType<NoContentResult>();
}

[Fact]
public async Task RetriggerSetCxMembership_ReturnsExpectedResult()
{
// Arrange
var applicationId = _fixture.Create<Guid>();

// Act
var result = await _controller.RetriggerSetCxMembership(applicationId);

// Assert
A.CallTo(() => _logic.TriggerChecklistAsync(applicationId, ApplicationChecklistEntryTypeId.APPLICATION_ACTIVATION, ProcessStepTypeId.RETRIGGER_SET_CX_MEMBERSHIP_IN_BPDM)).MustHaveHappenedOnceExactly();
result.Should().BeOfType<NoContentResult>();
}
}
46 changes: 46 additions & 0 deletions tests/externalsystems/Bpdm.Library/BpdmServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -662,4 +662,50 @@ public async Task GetSharingState_WithInvalidData_ThrowsServiceException()
}

#endregion

#region SetCxMembership

[Fact]
public async Task SetCxMembership_WithValidData_DoesNotThrowException()
{
// Arrange
const string bpn = "123";
var httpMessageHandlerMock = new HttpMessageHandlerMock(HttpStatusCode.OK);
using var httpClient = new HttpClient(httpMessageHandlerMock)
{
BaseAddress = new Uri("https://base.address.com")
};
A.CallTo(() => _tokenService.GetAuthorizedClient<BpdmService>(_options.Value, A<CancellationToken>._))
.Returns(httpClient);
var sut = new BpdmService(_tokenService, _options);

// Act
var result = await sut.SetCxMembership(bpn, CancellationToken.None);

// Assert
result.Should().BeTrue();
}

[Fact]
public async Task SetCxMembership_WithInvalidData_ThrowsServiceException()
{
// Arrange
const string bpn = "123";
var httpMessageHandlerMock = new HttpMessageHandlerMock(HttpStatusCode.BadRequest);
using var httpClient = new HttpClient(httpMessageHandlerMock)
{
BaseAddress = new Uri("https://base.address.com")
};
A.CallTo(() => _tokenService.GetAuthorizedClient<BpdmService>(_options.Value, A<CancellationToken>._)).Returns(httpClient);
var sut = new BpdmService(_tokenService, _options);

// Act
async Task Act() => await sut.SetCxMembership(bpn, CancellationToken.None);

// Assert
var ex = await Assert.ThrowsAsync<ServiceException>(Act);
ex.Message.Should().Contain("bpdm-put-cx-membership");
}

#endregion
}
Loading

0 comments on commit d94f222

Please sign in to comment.