Skip to content

Commit

Permalink
prepare refactor indentity for removal of UserEntityId
Browse files Browse the repository at this point in the history
  • Loading branch information
ntruchsess committed Nov 30, 2023
1 parent eccd27a commit cd874a1
Show file tree
Hide file tree
Showing 96 changed files with 639 additions and 850 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/********************************************************************************
* Copyright (c) 2021, 2023 BMW Group AG
* Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
Expand Down Expand Up @@ -58,14 +57,12 @@ public interface ISubscriptionConfigurationBusinessLogic
/// <summary>
/// Gets the service provider company details
/// </summary>
/// <param name="companyId">Id of the users company</param>
/// <returns>The detail data</returns>
Task<ProviderDetailReturnData> GetProviderCompanyDetailsAsync();

/// <summary>
/// Sets service provider company details
/// </summary>
/// <param name="data">Detail data for the service provider</param>
/// <param name="companyId">Id of the users company</param>
Task SetProviderCompanyDetailsAsync(ProviderDetailData data);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/********************************************************************************
* Copyright (c) 2021, 2023 BMW Group AG
* Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
Expand Down Expand Up @@ -44,7 +43,6 @@ public interface IUserBusinessLogic
/// Delete User Own Account using userId
/// </summary>
/// <param name="companyUserId"></param>
/// <param name="userId"></param>
/// <returns></returns>
Task<int> DeleteOwnUserAsync(Guid companyUserId);
IAsyncEnumerable<Guid> DeleteOwnCompanyUsersAsync(IEnumerable<Guid> userIds);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -477,12 +477,12 @@ private async ValueTask<IdentityProviderDetails> GetIdentityProviderDetailsSaml(
public async ValueTask<UserIdentityProviderLinkData> CreateOwnCompanyUserIdentityProviderLinkDataAsync(Guid companyUserId, UserIdentityProviderLinkData identityProviderLinkData)
{
var companyId = _identityService.IdentityData.CompanyId;
var (userEntityId, alias) = await GetUserAliasDataAsync(companyUserId, identityProviderLinkData.identityProviderId, companyId).ConfigureAwait(false);
var (iamUserId, alias) = await GetUserAliasDataAsync(companyUserId, identityProviderLinkData.identityProviderId, companyId).ConfigureAwait(false);

try
{
await _provisioningManager.AddProviderUserLinkToCentralUserAsync(
userEntityId,
iamUserId,
new IdentityProviderLink(
alias,
identityProviderLinkData.userId,
Expand All @@ -503,18 +503,18 @@ await _provisioningManager.AddProviderUserLinkToCentralUserAsync(
public async ValueTask<UserIdentityProviderLinkData> CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync(Guid companyUserId, Guid identityProviderId, UserLinkData userLinkData)
{
var companyId = _identityService.IdentityData.CompanyId;
var (userEntityId, alias) = await GetUserAliasDataAsync(companyUserId, identityProviderId, companyId).ConfigureAwait(false);
var (iamUserId, alias) = await GetUserAliasDataAsync(companyUserId, identityProviderId, companyId).ConfigureAwait(false);

try
{
await _provisioningManager.DeleteProviderUserLinkToCentralUserAsync(userEntityId, alias);
await _provisioningManager.DeleteProviderUserLinkToCentralUserAsync(iamUserId, alias);
}
catch (KeycloakEntityNotFoundException)
{
// for create-and-update semantics this is expected and not an error
}
await _provisioningManager.AddProviderUserLinkToCentralUserAsync(
userEntityId,
iamUserId,
new IdentityProviderLink(
alias,
userLinkData.userId,
Expand All @@ -530,9 +530,9 @@ await _provisioningManager.AddProviderUserLinkToCentralUserAsync(
public async ValueTask<UserIdentityProviderLinkData> GetOwnCompanyUserIdentityProviderLinkDataAsync(Guid companyUserId, Guid identityProviderId)
{
var companyId = _identityService.IdentityData.CompanyId;
var (userEntityId, alias) = await GetUserAliasDataAsync(companyUserId, identityProviderId, companyId).ConfigureAwait(false);
var (iamUserId, alias) = await GetUserAliasDataAsync(companyUserId, identityProviderId, companyId).ConfigureAwait(false);

var result = await _provisioningManager.GetProviderUserLinkDataForCentralUserIdAsync(userEntityId).FirstOrDefaultAsync(identityProviderLink => identityProviderLink.Alias == alias).ConfigureAwait(false);
var result = await _provisioningManager.GetProviderUserLinkDataForCentralUserIdAsync(iamUserId).FirstOrDefaultAsync(identityProviderLink => identityProviderLink.Alias == alias).ConfigureAwait(false);

if (result == default)
{
Expand All @@ -547,10 +547,10 @@ public async ValueTask<UserIdentityProviderLinkData> GetOwnCompanyUserIdentityPr
public async ValueTask DeleteOwnCompanyUserIdentityProviderDataAsync(Guid companyUserId, Guid identityProviderId)
{
var companyId = _identityService.IdentityData.CompanyId;
var (userEntityId, alias) = await GetUserAliasDataAsync(companyUserId, identityProviderId, companyId).ConfigureAwait(false);
var (iamUserId, alias) = await GetUserAliasDataAsync(companyUserId, identityProviderId, companyId).ConfigureAwait(false);
try
{
await _provisioningManager.DeleteProviderUserLinkToCentralUserAsync(userEntityId, alias).ConfigureAwait(false);
await _provisioningManager.DeleteProviderUserLinkToCentralUserAsync(iamUserId, alias).ConfigureAwait(false);
}
catch (KeycloakEntityNotFoundException e)
{
Expand Down Expand Up @@ -684,20 +684,20 @@ private UserUpdateError CreateUserUpdateError(int line, Exception error) =>
var success = false;
try
{
var (userEntityId, existingProfile, links) = await GetExistingUserAndLinkDataAsync(userRepository, companyUserId, companyId).ConfigureAwait(false);
var (iamUserId, existingProfile, links) = await GetExistingUserAndLinkDataAsync(userRepository, companyUserId, companyId).ConfigureAwait(false);
var existingLinks = await links.ToListAsync(cancellationToken).ConfigureAwait(false);
var updated = false;

cancellationToken.ThrowIfCancellationRequested();

foreach (var identityProviderLink in identityProviderLinks)
{
updated |= await UpdateIdentityProviderLinksAsync(userEntityId, companyUserId, identityProviderLink, existingLinks, sharedIdpAlias).ConfigureAwait(false);
updated |= await UpdateIdentityProviderLinksAsync(iamUserId, companyUserId, identityProviderLink, existingLinks, sharedIdpAlias).ConfigureAwait(false);
}

if (existingProfile != profile)
{
await UpdateUserProfileAsync(userRepository, userEntityId, companyUserId, profile, existingLinks, sharedIdpAlias).ConfigureAwait(false);
await UpdateUserProfileAsync(userRepository, iamUserId, companyUserId, profile, existingLinks, sharedIdpAlias).ConfigureAwait(false);
updated = true;
}
success = updated;
Expand Down Expand Up @@ -726,23 +726,25 @@ private UserUpdateError CreateUserUpdateError(int line, Exception error) =>
return (sharedIdpAlias, validAliase);
}

private async ValueTask<(string UserEntityId, UserProfile ExistingProfile, IAsyncEnumerable<IdentityProviderLink> ExistingLinks)> GetExistingUserAndLinkDataAsync(IUserRepository userRepository, Guid companyUserId, Guid companyId)
private async ValueTask<(string IamUserId, UserProfile ExistingProfile, IAsyncEnumerable<IdentityProviderLink> ExistingLinks)> GetExistingUserAndLinkDataAsync(IUserRepository userRepository, Guid companyUserId, Guid companyId)
{
var userEntityData = await userRepository.GetUserEntityDataAsync(companyUserId, companyId).ConfigureAwait(false);
if (userEntityData == default)
{
throw new ControllerArgumentException($"unexpected value of {_settings.CsvSettings.HeaderUserId}: '{companyUserId}'");
}
var (userEntityId, existingFirstName, existingLastName, existingEmail) = userEntityData;
var (existingFirstName, existingLastName, existingEmail) = userEntityData;

var iamUserId = await _provisioningManager.GetUserByUserName(companyUserId.ToString()).ConfigureAwait(false) ?? throw new ConflictException($"user {companyUserId} does not exist in keycloak");

return (
userEntityId,
iamUserId,
new UserProfile(existingFirstName, existingLastName, existingEmail),
_provisioningManager.GetProviderUserLinkDataForCentralUserIdAsync(userEntityId)
_provisioningManager.GetProviderUserLinkDataForCentralUserIdAsync(iamUserId)
);
}

private async ValueTask<bool> UpdateIdentityProviderLinksAsync(string userEntityId, Guid companyUserId, IdentityProviderLink identityProviderLink, IEnumerable<IdentityProviderLink> existingLinks, string? sharedIdpAlias)
private async ValueTask<bool> UpdateIdentityProviderLinksAsync(string iamUserId, Guid companyUserId, IdentityProviderLink identityProviderLink, IEnumerable<IdentityProviderLink> existingLinks, string? sharedIdpAlias)
{
var (alias, userId, userName) = identityProviderLink;

Expand All @@ -761,17 +763,17 @@ private async ValueTask<bool> UpdateIdentityProviderLinksAsync(string userEntity

if (existingLink != null)
{
await _provisioningManager.DeleteProviderUserLinkToCentralUserAsync(userEntityId, alias).ConfigureAwait(false);
await _provisioningManager.DeleteProviderUserLinkToCentralUserAsync(iamUserId, alias).ConfigureAwait(false);
}
await _provisioningManager.AddProviderUserLinkToCentralUserAsync(userEntityId, identityProviderLink).ConfigureAwait(false);
await _provisioningManager.AddProviderUserLinkToCentralUserAsync(iamUserId, identityProviderLink).ConfigureAwait(false);
return true;
}

private async ValueTask UpdateUserProfileAsync(IUserRepository userRepository, string userEntityId, Guid companyUserId, UserProfile profile, IEnumerable<IdentityProviderLink> existingLinks, string? sharedIdpAlias)
private async ValueTask UpdateUserProfileAsync(IUserRepository userRepository, string iamUserId, Guid companyUserId, UserProfile profile, IEnumerable<IdentityProviderLink> existingLinks, string? sharedIdpAlias)
{
var (firstName, lastName, email) = (profile.FirstName ?? "", profile.LastName ?? "", profile.Email ?? "");

await _provisioningManager.UpdateCentralUserAsync(userEntityId, firstName, lastName, email).ConfigureAwait(false);
await _provisioningManager.UpdateCentralUserAsync(iamUserId, firstName, lastName, email).ConfigureAwait(false);

if (sharedIdpAlias != null)
{
Expand Down Expand Up @@ -952,50 +954,51 @@ private async IAsyncEnumerable<string> GetOwnCompanyUsersIdentityProviderDataLin

private async IAsyncEnumerable<(Guid CompanyUserId, UserProfile UserProfile, IAsyncEnumerable<IdentityProviderLink> LinkDatas)> GetOwnCompanyIdentityProviderLinkDataInternalAsync(Guid companyId)
{
await foreach (var (companyUserId, firstName, lastName, email, userEntityId) in _portalRepositories.GetInstance<IUserRepository>()
await foreach (var (companyUserId, firstName, lastName, email) in _portalRepositories.GetInstance<IUserRepository>()
.GetOwnCompanyUserQuery(companyId)
.Select(companyUser =>
new ValueTuple<Guid, string?, string?, string?, string?>(
new ValueTuple<Guid, string?, string?, string?>(
companyUser.Id,
companyUser.Firstname,
companyUser.Lastname,
companyUser.Email,
companyUser.Identity!.UserEntityId))
companyUser.Email))
.ToAsyncEnumerable().ConfigureAwait(false))
{
if (userEntityId != null)
var iamUserId = await _provisioningManager.GetUserByUserName(companyUserId.ToString()).ConfigureAwait(false);
if (iamUserId != null)
{
yield return (
companyUserId,
new UserProfile(firstName, lastName, email),
_provisioningManager.GetProviderUserLinkDataForCentralUserIdAsync(userEntityId)
_provisioningManager.GetProviderUserLinkDataForCentralUserIdAsync(iamUserId)
);
}
}
}

private async ValueTask<(string UserEntityId, string Alias)> GetUserAliasDataAsync(Guid companyUserId, Guid identityProviderId, Guid companyId)
private async ValueTask<(string IamUserId, string Alias)> GetUserAliasDataAsync(Guid companyUserId, Guid identityProviderId, Guid companyId)
{
var userAliasData = await _portalRepositories.GetInstance<IIdentityProviderRepository>().GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, companyId).ConfigureAwait(false);
if (userAliasData == default)
var (isValidUser, alias, isSameCompany) = await _portalRepositories.GetInstance<IIdentityProviderRepository>().GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, companyId).ConfigureAwait(false);
if (!isValidUser)
{
throw new NotFoundException($"companyUserId {companyUserId} does not exist");
}
if (userAliasData.UserEntityId == null)
{
throw new UnexpectedConditionException($"companyUserId {companyUserId} is not linked to keycloak");
}
if (userAliasData.Alias == null)
if (alias == null)
{
throw new NotFoundException($"identityProvider {identityProviderId} not found in company of user {companyUserId}");
}
if (!userAliasData.IsSameCompany)
if (!isSameCompany)
{
throw new ForbiddenException($"identityProvider {identityProviderId} is not associated with company {companyId}");
}
var iamUserId = await _provisioningManager.GetUserByUserName(companyUserId.ToString()).ConfigureAwait(false);
if (iamUserId == null)
{
throw new UnexpectedConditionException($"companyUserId {companyUserId} is not linked to keycloak");
}
return new ValueTuple<string, string>(
userAliasData.UserEntityId,
userAliasData.Alias);
iamUserId,
alias);
}

private sealed record UserProfile(string? FirstName, string? LastName, string? Email);
Expand Down
Loading

0 comments on commit cd874a1

Please sign in to comment.