Merge pull request #3785 from mposolda/master

KEYCLOAK-4274 Fix recursive composite role mappings
This commit is contained in:
Marek Posolda 2017-01-23 19:01:25 +01:00 committed by GitHub
commit 8717cd0090
5 changed files with 38 additions and 11 deletions

View file

@ -176,7 +176,7 @@ public class RoleAdapter implements RoleModel {
@Override
public boolean hasRole(RoleModel role) {
return this.equals(role) || KeycloakModelUtils.searchFor(role, this);
return this.equals(role) || KeycloakModelUtils.searchFor(role, this, new HashSet<>());
}
@Override

View file

@ -128,7 +128,7 @@ public class RoleAdapter implements RoleModel, JpaModel<RoleEntity> {
@Override
public boolean hasRole(RoleModel role) {
return this.equals(role) || KeycloakModelUtils.searchFor(role, this);
return this.equals(role) || KeycloakModelUtils.searchFor(role, this, new HashSet<>());
}
@Override

View file

@ -172,7 +172,7 @@ public class RoleAdapter extends AbstractMongoAdapter<MongoRoleEntity> implement
@Override
public boolean hasRole(RoleModel role) {
return this.equals(role) || KeycloakModelUtils.searchFor(role, this);
return this.equals(role) || KeycloakModelUtils.searchFor(role, this, new HashSet<>());
}
public MongoRoleEntity getRole() {

View file

@ -177,14 +177,23 @@ public final class KeycloakModelUtils {
* @param visited set of already visited roles (used for recursion)
* @return true if "role" is descendant of "composite"
*/
public static boolean searchFor(RoleModel role, RoleModel composite) {
return composite.isComposite() && (
composite.getComposites().contains(role) ||
composite.getComposites().stream()
.filter(x -> x.isComposite() && x.hasRole(role))
public static boolean searchFor(RoleModel role, RoleModel composite, Set<String> visited) {
if (visited.contains(composite.getId())) {
return false;
}
visited.add(composite.getId());
if (!composite.isComposite()) {
return false;
}
Set<RoleModel> compositeRoles = composite.getComposites();
return compositeRoles.contains(role) ||
compositeRoles.stream()
.filter(x -> x.isComposite() && searchFor(role, x, visited))
.findFirst()
.isPresent()
);
.isPresent();
}
/**

View file

@ -17,7 +17,6 @@
package org.keycloak.testsuite.composites;
import org.jboss.arquillian.graphene.page.Page;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.keycloak.OAuth2Constants;
@ -28,6 +27,7 @@ import org.keycloak.common.enums.SslRequired;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.testsuite.Assert;
import org.keycloak.testsuite.admin.ApiUtil;
import org.keycloak.testsuite.pages.LoginPage;
import org.keycloak.testsuite.util.ClientBuilder;
@ -345,4 +345,22 @@ public class CompositeRoleTest extends AbstractCompositeKeycloakTest {
Assert.assertEquals(200, refreshResponse.getStatusCode());
}
// KEYCLOAK-4274
@Test
public void testRecursiveComposites() throws Exception {
// This will create recursive composite mappings between "REALM_COMPOSITE_1" and "REALM_ROLE_1"
RoleRepresentation realmComposite1 = testRealm().roles().get("REALM_COMPOSITE_1").toRepresentation();
testRealm().roles().get("REALM_ROLE_1").addComposites(Collections.singletonList(realmComposite1));
UserResource userResource = ApiUtil.findUserByUsernameId(testRealm(), "REALM_COMPOSITE_1_USER");
List<RoleRepresentation> realmRoles = userResource.roles().realmLevel().listEffective();
Assert.assertNames(realmRoles, "REALM_COMPOSITE_1", "REALM_ROLE_1");
userResource = ApiUtil.findUserByUsernameId(testRealm(), "REALM_ROLE_1_USER");
realmRoles = userResource.roles().realmLevel().listEffective();
Assert.assertNames(realmRoles, "REALM_COMPOSITE_1", "REALM_ROLE_1");
}
}