Skip to content

Commit c930aee

Browse files
committed
feat: add process to add and remove bpn from users
Refs: #1098
1 parent ca0d21f commit c930aee

File tree

70 files changed

+11295
-430
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+11295
-430
lines changed

docs/api/administration-service.yaml

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5529,11 +5529,6 @@ paths:
55295529
responses:
55305530
'200':
55315531
description: The business partner numbers have been added successfully.
5532-
content:
5533-
application/json:
5534-
schema:
5535-
type: integer
5536-
format: int32
55375532
'400':
55385533
description: Business Partner Numbers must not exceed 20 characters.
55395534
content:
@@ -5575,11 +5570,6 @@ paths:
55755570
responses:
55765571
'200':
55775572
description: The business partner number have been added successfully.
5578-
content:
5579-
application/json:
5580-
schema:
5581-
type: integer
5582-
format: int32
55835573
'400':
55845574
description: Business Partner Numbers must not exceed 20 characters.
55855575
content:
@@ -5630,11 +5620,6 @@ paths:
56305620
responses:
56315621
'200':
56325622
description: Empty response on success.
5633-
content:
5634-
application/json:
5635-
schema:
5636-
type: integer
5637-
format: int32
56385623
'403':
56395624
description: ForbiddenException if both users does not belongs to same company
56405625
content:
@@ -5935,6 +5920,45 @@ paths:
59355920
description: Internal Server Error
59365921
'401':
59375922
description: The User is unauthorized
5923+
'/api/administration/user/{processId}/retrigger-user-bpn-process':
5924+
post:
5925+
tags:
5926+
- User
5927+
summary: 'Retriggers the last failed step (Authorization required - Roles: modify_user_account)'
5928+
parameters:
5929+
- name: processId
5930+
in: path
5931+
description: Id of the process that should be triggered
5932+
required: true
5933+
schema:
5934+
type: string
5935+
format: uuid
5936+
example: 251e4596-5ff0-4176-b544-840b04ebeb93
5937+
- name: processStepTypeId
5938+
in: query
5939+
description: Id of the process step type which should be retriggered
5940+
schema:
5941+
$ref: '#/components/schemas/ProcessStepTypeId'
5942+
example: ProcessStepTypeId.DELETE_BPN_FROM_CENTRAL_USER
5943+
responses:
5944+
'204':
5945+
description: Empty response on success.
5946+
'400':
5947+
description: Bad Request
5948+
content:
5949+
application/json:
5950+
schema:
5951+
$ref: '#/components/schemas/ErrorResponse'
5952+
'404':
5953+
description: No Process found for the processId
5954+
content:
5955+
application/json:
5956+
schema:
5957+
$ref: '#/components/schemas/ErrorResponse'
5958+
'500':
5959+
description: Internal Server Error
5960+
'401':
5961+
description: The User is unauthorized
59385962
components:
59395963
schemas:
59405964
AgreementConsentData:
@@ -7596,6 +7620,14 @@ components:
75967620
- SELF_DESCRIPTION_COMPANY_CREATION
75977621
- RETRIGGER_SELF_DESCRIPTION_CONNECTOR_CREATION
75987622
- RETRIGGER_SELF_DESCRIPTION_COMPANY_CREATION
7623+
- DELETE_BPN_FROM_CENTRAL_USER
7624+
- DELETE_BPN_FROM_IDENTITY
7625+
- RETRIGGER_DELETE_BPN_FROM_CENTRAL_USER
7626+
- CHECK_LEGAL_ENTITY_DATA
7627+
- ADD_BPN_TO_IDENTITY
7628+
- CLEANUP_USER_BPN
7629+
- RETRIGGER_CHECK_LEGAL_ENTITY_DATA
7630+
- RETRIGGER_ADD_BPN_TO_IDENTITY
75997631
type: string
76007632
ProviderDetailData:
76017633
type: object

docs/api/apps-service.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3685,6 +3685,14 @@ components:
36853685
- SELF_DESCRIPTION_COMPANY_CREATION
36863686
- RETRIGGER_SELF_DESCRIPTION_CONNECTOR_CREATION
36873687
- RETRIGGER_SELF_DESCRIPTION_COMPANY_CREATION
3688+
- DELETE_BPN_FROM_CENTRAL_USER
3689+
- DELETE_BPN_FROM_IDENTITY
3690+
- RETRIGGER_DELETE_BPN_FROM_CENTRAL_USER
3691+
- CHECK_LEGAL_ENTITY_DATA
3692+
- ADD_BPN_TO_IDENTITY
3693+
- CLEANUP_USER_BPN
3694+
- RETRIGGER_CHECK_LEGAL_ENTITY_DATA
3695+
- RETRIGGER_ADD_BPN_TO_IDENTITY
36883696
type: string
36893697
SubscriberSubscriptionDetailData:
36903698
type: object

