Skip to content

Commit

Permalink
refactor into IIdentityProviderProvisioningService
Browse files Browse the repository at this point in the history
  • Loading branch information
ntruchsess committed Nov 5, 2024
1 parent 8f5da99 commit d0e9a1b
Show file tree
Hide file tree
Showing 13 changed files with 247 additions and 131 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLog
public class UserBusinessLogic(
IProvisioningManager provisioningManager,
IUserProvisioningService userProvisioningService,
IIdentityProviderProvisioningService identityProviderProvisioningService,
IProvisioningDBAccess provisioningDbAccess,
IPortalRepositories portalRepositories,
IIdentityService identityService,
Expand Down Expand Up @@ -96,7 +97,7 @@ private async IAsyncEnumerable<string> CreateOwnCompanyUsersInternalAsync(IEnume
user => user.userName ?? user.eMail,
user => user.eMail);

var companyDisplayName = await userProvisioningService.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias;
var companyDisplayName = await identityProviderProvisioningService.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias;

await foreach (var (companyUserId, userName, password, error) in userProvisioningService.CreateOwnCompanyIdpUsersAsync(companyNameIdpAliasData, userCreationInfoIdps).ConfigureAwait(false))
{
Expand Down Expand Up @@ -137,7 +138,7 @@ private Task<IEnumerable<UserRoleData>> GetOwnCompanyUserRoleData(IEnumerable<st
public async Task<Guid> CreateOwnCompanyIdpUserAsync(Guid identityProviderId, UserCreationInfoIdp userCreationInfo)
{
var (companyNameIdpAliasData, nameCreatedBy) = await userProvisioningService.GetCompanyNameIdpAliasData(identityProviderId, _identityData.IdentityId).ConfigureAwait(ConfigureAwaitOptions.None);
var displayName = await userProvisioningService.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias;
var displayName = await identityProviderProvisioningService.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias;

if (!userCreationInfo.Roles.Any())
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLog
public class UserUploadBusinessLogic : IUserUploadBusinessLogic
{
private readonly IUserProvisioningService _userProvisioningService;
private readonly IIdentityProviderProvisioningService _identityProviderProvisioningServcie;
private readonly IMailingProcessCreation _mailingProcessCreation;
private readonly UserSettings _settings;
private readonly IIdentityData _identityData;
Expand All @@ -45,18 +46,21 @@ public class UserUploadBusinessLogic : IUserUploadBusinessLogic
/// Constructor.
/// </summary>
/// <param name="userProvisioningService">User Provisioning Service</param>
/// <param name="identityProviderProvisioningService">IdentityProvider Provisioning Service</param>
/// <param name="mailingProcessCreation">The mailingProcessCreation</param>
/// <param name="identityService">Access to the identity Service</param>
/// <param name="errorMessageService">ErrorMessage Service</param>
/// <param name="settings">Settings</param>
public UserUploadBusinessLogic(
IUserProvisioningService userProvisioningService,
IIdentityProviderProvisioningService identityProviderProvisioningService,
IMailingProcessCreation mailingProcessCreation,
IIdentityService identityService,
IErrorMessageService errorMessageService,
IOptions<UserSettings> settings)
{
_userProvisioningService = userProvisioningService;
_identityProviderProvisioningServcie = identityProviderProvisioningService;
_mailingProcessCreation = mailingProcessCreation;
_identityData = identityService.IdentityData;
_errorMessageService = errorMessageService;
Expand All @@ -79,7 +83,7 @@ private async ValueTask<UserCreationStats> UploadOwnCompanyIdpUsersInternalAsync

var displayName = companyNameIdpAliasData.IsSharedIdp
? null
: await _userProvisioningService.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias;
: await _identityProviderProvisioningServcie.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias;

var (numCreated, numLines, errors) = await CsvParser.ProcessCsvAsync(
stream,
Expand Down Expand Up @@ -162,7 +166,7 @@ private async ValueTask<UserCreationStats> UploadOwnCompanySharedIdpUsersInterna
using var stream = document.OpenReadStream();

var (companyNameIdpAliasData, nameCreatedBy) = await _userProvisioningService.GetCompanyNameSharedIdpAliasData(_identityData.IdentityId).ConfigureAwait(ConfigureAwaitOptions.None);
var displayName = await _userProvisioningService.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias;
var displayName = await _identityProviderProvisioningServcie.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias;

var validRoleData = new List<UserRoleData>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,39 @@ public async IAsyncEnumerable<IdentityProviderMapperModel> GetIdentityProviderMa
public async Task<string?> GetIdentityProviderDisplayName(string alias) =>
(await GetCentralIdentityProviderAsync(alias).ConfigureAwait(ConfigureAwaitOptions.None)).DisplayName;

public async Task UpdateOrCreateCentralIdentityProviderOrganisationMapperAsync(string idpAlias, string organisationName)
{
var mapperName = _settings.MappedCompanyAttribute + "-mapper";
IdentityProviderMapper? mapper;
try
{
mapper = (await _centralIdp.GetIdentityProviderMappersAsync(_settings.CentralRealm, idpAlias).ConfigureAwait(ConfigureAwaitOptions.None))
.SingleOrDefault(z => z.Name == mapperName);
}
catch (InvalidOperationException)
{
throw new KeycloakEntityConflictException($"idp {idpAlias} attribute-mapper {mapperName} is ambigous in keycloak");
}
if (mapper is null)
{
await CreateCentralIdentityProviderOrganisationMapperAsync(idpAlias, organisationName);
}
else
{
mapper.Config ??= new Dictionary<string, string>
{
["syncMode"] = "INHERIT",
["attribute"] = _settings.MappedCompanyAttribute,
};
mapper.Config["attribute.value"] = organisationName;
await _centralIdp.UpdateIdentityProviderMapperAsync(
_settings.CentralRealm,
idpAlias,
mapper.Id ?? throw new KeycloakEntityConflictException($"idp {idpAlias} attribute-mapper {mapperName} has no Id"),
mapper).ConfigureAwait(ConfigureAwaitOptions.None);
}
}

private async ValueTask<string> GetCentralBrokerEndpointOIDCAsync(string alias)
{
var openidconfig = await _centralIdp.GetOpenIDConfigurationAsync(_settings.CentralRealm).ConfigureAwait(ConfigureAwaitOptions.None);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,5 @@ public interface IProvisioningManager
Task<string?> GetIdentityProviderDisplayName(string alias);
Task DeleteSharedRealmAsync(string alias);
Task DeleteIdpSharedServiceAccount(string alias);
ValueTask UpdateCentralIdentityProviderOrganisationMapperAsync(string idpAlias, string companyName);
Task UpdateOrCreateCentralIdentityProviderOrganisationMapperAsync(string idpAlias, string organisationName);
}
32 changes: 0 additions & 32 deletions src/provisioning/Provisioning.Library/ProvisioningManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
using Org.Eclipse.TractusX.Portal.Backend.Keycloak.ErrorHandling;
using Org.Eclipse.TractusX.Portal.Backend.Keycloak.Factory;
using Org.Eclipse.TractusX.Portal.Backend.Keycloak.Library;
using Org.Eclipse.TractusX.Portal.Backend.Keycloak.Library.Models.IdentityProviders;
using Org.Eclipse.TractusX.Portal.Backend.Provisioning.DBAccess;
using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Enums;
using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Models;
Expand Down Expand Up @@ -183,37 +182,6 @@ public async ValueTask UpdateSharedIdentityProviderAsync(string alias, string di
await UpdateCentralIdentityProviderAsync(alias, identityProvider).ConfigureAwait(ConfigureAwaitOptions.None);
}

public async ValueTask UpdateCentralIdentityProviderOrganisationMapperAsync(string idpAlias, string companyName)
{
var mappers = await _centralIdp.GetIdentityProviderMappersAsync(_settings.CentralRealm, idpAlias).ConfigureAwait(ConfigureAwaitOptions.None);
var organisationMapperId = mappers.FirstOrDefault(z => z.Name == $"{_settings.MappedCompanyAttribute}-mapper")?.Id ?? string.Empty;
if (!string.IsNullOrEmpty(organisationMapperId))
{
await UpdateAttributeInIdentityProvider(idpAlias, organisationMapperId, _settings.MappedCompanyAttribute, companyName);
}
else
{
await CreateCentralIdentityProviderOrganisationMapperAsync(idpAlias, companyName);
}
}

private async Task UpdateAttributeInIdentityProvider(string alias, string mapperId, string attributeName, string value) => await _centralIdp.UpdateIdentityProviderMapperAsync(
_settings.CentralRealm,
alias,
mapperId,
new IdentityProviderMapper
{
Id = mapperId,
Name = attributeName + "-mapper",
_IdentityProviderMapper = "hardcoded-attribute-idp-mapper",
IdentityProviderAlias = alias,
Config = new Dictionary<string, string>
{
["syncMode"] = "INHERIT",
["attribute"] = attributeName,
["attribute.value"] = value
}
}).ConfigureAwait(ConfigureAwaitOptions.None);
public async ValueTask UpdateSharedRealmTheme(string alias, string loginTheme)
{
var identityProvider = await GetCentralIdentityProviderAsync(alias).ConfigureAwait(ConfigureAwaitOptions.None);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/********************************************************************************
* 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.Provisioning.Library.Service;

public interface IIdentityProviderProvisioningService
{
Task<string?> GetIdentityProviderDisplayName(string idpAlias);
Task UpdateCompanyNameInSharedIdentityProvider(Guid companyId, string companyName);
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,8 @@ public interface IUserProvisioningService
Task HandleCentralKeycloakCreation(UserCreationRoleDataIdpInfo user, Guid companyUserId, string companyName, string? businessPartnerNumber, Identity? identity, IEnumerable<IdentityProviderLink> identityProviderLinks, IUserRepository userRepository, IUserRolesRepository userRolesRepository);
Task<(CompanyNameIdpAliasData IdpAliasData, string NameCreatedBy)> GetCompanyNameIdpAliasData(Guid identityProviderId, Guid companyUserId);
Task<(CompanyNameIdpAliasData IdpAliasData, string NameCreatedBy)> GetCompanyNameSharedIdpAliasData(Guid companyUserId, Guid? applicationId = null);
Task<string?> GetIdentityProviderDisplayName(string idpAlias);
IAsyncEnumerable<UserRoleData> GetRoleDatas(IEnumerable<UserRoleConfig> clientRoles);
Task<IEnumerable<UserRoleData>> GetOwnCompanyPortalRoleDatas(string clientId, IEnumerable<string> roles, Guid companyId);
Task<(Identity? Identity, Guid CompanyUserId)> GetOrCreateCompanyUser(IUserRepository userRepository, string alias, UserCreationRoleDataIdpInfo user, Guid companyId, Guid identityProviderId, string? businessPartnerNumber);
Task AssignRolesToNewUserAsync(IUserRolesRepository userRolesRepository, IEnumerable<UserRoleData> roleDatas, (string IamUserId, Guid CompanyUserId) userdata);
Task UpdateCompanyNameInIdentityProvider(Guid identityId, string companyName);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/********************************************************************************
* 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 Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories;

namespace Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Service;

public class IdentityProviderProvisioningService(IPortalRepositories portalRepositories, IProvisioningManager provisioningManager) : IIdentityProviderProvisioningService
{
public Task<string?> GetIdentityProviderDisplayName(string idpAlias) =>
provisioningManager.GetCentralIdentityProviderDisplayName(idpAlias);

public async Task UpdateCompanyNameInSharedIdentityProvider(Guid companyId, string companyName)
{
var idpAlias = await portalRepositories.GetInstance<IIdentityProviderRepository>().GetSharedIdentityProviderIamAliasDataUntrackedAsync(companyId).ConfigureAwait(false) ?? throw new ConflictException($"company {companyId} is not associated with any shared idp");
await provisioningManager.UpdateSharedIdentityProviderAsync(idpAlias, companyName).ConfigureAwait(false);
await provisioningManager.UpdateOrCreateCentralIdentityProviderOrganisationMapperAsync(idpAlias, companyName).ConfigureAwait(ConfigureAwaitOptions.None);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,6 @@ private Task<string> CreateSharedIdpUserOrReturnUserId(UserCreationRoleDataIdpIn
return (new CompanyNameIdpAliasData(company.CompanyId, company.CompanyName, company.BusinessPartnerNumber, idpAlias.Alias, idpAlias.IdentityProviderId, true), createdByName);
}

public Task<string?> GetIdentityProviderDisplayName(string idpAlias) =>
_provisioningManager.GetCentralIdentityProviderDisplayName(idpAlias);

private async Task<Guid> ValidateDuplicateIdpUsersAsync(IUserRepository userRepository, string alias, UserCreationRoleDataIdpInfo user, Guid companyId)
{
var existingCompanyUserId = Guid.Empty;
Expand Down Expand Up @@ -337,11 +334,4 @@ private static void ValidateRoleData(IEnumerable<UserRoleData> roleData, string
throw new ControllerArgumentException($"invalid roles: clientId: '{clientId}', roles: [{string.Join(", ", invalid)}]");
}
}

public async Task UpdateCompanyNameInIdentityProvider(Guid identityId, string companyName)
{
var (aliasData, _) = await GetCompanyNameSharedIdpAliasData(identityId).ConfigureAwait(ConfigureAwaitOptions.None);
await _provisioningManager.UpdateSharedIdentityProviderAsync(aliasData.IdpAlias, companyName).ConfigureAwait(false);
await _provisioningManager.UpdateCentralIdentityProviderOrganisationMapperAsync(aliasData.IdpAlias, companyName).ConfigureAwait(false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public class RegistrationBusinessLogic(
IOptions<RegistrationSettings> settings,
IBpnAccess bpnAccess,
IUserProvisioningService userProvisioningService,
IIdentityProviderProvisioningService identityProviderProvisioningService,
ILogger<RegistrationBusinessLogic> logger,
IPortalRepositories portalRepositories,
IApplicationChecklistCreationService checklistService,
Expand Down Expand Up @@ -264,7 +265,7 @@ await companyDetails.ValidateDatabaseData(
UpdateApplicationStatus(applicationId, companyApplicationData.ApplicationStatusId, UpdateApplicationSteps.CompanyWithAddress, applicationRepository, dateTimeProvider);
if (existingCompanyName != companyDetails.Name)
{
await userProvisioningService.UpdateCompanyNameInIdentityProvider(_identityData.IdentityId, companyDetails.Name);
await identityProviderProvisioningService.UpdateCompanyNameInSharedIdentityProvider(_identityData.CompanyId, companyDetails.Name).ConfigureAwait(ConfigureAwaitOptions.None);
}
await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);
}
Expand Down Expand Up @@ -412,7 +413,7 @@ private async Task<int> InviteNewUserInternalAsync(Guid applicationId, UserCreat

var modified = await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);

var companyDisplayName = await userProvisioningService.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias;
var companyDisplayName = await identityProviderProvisioningService.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias;
var mailParameters = ImmutableDictionary.CreateRange(new[]
{
KeyValuePair.Create("password", password),
Expand Down
Loading

0 comments on commit d0e9a1b

Please sign in to comment.