Browse Source

Fixed user update issues

pull/180/head
Galip Tolga Erdem 3 years ago
parent
commit
deadcc0ee1
  1. 40
      services/identity/src/EShopOnAbp.IdentityService.Application/BackgroundJobs/Users/KeycloakUserUpdatingJob.cs
  2. 5
      services/identity/src/EShopOnAbp.IdentityService.Application/Identity/EShopIdentityUserAppService.cs
  3. 3
      services/identity/src/EShopOnAbp.IdentityService.Application/Keycloak/Service/IKeycloakService.cs
  4. 25
      services/identity/src/EShopOnAbp.IdentityService.Application/Keycloak/Service/KeycloakService.cs
  5. 1
      services/identity/src/EShopOnAbp.IdentityService.Application/Keycloak/Service/KeycloakServiceExtensions.cs

40
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<IdentityUserUpdatingAr
private readonly ILogger<KeycloakUserCreationJob> _logger;
private readonly IObjectMapper _objectMapper;
public KeycloakUserUpdatingJob(IKeycloakService keycloakService, ILogger<KeycloakUserCreationJob> logger, IObjectMapper objectMapper)
public KeycloakUserUpdatingJob(IKeycloakService keycloakService, ILogger<KeycloakUserCreationJob> logger,
IObjectMapper objectMapper)
{
_keycloakService = keycloakService;
_logger = logger;
@ -30,11 +32,11 @@ public class KeycloakUserUpdatingJob : AsyncBackgroundJob<IdentityUserUpdatingAr
try
{
var keycloakUser = (await _keycloakService.GetUsersAsync())
.FirstOrDefault(q => 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<IdentityUserUpdatingArgs.FieldChange> differentFields = args.GetDifferentFields().ToList();
@ -42,7 +44,7 @@ public class KeycloakUserUpdatingJob : AsyncBackgroundJob<IdentityUserUpdatingAr
{
if (fieldChange.FieldName == "Email")
keycloakUser.Email = fieldChange.NewValue.ToString();
if (fieldChange.FieldName == "UserName")
if (fieldChange.FieldName == "UserName") // Username update is not working - not updating in keycloak
keycloakUser.UserName = fieldChange.NewValue.ToString();
if (fieldChange.FieldName == "Name")
keycloakUser.FirstName = fieldChange.NewValue.ToString();
@ -57,10 +59,34 @@ public class KeycloakUserUpdatingJob : AsyncBackgroundJob<IdentityUserUpdatingAr
if (differentFields.Count() != 0)
{
var mappedUser = _objectMapper.Map<CachedKeycloakUser, User>(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<CachedKeycloakRole>, List<Role>>(oldRoles));
}
if (newRoles.Count > 0)
{
await _keycloakService.AddRealmRolesToUserAsync(keycloakUser.Id,
_objectMapper.Map<List<CachedKeycloakRole>, List<Role>>(newRoles));
}
}
if (result)
{
_logger.LogInformation($"Keycloak user with the username:{args.UserName} has been updated.");

5
services/identity/src/EShopOnAbp.IdentityService.Application/Identity/EShopIdentityUserAppService.cs

@ -43,6 +43,11 @@ public class EShopIdentityUserAppService : IdentityUserAppService
public override async Task<IdentityUserDto> 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);

3
services/identity/src/EShopOnAbp.IdentityService.Application/Keycloak/Service/IKeycloakService.cs

@ -25,9 +25,8 @@ public interface IKeycloakService : ITransientDependency
Task<List<CachedKeycloakRole>> GetRolesAsync(CancellationToken cancellationToken = default);
Task<bool> AddRealmRolesToUserAsync(string userId, IEnumerable<Role> roles, CancellationToken cancellationToken = default);
public Task<IEnumerable<CachedKeycloakRole>> GetRealmRolesOfUserAsync(string userId, CancellationToken cancellationToken = default);
Task RemoveRealmRolesFromUserAsync(string userId, IEnumerable<Role> roles, CancellationToken cancellationToken = default);
Task<bool> RemoveRealmRolesFromUserAsync(string userId, IEnumerable<Role> roles, CancellationToken cancellationToken = default);
Task<bool> CreateRoleAsync(string name, CancellationToken cancellationToken = default);

25
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<List<CachedKeycloakUser>, string> _keycloakUsersCache;
private readonly IDistributedCache<List<CachedKeycloakRole>, string> _keycloakRolesCache;
private readonly IDistributedCache<List<CachedKeycloakRole>, string> _userRolesCache;
private readonly KeycloakClient _keycloakClient;
private readonly KeycloakClientOptions _keycloakOptions;
@ -32,13 +31,11 @@ public class KeycloakService : IKeycloakService
IOptions<KeycloakClientOptions> keycloakOptions,
IObjectMapper objectMapper,
IDistributedCache<List<CachedKeycloakUser>, string> keycloakUsersCache,
IDistributedCache<List<CachedKeycloakRole>, string> keycloakRolesCache,
IDistributedCache<List<CachedKeycloakRole>, string> userRolesCache)
IDistributedCache<List<CachedKeycloakRole>, 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<IEnumerable<CachedKeycloakRole>> 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<Role>, List<CachedKeycloakRole>>(roles);
await _userRolesCache.SetAsync(userId, userRoles, token: cancellationToken);
}
return userRoles;
}
public Task RemoveRealmRolesFromUserAsync(string userId, IEnumerable<Role> roles,
public Task<bool> RemoveRealmRolesFromUserAsync(string userId, IEnumerable<Role> roles,
CancellationToken cancellationToken = default)
{
return _keycloakClient.DeleteRealmRoleMappingsFromUserAsync(_keycloakOptions.RealmName, userId, roles,

1
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<Role> roles)

Loading…
Cancel
Save