docs/api/services-service.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2256,6 +2256,14 @@ components:
22562256
- SELF_DESCRIPTION_COMPANY_CREATION
22572257
- RETRIGGER_SELF_DESCRIPTION_CONNECTOR_CREATION
22582258
- RETRIGGER_SELF_DESCRIPTION_COMPANY_CREATION
2259+
- DELETE_BPN_FROM_CENTRAL_USER
2260+
- DELETE_BPN_FROM_IDENTITY
2261+
- RETRIGGER_DELETE_BPN_FROM_CENTRAL_USER
2262+
- CHECK_LEGAL_ENTITY_DATA
2263+
- ADD_BPN_TO_IDENTITY
2264+
- CLEANUP_USER_BPN
2265+
- RETRIGGER_CHECK_LEGAL_ENTITY_DATA
2266+
- RETRIGGER_ADD_BPN_TO_IDENTITY
22592267
type: string
22602268
ProviderSubscriptionDetailData:
22612269
type: object

src/administration/Administration.Service/BusinessLogic/IUserBusinessLogic.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models;
2121
using Org.Eclipse.TractusX.Portal.Backend.Framework.Models;
2222
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models;
23+
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums;
2324
using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Models;
2425

2526
namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLogic;
@@ -32,8 +33,8 @@ public interface IUserBusinessLogic
3233
Task<Guid> CreateOwnCompanyIdpUserAsync(Guid identityProviderId, UserCreationInfoIdp userCreationInfo);
3334
Task<Pagination.Response<CompanyUserData>> GetOwnCompanyUserDatasAsync(int page, int size, GetOwnCompanyUsersFilter filter);
3435
Task<CompanyUserDetailData> GetOwnCompanyUserDetailsAsync(Guid userId);
35-
Task<CompanyUsersBpnDetails> AddOwnCompanyUsersBusinessPartnerNumbersAsync(Guid userId, string token, IEnumerable<string> businessPartnerNumbers, CancellationToken cancellationToken);
36-
Task<CompanyUsersBpnDetails> AddOwnCompanyUsersBusinessPartnerNumberAsync(Guid userId, string token, string businessPartnerNumber, CancellationToken cancellationToken);
36+
Task AddOwnCompanyUsersBusinessPartnerNumbersAsync(Guid userId, IEnumerable<string> businessPartnerNumbers, CancellationToken cancellationToken);
37+
Task AddOwnCompanyUsersBusinessPartnerNumberAsync(Guid userId, string businessPartnerNumber, CancellationToken cancellationToken);
3738
Task<CompanyOwnUserDetails> GetOwnUserDetails();
3839
Task<CompanyUserDetails> UpdateOwnUserDetails(Guid companyUserId, OwnCompanyUserEditableDetails ownCompanyUserEditableDetails);
3940

@@ -46,5 +47,6 @@ public interface IUserBusinessLogic
4647
IAsyncEnumerable<Guid> DeleteOwnCompanyUsersAsync(IEnumerable<Guid> userIds);
4748
Task<bool> ExecuteOwnCompanyUserPasswordReset(Guid companyUserId);
4849
Task<Pagination.Response<CompanyAppUserDetails>> GetOwnCompanyAppUsersAsync(Guid appId, int page, int size, CompanyUserFilter filter);
49-
Task<int> DeleteOwnUserBusinessPartnerNumbersAsync(Guid userId, string businessPartnerNumber);
50+
Task DeleteOwnUserBusinessPartnerNumbersAsync(Guid userId, string businessPartnerNumber);
51+
Task RetriggerUserBpnProcess(Guid processId, ProcessStepTypeId processStepTypeId);
5052
}

src/administration/Administration.Service/BusinessLogic/UserBusinessLogic.cs

