diff --git a/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java index 26bcdf6f6f..e7661cdcd3 100755 --- a/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java @@ -33,6 +33,7 @@ public class UserRepresentation { protected String self; // link protected String id; + protected String origin; protected Long createdTimestamp; protected String username; protected Boolean enabled; @@ -240,4 +241,17 @@ public class UserRepresentation { public void setGroups(List groups) { this.groups = groups; } + + /** + * Returns id of UserStorageProvider that loaded this user + * + * @return NULL if user stored locally + */ + public String getOrigin() { + return origin; + } + + public void setOrigin(String origin) { + this.origin = origin; + } } diff --git a/server-spi/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/server-spi/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java index ef8828c352..5a18a6ecf7 100755 --- a/server-spi/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java +++ b/server-spi/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java @@ -87,6 +87,7 @@ import org.keycloak.representations.idm.authorization.ResourceOwnerRepresentatio import org.keycloak.representations.idm.authorization.ResourceRepresentation; import org.keycloak.representations.idm.authorization.ResourceServerRepresentation; import org.keycloak.representations.idm.authorization.ScopeRepresentation; +import org.keycloak.storage.StorageId; import org.keycloak.util.JsonSerialization; import java.io.IOException; @@ -178,6 +179,8 @@ public class ModelToRepresentation { public static UserRepresentation toRepresentation(KeycloakSession session, RealmModel realm, UserModel user) { UserRepresentation rep = new UserRepresentation(); rep.setId(user.getId()); + String providerId = StorageId.resolveProviderId(user); + rep.setOrigin(providerId); rep.setUsername(user.getUsername()); rep.setCreatedTimestamp(user.getCreatedTimestamp()); rep.setLastName(user.getLastName()); diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties index 313db82a31..27cb7908e7 100644 --- a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties +++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties @@ -1204,5 +1204,6 @@ userStorage.cachePolicy.evictionMinute=Eviction Minute userStorage.cachePolicy.evictionMinute.tooltip=Minute of day the entry will become invalid on. userStorage.cachePolicy.maxLifespan=Max Lifespan userStorage.cachePolicy.maxLifespan.tooltip=Max lifespan of a user cache entry in milliseconds. +user-origin-link=Storage Origin diff --git a/themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js b/themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js index 9ffe627056..1e7eb29c17 100755 --- a/themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js +++ b/themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js @@ -335,6 +335,7 @@ module.controller('UserTabCtrl', function($scope, $location, Dialog, Notificatio }); module.controller('UserDetailCtrl', function($scope, realm, user, BruteForceUser, User, + Components, UserFederationInstances, UserImpersonation, RequiredActions, $location, Dialog, Notifications) { $scope.realm = realm; @@ -362,13 +363,29 @@ module.controller('UserDetailCtrl', function($scope, realm, user, BruteForceUser }; if(user.federationLink) { console.log("federationLink is not null"); - UserFederationInstances.get({realm : realm.realm, instance: user.federationLink}, function(link) { - $scope.federationLinkName = link.displayName; - $scope.federationLink = "#/realms/" + realm.realm + "/user-federation/providers/" + link.providerName + "/" + link.id; - }) + if (user.federationLink.startsWith('f:')) { + Components.get({realm: realm.realm, componentId: user.federationLink}, function (link) { + $scope.federationLinkName = link.name; + $scope.federationLink = "#/realms/" + realm.realm + "/user-storage/providers/" + link.providerId + "/" + link.id; + }); + } else { + UserFederationInstances.get({realm: realm.realm, instance: user.federationLink}, function (link) { + $scope.federationLinkName = link.displayName; + $scope.federationLink = "#/realms/" + realm.realm + "/user-federation/providers/" + link.providerName + "/" + link.id; + }); + } + } else { console.log("federationLink is null"); } + if(user.origin) { + Components.get({realm: realm.realm, componentId: user.origin}, function (link) { + $scope.originName = link.name; + $scope.originLink = "#/realms/" + realm.realm + "/user-storage/providers/" + link.providerId + "/" + link.id; + }) + } else { + console.log("origin is null"); + } console.log('realm brute force? ' + realm.bruteForceProtected) $scope.temporarilyDisabled = false; var isDisabled = function () { diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/user-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/user-detail.html index c06e5b5559..17eb4f9fdb 100755 --- a/themes/src/main/resources/theme/base/admin/resources/partials/user-detail.html +++ b/themes/src/main/resources/theme/base/admin/resources/partials/user-detail.html @@ -82,6 +82,12 @@ {{federationLinkName}} +
+ + +