Evaluate composite roles for hardcoded LDAP roles/groups
Closes: 11771 see also KEYCLOAK-18308
This commit is contained in:
parent
52ca546cfa
commit
0efa4afd49
10 changed files with 316 additions and 10 deletions
|
@ -21,6 +21,7 @@ import org.jboss.logging.Logger;
|
|||
import org.keycloak.component.ComponentModel;
|
||||
import org.keycloak.models.*;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.models.utils.RoleUtils;
|
||||
import org.keycloak.models.utils.UserModelDelegate;
|
||||
import org.keycloak.storage.ldap.LDAPStorageProvider;
|
||||
import org.keycloak.storage.ldap.idm.model.LDAPObject;
|
||||
|
@ -63,7 +64,8 @@ public class HardcodedLDAPGroupStorageMapper extends AbstractLDAPStorageMapper {
|
|||
|
||||
@Override
|
||||
public boolean isMemberOf(GroupModel group) {
|
||||
return super.isMemberOf(group) || group.equals(getGroup(realm));
|
||||
GroupModel hardcodedGroup = getGroup(realm);
|
||||
return super.isMemberOf(group) || (hardcodedGroup != null && RoleUtils.isMember(Stream.of(hardcodedGroup), group));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -74,6 +76,12 @@ public class HardcodedLDAPGroupStorageMapper extends AbstractLDAPStorageMapper {
|
|||
super.leaveGroup(group);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRole(RoleModel role) {
|
||||
GroupModel group = getGroup(realm);
|
||||
return super.hasRole(role) || (group != null && group.hasRole(role));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -84,7 +84,8 @@ public class HardcodedLDAPRoleStorageMapper extends AbstractLDAPStorageMapper {
|
|||
|
||||
@Override
|
||||
public boolean hasRole(RoleModel role) {
|
||||
return super.hasRole(role) || role.equals(getRole(realm));
|
||||
RoleModel hardcodedRole = getRole(realm);
|
||||
return super.hasRole(role) || (hardcodedRole != null && hardcodedRole.hasRole(role));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -171,8 +171,9 @@ public class GroupAdapter implements GroupModel.Streams {
|
|||
public boolean hasRole(RoleModel role) {
|
||||
if (isUpdated()) return updated.hasRole(role);
|
||||
if (cached.getRoleMappings(modelSupplier).contains(role.getId())) return true;
|
||||
|
||||
return getRoleMappingsStream().anyMatch(r -> r.hasRole(role));
|
||||
if (getRoleMappingsStream().anyMatch(r -> r.hasRole(role))) return true;
|
||||
GroupModel parent = getParent();
|
||||
return parent != null && parent.hasRole(role);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -214,7 +214,9 @@ public class GroupAdapter implements GroupModel.Streams , JpaModel<GroupEntity>
|
|||
|
||||
@Override
|
||||
public boolean hasRole(RoleModel role) {
|
||||
return RoleUtils.hasRole(getRoleMappingsStream(), role);
|
||||
if (RoleUtils.hasRole(getRoleMappingsStream(), role)) return true;
|
||||
GroupModel parent = getParent();
|
||||
return parent != null && parent.hasRole(role);
|
||||
}
|
||||
|
||||
protected TypedQuery<GroupRoleMappingEntity> getGroupRoleMappingEntityTypedQuery(RoleModel role) {
|
||||
|
|
|
@ -151,7 +151,9 @@ public class MapGroupAdapter extends AbstractGroupModel<MapGroupEntity> {
|
|||
|
||||
@Override
|
||||
public boolean hasRole(RoleModel role) {
|
||||
return RoleUtils.hasRole(getRoleMappingsStream(), role);
|
||||
if (RoleUtils.hasRole(getRoleMappingsStream(), role)) return true;
|
||||
GroupModel parent = getParent();
|
||||
return parent != null && parent.hasRole(role);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -28,16 +28,21 @@ import javax.ws.rs.QueryParam;
|
|||
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
import org.keycloak.component.ComponentModel;
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.LDAPConstants;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.storage.CacheableStorageProviderModel;
|
||||
import org.keycloak.storage.UserStorageProvider;
|
||||
import org.keycloak.storage.UserStorageProviderModel;
|
||||
import org.keycloak.storage.ldap.LDAPStorageProvider;
|
||||
import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
|
||||
import org.keycloak.storage.ldap.LDAPUtils;
|
||||
import org.keycloak.storage.ldap.idm.model.LDAPObject;
|
||||
import org.keycloak.storage.ldap.mappers.HardcodedLDAPRoleStorageMapper;
|
||||
import org.keycloak.storage.ldap.mappers.HardcodedLDAPRoleStorageMapperFactory;
|
||||
import org.keycloak.storage.ldap.mappers.membership.LDAPGroupMapperMode;
|
||||
import org.keycloak.storage.ldap.mappers.membership.MembershipType;
|
||||
import org.keycloak.storage.ldap.mappers.membership.group.GroupLDAPStorageMapperFactory;
|
||||
|
@ -180,7 +185,7 @@ public class TestLDAPResource {
|
|||
}
|
||||
|
||||
/**
|
||||
* Prepare groups LDAP tests. Creates some LDAP mappers as well as some built-in GRoups and users in LDAP
|
||||
* Prepare roles LDAP tests. Creates some LDAP mappers as well as some built-in GRoups and users in LDAP
|
||||
*/
|
||||
@POST
|
||||
@Path("/configure-roles")
|
||||
|
@ -225,6 +230,72 @@ public class TestLDAPResource {
|
|||
new RoleLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(realm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare roles LDAP tests. Creates some LDAP mappers as well as some built-in GRoups and users in LDAP
|
||||
*/
|
||||
@POST
|
||||
@Path("/configure-hardcoded-roles")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public void prepareHardcodedRolesLDAPTest() {
|
||||
ComponentModel ldapCompModel = LDAPTestUtils.getLdapProviderModel(realm);
|
||||
LDAPStorageProvider ldapFedProvider = LDAPTestUtils.getLdapProvider(session, ldapCompModel);
|
||||
UserStorageProviderModel ldapModel = ldapFedProvider.getModel();
|
||||
ldapModel.setCachePolicy(CacheableStorageProviderModel.CachePolicy.NO_CACHE);
|
||||
ldapModel.setImportEnabled(false);
|
||||
ldapModel.getConfig().putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.READ_ONLY.name());
|
||||
realm.updateComponent(ldapModel);
|
||||
|
||||
// Add a hardcoded and composite role
|
||||
RoleModel clientRole = realm.getClientByClientId("admin-cli").addRole("client_role");
|
||||
RoleModel hardcodedRole = realm.addRole("hardcoded_role");
|
||||
hardcodedRole.addCompositeRole(clientRole);
|
||||
|
||||
// Add role mapper
|
||||
LDAPTestUtils.addOrUpdateHardcodedRoleMapper(realm, ldapModel);
|
||||
|
||||
// Remove all LDAP users
|
||||
LDAPTestUtils.removeAllLDAPUsers(ldapFedProvider, realm);
|
||||
|
||||
// Add some LDAP users for testing
|
||||
LDAPObject john = LDAPTestUtils.addLDAPUser(ldapFedProvider, realm, "johnkeycloak", "John", "Doe", "john@email.org", null, "1234");
|
||||
LDAPTestUtils.updateLDAPPassword(ldapFedProvider, john, "Password1");
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare roles LDAP tests. Creates some LDAP mappers as well as some built-in GRoups and users in LDAP
|
||||
*/
|
||||
@POST
|
||||
@Path("/configure-hardcoded-groups")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public void prepareHardcodedGroupsLDAPTest() {
|
||||
ComponentModel ldapCompModel = LDAPTestUtils.getLdapProviderModel(realm);
|
||||
LDAPStorageProvider ldapFedProvider = LDAPTestUtils.getLdapProvider(session, ldapCompModel);
|
||||
UserStorageProviderModel ldapModel = ldapFedProvider.getModel();
|
||||
ldapModel.setCachePolicy(CacheableStorageProviderModel.CachePolicy.NO_CACHE);
|
||||
ldapModel.setImportEnabled(false);
|
||||
ldapModel.getConfig().putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.READ_ONLY.name());
|
||||
realm.updateComponent(ldapModel);
|
||||
|
||||
// Add a hardcoded group hierarchy with role
|
||||
RoleModel clientRole = realm.getClientByClientId("admin-cli").addRole("client_role");
|
||||
GroupModel parentGroup = realm.createGroup("parent_group");
|
||||
parentGroup.grantRole(clientRole);
|
||||
GroupModel hardcodedGroup = realm.createGroup("hardcoded_group");
|
||||
parentGroup.addChild(hardcodedGroup);
|
||||
|
||||
// Add group mapper
|
||||
LDAPTestUtils.addOrUpdateHardcodedGroupMapper(realm, ldapModel);
|
||||
|
||||
// Remove all LDAP users
|
||||
LDAPTestUtils.removeAllLDAPUsers(ldapFedProvider, realm);
|
||||
|
||||
// Add some LDAP users for testing
|
||||
LDAPObject john = LDAPTestUtils.addLDAPUser(ldapFedProvider, realm, "johnkeycloak", "John", "Doe", "john@email.org", null, "1234");
|
||||
LDAPTestUtils.updateLDAPPassword(ldapFedProvider, john, "Password1");
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove specified user directly just from the LDAP server
|
||||
*/
|
||||
|
|
|
@ -34,6 +34,10 @@ import org.keycloak.storage.ldap.idm.model.LDAPDn;
|
|||
import org.keycloak.storage.ldap.idm.model.LDAPObject;
|
||||
import org.keycloak.storage.ldap.idm.query.internal.LDAPQuery;
|
||||
import org.keycloak.storage.ldap.idm.store.ldap.LDAPIdentityStore;
|
||||
import org.keycloak.storage.ldap.mappers.HardcodedLDAPGroupStorageMapper;
|
||||
import org.keycloak.storage.ldap.mappers.HardcodedLDAPGroupStorageMapperFactory;
|
||||
import org.keycloak.storage.ldap.mappers.HardcodedLDAPRoleStorageMapper;
|
||||
import org.keycloak.storage.ldap.mappers.HardcodedLDAPRoleStorageMapperFactory;
|
||||
import org.keycloak.storage.ldap.mappers.LDAPStorageMapper;
|
||||
import org.keycloak.storage.ldap.mappers.UserAttributeLDAPStorageMapper;
|
||||
import org.keycloak.storage.ldap.mappers.UserAttributeLDAPStorageMapperFactory;
|
||||
|
@ -228,6 +232,20 @@ public class LDAPTestUtils {
|
|||
.orElse(null);
|
||||
}
|
||||
|
||||
public static void addOrUpdateHardcodedGroupMapper(RealmModel realm, ComponentModel providerModel, String... otherConfigOptions) {
|
||||
ComponentModel mapperModel = getSubcomponentByName(realm, providerModel, "hardcodedGroupsMapper");
|
||||
if (mapperModel != null) {
|
||||
updateGroupMapperConfigOptions(mapperModel, otherConfigOptions);
|
||||
realm.updateComponent(mapperModel);
|
||||
} else {
|
||||
mapperModel = KeycloakModelUtils.createComponentModel("hardcodedGroupsMapper", providerModel.getId(),
|
||||
HardcodedLDAPGroupStorageMapperFactory.PROVIDER_ID, LDAPStorageMapper.class.getName(),
|
||||
HardcodedLDAPGroupStorageMapper.GROUP, "parent_group/hardcoded_group");
|
||||
updateConfigOptions(mapperModel, otherConfigOptions);
|
||||
realm.addComponentModel(mapperModel);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addOrUpdateGroupMapper(RealmModel realm, ComponentModel providerModel, LDAPGroupMapperMode mode, String descriptionAttrName, String... otherConfigOptions) {
|
||||
ComponentModel mapperModel = getSubcomponentByName(realm, providerModel, "groupsMapper");
|
||||
if (mapperModel != null) {
|
||||
|
@ -247,6 +265,19 @@ public class LDAPTestUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static void addOrUpdateHardcodedRoleMapper(RealmModel realm, ComponentModel providerModel, String... otherConfigOptions) {
|
||||
ComponentModel mapperModel = getSubcomponentByName(realm, providerModel, "hardcodedRolesMapper");
|
||||
if (mapperModel != null) {
|
||||
updateConfigOptions(mapperModel, otherConfigOptions);
|
||||
realm.updateComponent(mapperModel);
|
||||
} else {
|
||||
mapperModel = KeycloakModelUtils.createComponentModel("hardcodedRolesMapper", providerModel.getId(), HardcodedLDAPRoleStorageMapperFactory.PROVIDER_ID, LDAPStorageMapper.class.getName(),
|
||||
HardcodedLDAPRoleStorageMapper.ROLE, "hardcoded_role");
|
||||
updateConfigOptions(mapperModel, otherConfigOptions);
|
||||
realm.addComponentModel(mapperModel);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addOrUpdateRoleMapper(RealmModel realm, ComponentModel providerModel, LDAPGroupMapperMode mode, String... otherConfigOptions) {
|
||||
ComponentModel mapperModel = getSubcomponentByName(realm, providerModel, "rolesMapper");
|
||||
if (mapperModel != null) {
|
||||
|
@ -264,14 +295,19 @@ public class LDAPTestUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static void updateGroupMapperConfigOptions(ComponentModel mapperModel, String... configOptions) {
|
||||
public static void updateConfigOptions(ComponentModel componentModel, String... configOptions) {
|
||||
for (int i=0 ; i<configOptions.length ; i+=2) {
|
||||
String cfgName = configOptions[i];
|
||||
String cfgValue = configOptions[i+1];
|
||||
mapperModel.getConfig().putSingle(cfgName, cfgValue);
|
||||
componentModel.getConfig().putSingle(cfgName, cfgValue);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void updateGroupMapperConfigOptions(ComponentModel mapperModel, String... configOptions) {
|
||||
updateConfigOptions(mapperModel, configOptions);
|
||||
}
|
||||
|
||||
// End CRUD model mappers
|
||||
|
||||
public static void syncRolesFromLDAP(RealmModel realm, LDAPStorageProvider ldapProvider, ComponentModel providerModel) {
|
||||
|
|
|
@ -56,7 +56,16 @@ public interface TestingLDAPResource {
|
|||
void prepareGroupsLDAPTest();
|
||||
|
||||
/**
|
||||
* Prepare groups LDAP tests. Creates some LDAP mappers as well as some built-in GRoups and users in LDAP
|
||||
* Prepare hardcoded groups LDAP tests. Creates some LDAP mappers as well as some built-in Groups and users in LDAP
|
||||
*/
|
||||
@POST
|
||||
@Path("/configure-hardcoded-groups")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
void prepareHardcodedGroupsLDAPTest();
|
||||
|
||||
/**
|
||||
* Prepare groups LDAP tests. Creates some LDAP mappers as well as some built-in Groups and users in LDAP
|
||||
*/
|
||||
@POST
|
||||
@Path("/configure-roles")
|
||||
|
@ -64,6 +73,15 @@ public interface TestingLDAPResource {
|
|||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
void prepareRolesLDAPTest();
|
||||
|
||||
/**
|
||||
* Prepare hardcoded roles LDAP tests. Creates some LDAP mappers as well as some hardcoded roles and users in LDAP
|
||||
*/
|
||||
@POST
|
||||
@Path("/configure-hardcoded-roles")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
void prepareHardcodedRolesLDAPTest();
|
||||
|
||||
/**
|
||||
* Remove specified user directly just from the LDAP server
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright 2020 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.testsuite.federation.ldap;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.testsuite.util.LDAPRule;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
/**
|
||||
* @author sventorben
|
||||
*/
|
||||
public class LDAPHardcodedGroupMapperTest extends AbstractLDAPTest implements Serializable {
|
||||
|
||||
@ClassRule
|
||||
public static LDAPRule ldapRule = new LDAPRule();
|
||||
|
||||
@Override
|
||||
protected LDAPRule getLDAPRule() {
|
||||
return ldapRule;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterImportTestRealm() {
|
||||
testingClient.testing().ldap(TEST_REALM_NAME).prepareHardcodedGroupsLDAPTest();
|
||||
}
|
||||
|
||||
/**
|
||||
* KEYCLOAK-18308
|
||||
*/
|
||||
@Test
|
||||
public void testCompositeGroups() {
|
||||
testingClient.server().run(session -> {
|
||||
LDAPTestContext ctx = LDAPTestContext.init(session);
|
||||
RealmModel appRealm = ctx.getRealm();
|
||||
|
||||
// check users
|
||||
UserModel john = session.users().getUserByUsername(appRealm, "johnkeycloak");
|
||||
assertThat(john, notNullValue());
|
||||
|
||||
// check roles
|
||||
RoleModel clientRoleGrantedViaHardcodedGroupMembership = appRealm.getClientByClientId("admin-cli").getRole(
|
||||
"client_role");
|
||||
assertThat(clientRoleGrantedViaHardcodedGroupMembership, notNullValue());
|
||||
|
||||
// check groups
|
||||
GroupModel hardcodedGroup = appRealm.getGroupsStream()
|
||||
.filter(it -> it.getName().equals("hardcoded_group")).findFirst().orElse(null);
|
||||
assertThat(hardcodedGroup, notNullValue());
|
||||
GroupModel parentGroup = appRealm.getGroupsStream()
|
||||
.filter(it -> it.getName().equals("parent_group")).findFirst().orElse(null);
|
||||
assertThat(parentGroup, notNullValue());
|
||||
assertThat(hardcodedGroup.getParent(), equalTo(parentGroup));
|
||||
|
||||
// check group membership
|
||||
assertThat(john.isMemberOf(hardcodedGroup), is(true));
|
||||
assertThat(john.isMemberOf(parentGroup), is(true));
|
||||
|
||||
// check role membership
|
||||
assertThat(john.hasRole(clientRoleGrantedViaHardcodedGroupMembership), is(true));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright 2020 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.testsuite.federation.ldap;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.testsuite.util.LDAPRule;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
|
||||
/**
|
||||
* @author sventorben
|
||||
*/
|
||||
public class LDAPHardcodedRoleMapperTest extends AbstractLDAPTest {
|
||||
|
||||
@ClassRule
|
||||
public static LDAPRule ldapRule = new LDAPRule();
|
||||
|
||||
@Override
|
||||
protected LDAPRule getLDAPRule() {
|
||||
return ldapRule;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterImportTestRealm() {
|
||||
testingClient.testing().ldap(TEST_REALM_NAME).prepareHardcodedRolesLDAPTest();
|
||||
}
|
||||
|
||||
/**
|
||||
* KEYCLOAK-18308
|
||||
*/
|
||||
@Test
|
||||
public void testCompositeRoles() {
|
||||
testingClient.server().run(session -> {
|
||||
LDAPTestContext ctx = LDAPTestContext.init(session);
|
||||
RealmModel appRealm = ctx.getRealm();
|
||||
|
||||
// check users
|
||||
UserModel john = session.users().getUserByUsername(appRealm, "johnkeycloak");
|
||||
assertThat(john, notNullValue());
|
||||
|
||||
// check roles
|
||||
RoleModel hardcodedRole = appRealm.getRole("hardcoded_role");
|
||||
assertThat(hardcodedRole, notNullValue());
|
||||
RoleModel compositeClientRole = appRealm.getClientByClientId("admin-cli").getRole("client_role");
|
||||
assertThat(compositeClientRole, notNullValue());
|
||||
assertThat(hardcodedRole.isComposite(), is(true));
|
||||
assertThat(hardcodedRole.getCompositesStream().map(RoleModel::getName).collect(Collectors.toSet()),
|
||||
containsInAnyOrder("client_role"));
|
||||
|
||||
// check role membership
|
||||
assertThat(john.hasRole(hardcodedRole), is(true));
|
||||
assertThat(john.hasRole(compositeClientRole), is(true));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue