Skip to content

Commit

Permalink
feat(user): save userid of ipd
Browse files Browse the repository at this point in the history
* save the userid for each idp for a specific the user
* add displayName to iamIdentityProvider
* return userid of an idp with the idps display name

Refs: CPLP-3401
  • Loading branch information
Phil91 committed Jan 23, 2024
1 parent 805a422 commit b7e2968
Show file tree
Hide file tree
Showing 33 changed files with 9,905 additions and 158 deletions.
30 changes: 30 additions & 0 deletions src/Portal.Backend.sln
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Keycloak.Authentication.Tes
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Framework.ProcessIdentity.Tests", "..\tests\framework\Framework.ProcessIdentity.Tests\Framework.ProcessIdentity.Tests.csproj", "{996CAB8C-B43A-4E76-B906-034A395C1429}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Synchronization.Executor.Tests", "..\tests\processes\Synchronization.Executor.Tests\Synchronization.Executor.Tests.csproj", "{B24DE478-F7F0-4BF5-8C45-F0B0B58CFCFB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Synchronization.Executor", "processes\Synchronization.Executor\Synchronization.Executor.csproj", "{4AD6F876-2524-4179-BDFB-22166634369C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -1508,6 +1512,30 @@ Global
{996CAB8C-B43A-4E76-B906-034A395C1429}.Release|x64.Build.0 = Release|Any CPU
{996CAB8C-B43A-4E76-B906-034A395C1429}.Release|x86.ActiveCfg = Release|Any CPU
{996CAB8C-B43A-4E76-B906-034A395C1429}.Release|x86.Build.0 = Release|Any CPU
{B24DE478-F7F0-4BF5-8C45-F0B0B58CFCFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B24DE478-F7F0-4BF5-8C45-F0B0B58CFCFB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B24DE478-F7F0-4BF5-8C45-F0B0B58CFCFB}.Debug|x64.ActiveCfg = Debug|Any CPU
{B24DE478-F7F0-4BF5-8C45-F0B0B58CFCFB}.Debug|x64.Build.0 = Debug|Any CPU
{B24DE478-F7F0-4BF5-8C45-F0B0B58CFCFB}.Debug|x86.ActiveCfg = Debug|Any CPU
{B24DE478-F7F0-4BF5-8C45-F0B0B58CFCFB}.Debug|x86.Build.0 = Debug|Any CPU
{B24DE478-F7F0-4BF5-8C45-F0B0B58CFCFB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B24DE478-F7F0-4BF5-8C45-F0B0B58CFCFB}.Release|Any CPU.Build.0 = Release|Any CPU
{B24DE478-F7F0-4BF5-8C45-F0B0B58CFCFB}.Release|x64.ActiveCfg = Release|Any CPU
{B24DE478-F7F0-4BF5-8C45-F0B0B58CFCFB}.Release|x64.Build.0 = Release|Any CPU
{B24DE478-F7F0-4BF5-8C45-F0B0B58CFCFB}.Release|x86.ActiveCfg = Release|Any CPU
{B24DE478-F7F0-4BF5-8C45-F0B0B58CFCFB}.Release|x86.Build.0 = Release|Any CPU
{4AD6F876-2524-4179-BDFB-22166634369C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4AD6F876-2524-4179-BDFB-22166634369C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4AD6F876-2524-4179-BDFB-22166634369C}.Debug|x64.ActiveCfg = Debug|Any CPU
{4AD6F876-2524-4179-BDFB-22166634369C}.Debug|x64.Build.0 = Debug|Any CPU
{4AD6F876-2524-4179-BDFB-22166634369C}.Debug|x86.ActiveCfg = Debug|Any CPU
{4AD6F876-2524-4179-BDFB-22166634369C}.Debug|x86.Build.0 = Debug|Any CPU
{4AD6F876-2524-4179-BDFB-22166634369C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4AD6F876-2524-4179-BDFB-22166634369C}.Release|Any CPU.Build.0 = Release|Any CPU
{4AD6F876-2524-4179-BDFB-22166634369C}.Release|x64.ActiveCfg = Release|Any CPU
{4AD6F876-2524-4179-BDFB-22166634369C}.Release|x64.Build.0 = Release|Any CPU
{4AD6F876-2524-4179-BDFB-22166634369C}.Release|x86.ActiveCfg = Release|Any CPU
{4AD6F876-2524-4179-BDFB-22166634369C}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -1621,5 +1649,7 @@ Global
{F1A5A73C-2B8C-4959-A128-CC5A8DECCB1B} = {323C198D-A8C6-4EB0-8B79-72624275E35F}
{09EF5799-B375-49F1-B78F-0A94D8109F8B} = {AB9C5AA2-DD5D-4A38-97C0-674A995C0AE0}
{C7ACF748-DEF4-4646-A791-F1DA437CC965} = {323C198D-A8C6-4EB0-8B79-72624275E35F}
{B24DE478-F7F0-4BF5-8C45-F0B0B58CFCFB} = {323C198D-A8C6-4EB0-8B79-72624275E35F}
{4AD6F876-2524-4179-BDFB-22166634369C} = {282CEF03-292F-4A49-83C6-997567D0FF5F}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public interface IUserBusinessLogic
Task<Pagination.Response<CompanyUserData>> GetOwnCompanyUserDatasAsync(int page, int size, GetOwnCompanyUsersFilter filter);
[Obsolete("to be replaced by UserRolesBusinessLogic.GetAppRolesAsync. Remove as soon frontend is adjusted")]
IAsyncEnumerable<ClientRoles> GetClientRolesAsync(Guid appId, string? languageShortName = null);
Task<CompanyUserDetails> GetOwnCompanyUserDetailsAsync(Guid userId);
Task<CompanyUserDetailData> GetOwnCompanyUserDetailsAsync(Guid userId);
Task<int> AddOwnCompanyUsersBusinessPartnerNumbersAsync(Guid userId, IEnumerable<string> businessPartnerNumbers);
Task<int> AddOwnCompanyUsersBusinessPartnerNumberAsync(Guid userId, string businessPartnerNumber);
Task<CompanyOwnUserDetails> GetOwnUserDetails();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ private async ValueTask<IdentityProviderDetails> CreateOwnCompanyIdentityProvide
{
identityProviderRepository.CreateCompanyIdentityProvider(companyId, identityProviderId);
}
identityProviderRepository.CreateIamIdentityProvider(identityProviderId, alias);
identityProviderRepository.CreateIamIdentityProvider(identityProviderId, alias, displayName ?? result.CompanyName);
await _portalRepositories.SaveAsync().ConfigureAwait(false);

return protocol switch
Expand Down Expand Up @@ -362,7 +362,7 @@ public async ValueTask DeleteCompanyIdentityProviderAsync(Guid identityProviderI

if (alias != null)
{
identityProviderRepository.DeleteIamIdentityProvider(alias);
_portalRepositories.Remove(new IamIdentityProvider(alias, null!, Guid.Empty));
if (typeId == IdentityProviderTypeId.SHARED)
{
await _provisioningManager.DeleteSharedIdpRealmAsync(alias).ConfigureAwait(false);
Expand All @@ -380,7 +380,10 @@ public async ValueTask DeleteCompanyIdentityProviderAsync(Guid identityProviderI
}

identityProviderRepository.DeleteIdentityProvider(identityProviderId);

if (alias != null)
{
identityProviderRepository.DeleteIamIdentityProvider(alias);
}
await _portalRepositories.SaveAsync().ConfigureAwait(false);
}

Expand Down Expand Up @@ -743,7 +746,7 @@ private async ValueTask<IdentityProviderUpdateStats> UploadOwnCompanyUsersIdenti
{
var userRepository = _portalRepositories.GetInstance<IUserRepository>();
var companyId = _identityData.CompanyId;
var (sharedIdpAlias, existingAliase) = await GetCompanyAliasDataAsync(companyId).ConfigureAwait(false);
var (sharedIdp, existingAliase) = await GetCompanyAliasDataAsync(companyId).ConfigureAwait(false);

using var stream = document.OpenReadStream();

Expand All @@ -755,8 +758,8 @@ private async ValueTask<IdentityProviderUpdateStats> UploadOwnCompanyUsersIdenti
{
numIdps = ParseCSVFirstLineReturningNumIdps(line);
},
line => ParseCSVLine(line, numIdps, existingAliase),
lines => ProcessOwnCompanyUsersIdentityProviderLinkDataInternalAsync(lines, userRepository, companyId, sharedIdpAlias, cancellationToken),
line => ParseCSVLine(line, numIdps, existingAliase.Select(x => x.Alias)),
lines => ProcessOwnCompanyUsersIdentityProviderLinkDataInternalAsync(lines, userRepository, companyId, sharedIdp, existingAliase, cancellationToken),
cancellationToken
).ConfigureAwait(false);

Expand All @@ -782,7 +785,8 @@ private UserUpdateError CreateUserUpdateError(int line, Exception error) =>
IAsyncEnumerable<(Guid CompanyUserId, UserProfile UserProfile, IEnumerable<IdentityProviderLink> IdentityProviderLinks)> userProfileLinkDatas,
IUserRepository userRepository,
Guid companyId,
string? sharedIdpAlias,
(Guid IdentityProviderId, string Alias) sharedIdp,
IEnumerable<(Guid IdentityProviderId, string Alias)> existingIdps,
[EnumeratorCancellation] CancellationToken cancellationToken)
{
await foreach (var (companyUserId, profile, identityProviderLinks) in userProfileLinkDatas)
Expand All @@ -799,12 +803,12 @@ private UserUpdateError CreateUserUpdateError(int line, Exception error) =>

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

if (existingProfile != profile)
{
await UpdateUserProfileAsync(userRepository, iamUserId, companyUserId, profile, existingLinks, sharedIdpAlias).ConfigureAwait(false);
await UpdateUserProfileAsync(userRepository, iamUserId, companyUserId, profile, existingLinks, sharedIdp).ConfigureAwait(false);
updated = true;
}
success = updated;
Expand All @@ -821,15 +825,15 @@ private UserUpdateError CreateUserUpdateError(int line, Exception error) =>
}
}

private async ValueTask<(string? SharedIdpAlias, IEnumerable<string> ValidAliase)> GetCompanyAliasDataAsync(Guid companyId)
private async ValueTask<((Guid IdentityProviderId, string Alias) SharedIdp, IEnumerable<(Guid IdentityProviderId, string Alias)> ValidAliase)> GetCompanyAliasDataAsync(Guid companyId)
{
var identityProviderCategoryData = await _portalRepositories.GetInstance<IIdentityProviderRepository>()
.GetCompanyIdentityProviderCategoryDataUntracked(companyId)
.Where(data => data.Alias != null)
.Select(data => (data.TypeId, Alias: data.Alias!))
.Select(data => (data.IdentityProviderId, data.TypeId, Alias: data.Alias!))
.ToListAsync().ConfigureAwait(false);
var sharedIdpAlias = identityProviderCategoryData.SingleOrDefault(data => data.TypeId == IdentityProviderTypeId.SHARED).Alias;
var validAliase = identityProviderCategoryData.Select(data => data.Alias).ToList();
var sharedIdpAlias = identityProviderCategoryData.Where(data => data.TypeId == IdentityProviderTypeId.SHARED).Select(data => (data.IdentityProviderId, data.Alias)).SingleOrDefault();
var validAliase = identityProviderCategoryData.Select(data => (data.IdentityProviderId, data.Alias)).ToList();
return (sharedIdpAlias, validAliase);
}

Expand All @@ -851,7 +855,13 @@ private UserUpdateError CreateUserUpdateError(int line, Exception error) =>
);
}

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