Lines changed: 38 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,15 @@
2323
using Org.Eclipse.TractusX.Portal.Backend.Framework.Async;
2424
using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling;
2525
using Org.Eclipse.TractusX.Portal.Backend.Framework.Identity;
26-
using Org.Eclipse.TractusX.Portal.Backend.Framework.Linq;
2726
using Org.Eclipse.TractusX.Portal.Backend.Framework.Models;
27+
using Org.Eclipse.TractusX.Portal.Backend.Framework.Processes.Library.Enums;
28+
using Org.Eclipse.TractusX.Portal.Backend.Framework.Processes.Library.Extensions;
2829
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess;
2930
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models;
3031
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories;
32+
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities;
3133
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums;
34+
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Extensions;
3235
using Org.Eclipse.TractusX.Portal.Backend.Processes.Mailing.Library;
3336
using Org.Eclipse.TractusX.Portal.Backend.Provisioning.DBAccess;
3437
using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library;
@@ -50,7 +53,7 @@ public class UserBusinessLogic(
5053
IIdentityService identityService,
5154
IMailingProcessCreation mailingProcessCreation,
5255
ILogger<UserBusinessLogic> logger,
53-
IBpnAccess bpnAccess,
56+
IBpdmAccessService bpdmAccessService,
5457
IOptions<UserSettings> options) : IUserBusinessLogic
5558
{
5659
private readonly UserSettings _settings = options.Value;
@@ -267,74 +270,38 @@ await Task.WhenAll(details.IdpUserIds.Select(async x =>
267270
details.Email);
268271
}
269272

270-
public async Task<CompanyUsersBpnDetails> AddOwnCompanyUsersBusinessPartnerNumbersAsync(Guid userId, string token, IEnumerable<string> businessPartnerNumbers, CancellationToken cancellationToken)
273+
public async Task AddOwnCompanyUsersBusinessPartnerNumbersAsync(Guid userId, IEnumerable<string> businessPartnerNumbers, CancellationToken cancellationToken)
271274
{
272275
var companyId = _identityData.CompanyId;
276+
277+
var invalidBpns = businessPartnerNumbers.Where(bpn => bpn.Length > 20);
278+
if (invalidBpns.Any())
279+
{
280+
throw new ControllerArgumentException($"BusinessPartnerNumbers {string.Join(",", invalidBpns)} must not exceed 20 characters");
281+
}
282+
273283
var (assignedBusinessPartnerNumbers, isValidUser) = await portalRepositories.GetInstance<IUserRepository>().GetOwnCompanyUserWithAssignedBusinessPartnerNumbersUntrackedAsync(userId, companyId).ConfigureAwait(ConfigureAwaitOptions.None);
274284
if (!isValidUser)
275285
{
276286
throw new NotFoundException($"user {userId} not found in company {companyId}");
277287
}
278288

279-
var iamUserId = await provisioningManager.GetUserByUserName(userId.ToString()).ConfigureAwait(ConfigureAwaitOptions.None) ??
280-
throw new ConflictException($"user {userId} not found in keycloak");
281-
282-
var (successfulBpns, unsuccessfulBpns) = await businessPartnerNumbers.AggregateAwait(
283-
(SuccessfulBpns: ImmutableList.CreateBuilder<string>(), UnsuccessfulBpns: ImmutableList.CreateBuilder<UnsuccessfulBpns>()),
284-
async (acc, bpn) =>
285-
{
286-
var (bpns, error) = await CompanyUsersBpnCheck(bpn, token, cancellationToken).ConfigureAwait(false);
287-
if (error == null)
288-
{
289-
acc.SuccessfulBpns.Add(bpns);
290-
}
291-
else
292-
{
293-
acc.UnsuccessfulBpns.Add(new UnsuccessfulBpns(bpns, error.Message));
294-
}
295-
return acc;
296-
},
297-
acc => (acc.SuccessfulBpns.ToImmutable(), acc.UnsuccessfulBpns.ToImmutable()),
298-
cancellationToken
299-
).ConfigureAwait(ConfigureAwaitOptions.None);
300-
301-
if (successfulBpns.Count != 0)
289+
Action<CompanyUserAssignedBusinessPartner> CreateProcess()
302290
{
303-
await provisioningManager.AddBpnAttributetoUserAsync(iamUserId, successfulBpns).ConfigureAwait(false);
304-
successfulBpns.Except(assignedBusinessPartnerNumbers).IfAny(businessPartnersToAdd =>
305-
portalRepositories.GetInstance<IUserBusinessPartnerRepository>().CreateCompanyUserAssignedBusinessPartners(businessPartnersToAdd.Select(bpn => (userId, bpn))));
291+
var processStepRepository = portalRepositories.GetInstance<IPortalProcessStepRepository>();
292+
var processId = processStepRepository.CreateProcess(ProcessTypeId.USER_BPN).Id;
293+
processStepRepository.CreateProcessStep(ProcessStepTypeId.CHECK_LEGAL_ENTITY_DATA, ProcessStepStatusId.TODO, processId);
294+
return x => x.ProcessId = processId;
306295
}
307296

308-
await portalRepositories.SaveAsync();
309-
return new CompanyUsersBpnDetails(successfulBpns, unsuccessfulBpns);
310-
}
311-
312-
private async ValueTask<(string bpns, Exception? error)> CompanyUsersBpnCheck(string bpn, string token, CancellationToken cancellationToken)
313-
{
314-
Exception? error = null;
315-
try
316-
{
317-
if (bpn.Length > 20)
318-
{
319-
throw new ControllerArgumentException("BusinessPartnerNumbers must not exceed 20 characters");
320-
}
321-
322-
var legalEntity = await bpnAccess.FetchLegalEntityByBpn(bpn, token, cancellationToken).ConfigureAwait(false);
323-
if (!bpn.Equals(legalEntity.Bpn, StringComparison.OrdinalIgnoreCase))
324-
{
325-
throw new ConflictException("Bpdm did return incorrect bpn legal-entity-data");
326-
}
327-
}
328-
catch (Exception ex)
329-
{
330-
error = ex;
331-
}
297+
portalRepositories.GetInstance<IUserBusinessPartnerRepository>()
298+
.CreateCompanyUserAssignedBusinessPartners(businessPartnerNumbers.Except(assignedBusinessPartnerNumbers).Select(bpn => (userId, bpn, CreateProcess())));
332299

333-
return (bpn, error);
300+
await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);
334301
}
335302

