From deadcc0ee16666ffeccfd714434d4c78b416998b Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Wed, 26 Jul 2023 21:06:38 -0400 Subject: [PATCH] Fixed user update issues --- .../Users/KeycloakUserUpdatingJob.cs | 40 +++++++++++++++---- .../Identity/EShopIdentityUserAppService.cs | 5 +++ .../Keycloak/Service/IKeycloakService.cs | 3 +- .../Keycloak/Service/KeycloakService.cs | 25 +----------- .../Service/KeycloakServiceExtensions.cs | 1 + 5 files changed, 42 insertions(+), 32 deletions(-) diff --git a/services/identity/src/EShopOnAbp.IdentityService.Application/BackgroundJobs/Users/KeycloakUserUpdatingJob.cs b/services/identity/src/EShopOnAbp.IdentityService.Application/BackgroundJobs/Users/KeycloakUserUpdatingJob.cs index 5308ed5e..f3bc74a4 100644 --- a/services/identity/src/EShopOnAbp.IdentityService.Application/BackgroundJobs/Users/KeycloakUserUpdatingJob.cs +++ b/services/identity/src/EShopOnAbp.IdentityService.Application/BackgroundJobs/Users/KeycloakUserUpdatingJob.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using EShopOnAbp.IdentityService.Keycloak.Service; +using Keycloak.Net.Models.Roles; using Keycloak.Net.Models.Users; using Microsoft.Extensions.Logging; using Volo.Abp; @@ -18,7 +19,8 @@ public class KeycloakUserUpdatingJob : AsyncBackgroundJob _logger; private readonly IObjectMapper _objectMapper; - public KeycloakUserUpdatingJob(IKeycloakService keycloakService, ILogger logger, IObjectMapper objectMapper) + public KeycloakUserUpdatingJob(IKeycloakService keycloakService, ILogger logger, + IObjectMapper objectMapper) { _keycloakService = keycloakService; _logger = logger; @@ -30,11 +32,11 @@ public class KeycloakUserUpdatingJob : AsyncBackgroundJob q.UserName == args.UserName); + .FirstOrDefault(q => q.UserName == args.OldUserName); if (keycloakUser == null) { - _logger.LogError($"Keycloak user could not be found to update! Username:{args.UserName}"); - throw new UserFriendlyException($"Keycloak user with the username:{args.UserName} could not be found!"); + _logger.LogError($"Keycloak user could not be found to update! Username:{args.OldUserName}"); + throw new UserFriendlyException($"Keycloak user with the username:{args.OldUserName} could not be found!"); } IEnumerable differentFields = args.GetDifferentFields().ToList(); @@ -42,7 +44,7 @@ public class KeycloakUserUpdatingJob : AsyncBackgroundJob(keycloakUser); + var result = await _keycloakService.UpdateUserAsync( - keycloakUser.Id, + keycloakUser.Id, mappedUser - ); + ); + + // User roles are not being updated - Updating manually + if (differentFields.FirstOrDefault(q => q.FieldName == "RoleNames") != null) + { + var oldRoles = (await _keycloakService.GetRolesAsync()) + .Where(q => args.OldRoleNames.Contains(q.Name)) + .ToList(); + var newRoles = (await _keycloakService.GetRolesAsync()) + .Where(q => args.RoleNames.Contains(q.Name)) + .ToList(); + if (oldRoles.Count > 0) + { + await _keycloakService.RemoveRealmRolesFromUserAsync(keycloakUser.Id, + _objectMapper.Map, List>(oldRoles)); + } + + if (newRoles.Count > 0) + { + await _keycloakService.AddRealmRolesToUserAsync(keycloakUser.Id, + _objectMapper.Map, List>(newRoles)); + } + } + if (result) { _logger.LogInformation($"Keycloak user with the username:{args.UserName} has been updated."); diff --git a/services/identity/src/EShopOnAbp.IdentityService.Application/Identity/EShopIdentityUserAppService.cs b/services/identity/src/EShopOnAbp.IdentityService.Application/Identity/EShopIdentityUserAppService.cs index 2f10bfe7..f56f7d4a 100644 --- a/services/identity/src/EShopOnAbp.IdentityService.Application/Identity/EShopIdentityUserAppService.cs +++ b/services/identity/src/EShopOnAbp.IdentityService.Application/Identity/EShopIdentityUserAppService.cs @@ -43,6 +43,11 @@ public class EShopIdentityUserAppService : IdentityUserAppService public override async Task UpdateAsync(Guid id, IdentityUserUpdateDto input) { var existingUser = await _userRepository.GetAsync(id); + // Disabling username updating. Keycloak service is unavailable to update the username field! + if (input.UserName != existingUser.UserName) + { + input.UserName = existingUser.UserName; + } var args = await CreateIdentityUserUpdatingArgsAsync(existingUser, input); var updatedUser = await base.UpdateAsync(id, input); await _backgroundJobManager.EnqueueAsync(args); diff --git a/services/identity/src/EShopOnAbp.IdentityService.Application/Keycloak/Service/IKeycloakService.cs b/services/identity/src/EShopOnAbp.IdentityService.Application/Keycloak/Service/IKeycloakService.cs index 12bf5b7e..aa09d8d3 100644 --- a/services/identity/src/EShopOnAbp.IdentityService.Application/Keycloak/Service/IKeycloakService.cs +++ b/services/identity/src/EShopOnAbp.IdentityService.Application/Keycloak/Service/IKeycloakService.cs @@ -25,9 +25,8 @@ public interface IKeycloakService : ITransientDependency Task> GetRolesAsync(CancellationToken cancellationToken = default); Task AddRealmRolesToUserAsync(string userId, IEnumerable roles, CancellationToken cancellationToken = default); - public Task> GetRealmRolesOfUserAsync(string userId, CancellationToken cancellationToken = default); - Task RemoveRealmRolesFromUserAsync(string userId, IEnumerable roles, CancellationToken cancellationToken = default); + Task RemoveRealmRolesFromUserAsync(string userId, IEnumerable roles, CancellationToken cancellationToken = default); Task CreateRoleAsync(string name, CancellationToken cancellationToken = default); diff --git a/services/identity/src/EShopOnAbp.IdentityService.Application/Keycloak/Service/KeycloakService.cs b/services/identity/src/EShopOnAbp.IdentityService.Application/Keycloak/Service/KeycloakService.cs index 23ed6caa..73f2b41b 100644 --- a/services/identity/src/EShopOnAbp.IdentityService.Application/Keycloak/Service/KeycloakService.cs +++ b/services/identity/src/EShopOnAbp.IdentityService.Application/Keycloak/Service/KeycloakService.cs @@ -23,7 +23,6 @@ public class KeycloakService : IKeycloakService private readonly IObjectMapper _objectMapper; private readonly IDistributedCache, string> _keycloakUsersCache; private readonly IDistributedCache, string> _keycloakRolesCache; - private readonly IDistributedCache, string> _userRolesCache; private readonly KeycloakClient _keycloakClient; private readonly KeycloakClientOptions _keycloakOptions; @@ -32,13 +31,11 @@ public class KeycloakService : IKeycloakService IOptions keycloakOptions, IObjectMapper objectMapper, IDistributedCache, string> keycloakUsersCache, - IDistributedCache, string> keycloakRolesCache, - IDistributedCache, string> userRolesCache) + IDistributedCache, string> keycloakRolesCache) { _objectMapper = objectMapper; _keycloakUsersCache = keycloakUsersCache; _keycloakRolesCache = keycloakRolesCache; - _userRolesCache = userRolesCache; _keycloakOptions = keycloakOptions.Value; _keycloakClient = new KeycloakClient( @@ -84,7 +81,6 @@ public class KeycloakService : IKeycloakService await _keycloakUsersCache.RemoveAsync(UsersCacheKey, token: cancellationToken); } -// _keycloakClient.DeleteRealmRoleMappingsFromUserAsync() return result; } @@ -122,24 +118,7 @@ public class KeycloakService : IKeycloakService cancellationToken); } - // Updating user with roles is not working - public async Task> GetRealmRolesOfUserAsync(string userId, - CancellationToken cancellationToken = default) - { - var userRoles = await _userRolesCache.GetAsync(userId, token: cancellationToken); - if (userRoles == null) - { - var roles = (await _keycloakClient.GetRealmRoleMappingsForUserAsync(_keycloakOptions.RealmName, userId, - cancellationToken)) - .ToList(); - userRoles = _objectMapper.Map, List>(roles); - await _userRolesCache.SetAsync(userId, userRoles, token: cancellationToken); - } - - return userRoles; - } - - public Task RemoveRealmRolesFromUserAsync(string userId, IEnumerable roles, + public Task RemoveRealmRolesFromUserAsync(string userId, IEnumerable roles, CancellationToken cancellationToken = default) { return _keycloakClient.DeleteRealmRoleMappingsFromUserAsync(_keycloakOptions.RealmName, userId, roles, diff --git a/services/identity/src/EShopOnAbp.IdentityService.Application/Keycloak/Service/KeycloakServiceExtensions.cs b/services/identity/src/EShopOnAbp.IdentityService.Application/Keycloak/Service/KeycloakServiceExtensions.cs index 01474c1b..21840fbe 100644 --- a/services/identity/src/EShopOnAbp.IdentityService.Application/Keycloak/Service/KeycloakServiceExtensions.cs +++ b/services/identity/src/EShopOnAbp.IdentityService.Application/Keycloak/Service/KeycloakServiceExtensions.cs @@ -8,6 +8,7 @@ using Keycloak.Net.Models.Users; namespace EShopOnAbp.IdentityService.Keycloak.Service; +/* Extensions to create unique strings based on list values */ public static class KeycloakServiceExtensions { public static string GenerateCacheKeyBasedOnValues(this IEnumerable roles)