Expand All @@ -863,7 +873,7 @@ private async ValueTask<bool> UpdateIdentityProviderLinksAsync(string iamUserId,
return false;
}

if (alias == sharedIdpAlias)
if (alias == sharedIdp.Alias)
{
throw new ControllerArgumentException($"unexpected update of shared identityProviderLink, alias '{alias}', companyUser '{companyUserId}', providerUserId: '{userId}', providerUserName: '{userName}'");
}
Expand All @@ -873,23 +883,49 @@ private async ValueTask<bool> UpdateIdentityProviderLinksAsync(string iamUserId,
await _provisioningManager.DeleteProviderUserLinkToCentralUserAsync(iamUserId, alias).ConfigureAwait(false);
}
await _provisioningManager.AddProviderUserLinkToCentralUserAsync(iamUserId, identityProviderLink).ConfigureAwait(false);
await InsertUpdateCompanyUserAssignedIdentityProvider(companyUserId, existingIdps.Single(x => x.Alias == alias).IdentityProviderId, identityProviderLink).ConfigureAwait(false);
return true;
}

private async ValueTask UpdateUserProfileAsync(IUserRepository userRepository, string iamUserId, Guid companyUserId, UserProfile profile, IEnumerable<IdentityProviderLink> existingLinks, string? sharedIdpAlias)
private async Task InsertUpdateCompanyUserAssignedIdentityProvider(Guid companyUserId, Guid identityProviderId, IdentityProviderLink providerLink)
{
var userRepository = _portalRepositories.GetInstance<IUserRepository>();
var data = await userRepository.GetCompanyUserAssignedIdentityProvider(companyUserId, identityProviderId).ConfigureAwait(false);
if (data == default)
{
userRepository.AddCompanyUserAssignedIdentityProvider(companyUserId, identityProviderId, providerLink.UserId, providerLink.UserName);
}
else
{
userRepository.AttachAndModifyUserAssignedIdentityProvider(companyUserId, identityProviderId,
uaip =>
{
uaip.ProviderId = data.ProviderId;
uaip.UserName = data.Username;
},
uaip =>
{
uaip.ProviderId = providerLink.UserId;
uaip.UserName = providerLink.UserName;
});
}
}

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

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