336-
public Task<CompanyUsersBpnDetails> AddOwnCompanyUsersBusinessPartnerNumberAsync(Guid userId, string token, string businessPartnerNumber, CancellationToken cancellationToken) =>
337-
AddOwnCompanyUsersBusinessPartnerNumbersAsync(userId, token, Enumerable.Repeat(businessPartnerNumber, 1), cancellationToken);
303+
public Task AddOwnCompanyUsersBusinessPartnerNumberAsync(Guid userId, string businessPartnerNumber, CancellationToken cancellationToken) =>
304+
AddOwnCompanyUsersBusinessPartnerNumbersAsync(userId, Enumerable.Repeat(businessPartnerNumber, 1), cancellationToken);
338305

339306
public async Task<CompanyOwnUserDetails> GetOwnUserDetails()
340307
{
@@ -576,12 +543,10 @@ public async Task<bool> ExecuteOwnCompanyUserPasswordReset(Guid companyUserId)
576543
new[] { UserStatusId.ACTIVE, UserStatusId.INACTIVE },
577544
filter));
578545

579-
public async Task<int> DeleteOwnUserBusinessPartnerNumbersAsync(Guid userId, string businessPartnerNumber)
546+
public async Task DeleteOwnUserBusinessPartnerNumbersAsync(Guid userId, string businessPartnerNumber)
580547
{
581548
var userBusinessPartnerRepository = portalRepositories.GetInstance<IUserBusinessPartnerRepository>();
582-
583549
var (isValidUser, isAssignedBusinessPartner, isSameCompany) = await userBusinessPartnerRepository.GetOwnCompanyUserWithAssignedBusinessPartnerNumbersAsync(userId, _identityData.CompanyId, businessPartnerNumber.ToUpper()).ConfigureAwait(ConfigureAwaitOptions.None);
584-
585550
if (!isValidUser)
586551
{
587552
throw new NotFoundException($"user {userId} does not exist");
@@ -597,12 +562,21 @@ public async Task<int> DeleteOwnUserBusinessPartnerNumbersAsync(Guid userId, str
597562
throw new ForbiddenException($"userId {userId} and adminUserId {_identityData.IdentityId} do not belong to same company");
598563
}
599564

600-
var iamUserId = await provisioningManager.GetUserByUserName(userId.ToString()).ConfigureAwait(ConfigureAwaitOptions.None) ?? throw new ConflictException($"user {userId} is not associated with a user in keycloak");
601-
602-
userBusinessPartnerRepository.DeleteCompanyUserAssignedBusinessPartner(userId, businessPartnerNumber.ToUpper());
565+
var processStepRepository = portalRepositories.GetInstance<IPortalProcessStepRepository>();
566+
var processId = processStepRepository.CreateProcess(ProcessTypeId.USER_BPN).Id;
567+
processStepRepository.CreateProcessStep(ProcessStepTypeId.DELETE_BPN_FROM_CENTRAL_USER, ProcessStepStatusId.TODO, processId);
568+
userBusinessPartnerRepository.AttachAndModifyCompanyUserAssignedBusinessPartner(userId, businessPartnerNumber, c => c.ProcessId = processId);
569+
await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);
570+
}
603571

604-
await provisioningManager.DeleteCentralUserBusinessPartnerNumberAsync(iamUserId, businessPartnerNumber.ToUpper()).ConfigureAwait(ConfigureAwaitOptions.None);
572+
public Task RetriggerUserBpnProcess(Guid processId, ProcessStepTypeId processStepTypeId)
573+
{
574+
var (processType, _) = ProcessTypeExtensions.GetProcessStepForRetrigger(processStepTypeId);
575+
if (processType != ProcessTypeId.USER_BPN)
576+
{
577+
throw new ConflictException($"{processStepTypeId} can't be retriggered for Process {processId}");
578+
}
605579

606-
return await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);
580+
return processStepTypeId.TriggerProcessStep(processId, portalRepositories, ProcessTypeExtensions.GetProcessStepForRetrigger);
607581
}
608582
}

0 commit comments

Comments
 (0)