Users in role Rest API returns empty when User federation used (#23318)
* Users in role Rest API returns empty when User federation used Co-authored-by: Shankar Yadav <ET1024@neeyamoworks.com> Co-authored-by: Martin Kanis <mkanis@redhat.com> Co-authored-by: Michal Hajas <mhajas@redhat.com>
This commit is contained in:
parent
9627187447
commit
10a2c96c72
5 changed files with 61 additions and 1 deletions
|
@ -474,6 +474,15 @@ public class JpaUserFederatedStorageProvider implements
|
||||||
|
|
||||||
return closing(paginateQuery(query, firstResult, max).getResultStream());
|
return closing(paginateQuery(query, firstResult, max).getResultStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<String> getRoleMembersStream(RealmModel realm, RoleModel role, Integer firstResult, Integer max) {
|
||||||
|
TypedQuery<String> query = em.createNamedQuery("fedRoleMembership", String.class);
|
||||||
|
query.setParameter("roleId", role.getId());
|
||||||
|
query.setParameter("realmId", realm.getId());
|
||||||
|
|
||||||
|
return closing(paginateQuery(query, firstResult, max).getResultStream());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Stream<String> getRequiredActionsStream(RealmModel realm, String userId) {
|
public Stream<String> getRequiredActionsStream(RealmModel realm, String userId) {
|
||||||
|
|
|
@ -40,7 +40,7 @@ import java.io.Serializable;
|
||||||
@NamedQuery(name="deleteFederatedUserRoleMappingsByRealmAndLink", query="delete from FederatedUserRoleMappingEntity mapping where mapping.userId IN (select u.id from UserEntity u where u.realmId=:realmId and u.federationLink=:link)"),
|
@NamedQuery(name="deleteFederatedUserRoleMappingsByRealmAndLink", query="delete from FederatedUserRoleMappingEntity mapping where mapping.userId IN (select u.id from UserEntity u where u.realmId=:realmId and u.federationLink=:link)"),
|
||||||
@NamedQuery(name="deleteFederatedUserRoleMappingsByRole", query="delete from FederatedUserRoleMappingEntity m where m.roleId = :roleId"),
|
@NamedQuery(name="deleteFederatedUserRoleMappingsByRole", query="delete from FederatedUserRoleMappingEntity m where m.roleId = :roleId"),
|
||||||
@NamedQuery(name="deleteFederatedUserRoleMappingsByUser", query="delete from FederatedUserRoleMappingEntity m where m.userId = :userId and m.realmId = :realmId"),
|
@NamedQuery(name="deleteFederatedUserRoleMappingsByUser", query="delete from FederatedUserRoleMappingEntity m where m.userId = :userId and m.realmId = :realmId"),
|
||||||
|
@NamedQuery(name="fedRoleMembership", query="select m.userId FROM FederatedUserRoleMappingEntity m where m.roleId = :roleId AND m.realmId = :realmId"),
|
||||||
})
|
})
|
||||||
@Table(name="FED_USER_ROLE_MAPPING")
|
@Table(name="FED_USER_ROLE_MAPPING")
|
||||||
@Entity
|
@Entity
|
||||||
|
|
|
@ -423,6 +423,10 @@ public class UserStorageManager extends AbstractStorageManager<UserStorageProvid
|
||||||
if (provider instanceof UserQueryMethodsProvider) {
|
if (provider instanceof UserQueryMethodsProvider) {
|
||||||
return ((UserQueryMethodsProvider)provider).getRoleMembersStream(realm, role, firstResultInQuery, maxResultsInQuery);
|
return ((UserQueryMethodsProvider)provider).getRoleMembersStream(realm, role, firstResultInQuery, maxResultsInQuery);
|
||||||
}
|
}
|
||||||
|
else if (provider instanceof UserFederatedStorageProvider) {
|
||||||
|
return ((UserFederatedStorageProvider)provider).getRoleMembersStream(realm, role, firstResultInQuery, maxResultsInQuery).
|
||||||
|
map(id -> getUserById(realm, id));
|
||||||
|
}
|
||||||
return Stream.empty();
|
return Stream.empty();
|
||||||
}, realm, firstResult, maxResults);
|
}, realm, firstResult, maxResults);
|
||||||
return importValidation(realm, results);
|
return importValidation(realm, results);
|
||||||
|
|
|
@ -40,6 +40,17 @@ public interface UserRoleMappingsFederatedStorage {
|
||||||
|
|
||||||
void deleteRoleMapping(RealmModel realm, String userId, RoleModel role);
|
void deleteRoleMapping(RealmModel realm, String userId, RoleModel role);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the federated users that are members of the given {@code role} in the specified {@code realm}.
|
||||||
|
*
|
||||||
|
* @param realm a reference to the realm.
|
||||||
|
* @param role a reference to the role whose federated members are being searched.
|
||||||
|
* @param firstResult first result to return. Ignored if negative or {@code null}.
|
||||||
|
* @param max maximum number of results to return. Ignored if negative or {@code null}.
|
||||||
|
* @return a non-null {@code Stream} of federated user ids that are members of the role in the realm.
|
||||||
|
*/
|
||||||
|
Stream<String> getRoleMembersStream(RealmModel realm, RoleModel role, Integer firstResult, Integer max);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated This interface is no longer necessary; collection-based methods were removed from the parent interface
|
* @deprecated This interface is no longer necessary; collection-based methods were removed from the parent interface
|
||||||
* and therefore the parent interface can be used directly
|
* and therefore the parent interface can be used directly
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.keycloak.testsuite.federation.storage;
|
package org.keycloak.testsuite.federation.storage;
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.hamcrest.Matchers;
|
||||||
import org.jboss.arquillian.graphene.page.Page;
|
import org.jboss.arquillian.graphene.page.Page;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
@ -20,6 +21,7 @@ import org.keycloak.credential.CredentialProvider;
|
||||||
import org.keycloak.credential.CredentialProviderFactory;
|
import org.keycloak.credential.CredentialProviderFactory;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.cache.CachedUserModel;
|
import org.keycloak.models.cache.CachedUserModel;
|
||||||
import org.keycloak.models.credential.OTPCredentialModel;
|
import org.keycloak.models.credential.OTPCredentialModel;
|
||||||
|
@ -867,6 +869,40 @@ public class UserStorageTest extends AbstractAuthTest {
|
||||||
adminClient.realms().create(repOrig);
|
adminClient.realms().create(repOrig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRoleMembership() {
|
||||||
|
RoleRepresentation role1 = new RoleRepresentation();
|
||||||
|
role1.setName("role1");
|
||||||
|
RoleRepresentation role2 = new RoleRepresentation();
|
||||||
|
role2.setName("role2");
|
||||||
|
testRealmResource().roles().create(role1);
|
||||||
|
testRealmResource().roles().create(role2);
|
||||||
|
|
||||||
|
UserRepresentation thor = ApiUtil.findUserByUsername(testRealmResource(), "thor");
|
||||||
|
ApiUtil.assignRealmRoles(testRealmResource(), thor.getId(), "role1", "role2");
|
||||||
|
|
||||||
|
UserRepresentation zeus = ApiUtil.findUserByUsername(testRealmResource(), "zeus");
|
||||||
|
ApiUtil.assignRealmRoles(testRealmResource(), zeus.getId(), "role1");
|
||||||
|
|
||||||
|
|
||||||
|
testingClient.server().run(session -> {
|
||||||
|
RealmModel realm = session.realms().getRealmByName("test");
|
||||||
|
RoleModel roleModel1 = session.roles().getRealmRole(realm, "role1");
|
||||||
|
RoleModel roleModel2 = session.roles().getRealmRole(realm, "role2");
|
||||||
|
|
||||||
|
List<String> users = session.users().getRoleMembersStream(realm, roleModel1).map(UserModel::getUsername).collect(Collectors.toList());
|
||||||
|
Assert.assertEquals(2, users.size());
|
||||||
|
Assert.assertThat(users, Matchers.containsInAnyOrder("thor", "zeus"));
|
||||||
|
|
||||||
|
users = session.users().getRoleMembersStream(realm, roleModel2).map(UserModel::getUsername).collect(Collectors.toList());
|
||||||
|
Assert.assertEquals(1, users.size());
|
||||||
|
Assert.assertThat(users, Matchers.containsInAnyOrder("thor"));
|
||||||
|
});
|
||||||
|
|
||||||
|
testRealmResource().roles().get("role1").remove();
|
||||||
|
testRealmResource().roles().get("role2").remove();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore
|
@Ignore
|
||||||
public void testEntityRemovalHooksCascade() {
|
public void testEntityRemovalHooksCascade() {
|
||||||
|
|
Loading…
Reference in a new issue