if (sharedIdpAlias != null)
if (sharedIdp != default)
{
var sharedIdpLink = existingLinks.FirstOrDefault(link => link.Alias == sharedIdpAlias);
var sharedIdpLink = existingLinks.FirstOrDefault(link => link.Alias == sharedIdp.Alias);
if (sharedIdpLink != default)
{
await _provisioningManager.UpdateSharedRealmUserAsync(sharedIdpAlias, sharedIdpLink.UserId, firstName, lastName, email).ConfigureAwait(false);
await _provisioningManager.UpdateSharedRealmUserAsync(sharedIdp.Alias, sharedIdpLink.UserId, firstName, lastName, email).ConfigureAwait(false);
}
}

userRepository.AttachAndModifyCompanyUser(companyUserId, null, companyUser =>
{
companyUser.Firstname = profile.FirstName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ private async Task ExecuteInvitationInternalAsync(CompanyInvitationData invitati
var identityProviderRepository = _portalRepositories.GetInstance<IIdentityProviderRepository>();
var identityProvider = identityProviderRepository.CreateIdentityProvider(IdentityProviderCategoryId.KEYCLOAK_OIDC, IdentityProviderTypeId.SHARED, company.Id, null);
identityProvider.Companies.Add(company);
identityProviderRepository.CreateIamIdentityProvider(identityProvider.Id, idpName);
identityProviderRepository.CreateIamIdentityProvider(identityProvider.Id, idpName, invitationData.organisationName);

var applicationRepository = _portalRepositories.GetInstance<IApplicationRepository>();
var application = applicationRepository.CreateCompanyApplication(company.Id, CompanyApplicationStatusId.CREATED, CompanyApplicationTypeId.INTERNAL);
Expand Down
Loading

0 comments on commit b7e2968

Please sign in to comment.