KEYCLOAK-13306 Model fixes for check realm when lookup by ID
(cherry picked from commit e40a62de31f6f5d326234314a9e285010665f707)
This commit is contained in:
parent
821405e175
commit
b29810c923
4 changed files with 627 additions and 32 deletions
|
@ -250,14 +250,17 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
|
|||
}
|
||||
|
||||
protected UserSessionAdapter getUserSession(RealmModel realm, String id, boolean offline) {
|
||||
UserSessionEntity entity = getUserSessionEntity(id, offline);
|
||||
UserSessionEntity entity = getUserSessionEntity(realm, id, offline);
|
||||
return wrap(realm, entity, offline);
|
||||
}
|
||||
|
||||
private UserSessionEntity getUserSessionEntity(String id, boolean offline) {
|
||||
private UserSessionEntity getUserSessionEntity(RealmModel realm, String id, boolean offline) {
|
||||
InfinispanChangelogBasedTransaction<String, UserSessionEntity> tx = getTransaction(offline);
|
||||
SessionEntityWrapper<UserSessionEntity> entityWrapper = tx.get(id);
|
||||
return entityWrapper==null ? null : entityWrapper.getEntity();
|
||||
if (entityWrapper==null) return null;
|
||||
UserSessionEntity entity = entityWrapper.getEntity();
|
||||
if (!entity.getRealmId().equals(realm.getId())) return null;
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
||||
|
@ -455,7 +458,7 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
|
|||
|
||||
@Override
|
||||
public void removeUserSession(RealmModel realm, UserSessionModel session) {
|
||||
UserSessionEntity entity = getUserSessionEntity(session, false);
|
||||
UserSessionEntity entity = getUserSessionEntity(realm, session, false);
|
||||
if (entity != null) {
|
||||
removeUserSession(entity, false);
|
||||
}
|
||||
|
@ -801,11 +804,12 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
|
|||
return entity != null ? new UserLoginFailureAdapter(this, key, entity) : null;
|
||||
}
|
||||
|
||||
UserSessionEntity getUserSessionEntity(UserSessionModel userSession, boolean offline) {
|
||||
UserSessionEntity getUserSessionEntity(RealmModel realm, UserSessionModel userSession, boolean offline) {
|
||||
if (userSession instanceof UserSessionAdapter) {
|
||||
if (!userSession.getRealm().equals(realm)) return null;
|
||||
return ((UserSessionAdapter) userSession).getEntity();
|
||||
} else {
|
||||
return getUserSessionEntity(userSession.getId(), offline);
|
||||
return getUserSessionEntity(realm, userSession.getId(), offline);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -829,7 +833,7 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
|
|||
|
||||
@Override
|
||||
public void removeOfflineUserSession(RealmModel realm, UserSessionModel userSession) {
|
||||
UserSessionEntity userSessionEntity = getUserSessionEntity(userSession, true);
|
||||
UserSessionEntity userSessionEntity = getUserSessionEntity(realm, userSession, true);
|
||||
if (userSessionEntity != null) {
|
||||
removeUserSession(userSessionEntity, true);
|
||||
}
|
||||
|
|
|
@ -364,6 +364,10 @@ public class JpaRealmProvider implements RealmProvider {
|
|||
container.removeDefaultRoles(role.getName());
|
||||
}
|
||||
RoleEntity roleEntity = em.getReference(RoleEntity.class, role.getId());
|
||||
if (roleEntity == null || !roleEntity.getRealmId().equals(realm.getId())) {
|
||||
// Throw model exception to ensure transaction rollback and revert previous operations (removing default roles) as well
|
||||
throw new ModelException("Role not found or trying to remove role from incorrect realm");
|
||||
}
|
||||
String compositeRoleTable = JpaUtils.getTableNameForNativeQuery("COMPOSITE_ROLE", em);
|
||||
em.createNativeQuery("delete from " + compositeRoleTable + " where CHILD_ROLE = :role").setParameter("role", roleEntity).executeUpdate();
|
||||
realm.getClients().forEach(c -> c.deleteScopeMapping(role));
|
||||
|
@ -786,20 +790,18 @@ public class JpaRealmProvider implements RealmProvider {
|
|||
@Override
|
||||
public ClientInitialAccessModel getClientInitialAccessModel(RealmModel realm, String id) {
|
||||
ClientInitialAccessEntity entity = em.find(ClientInitialAccessEntity.class, id);
|
||||
if (entity == null) {
|
||||
return null;
|
||||
} else {
|
||||
return entityToModel(entity);
|
||||
}
|
||||
if (entity == null) return null;
|
||||
if (!entity.getRealm().getId().equals(realm.getId())) return null;
|
||||
return entityToModel(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeClientInitialAccessModel(RealmModel realm, String id) {
|
||||
ClientInitialAccessEntity entity = em.find(ClientInitialAccessEntity.class, id, LockModeType.PESSIMISTIC_WRITE);
|
||||
if (entity != null) {
|
||||
em.remove(entity);
|
||||
em.flush();
|
||||
}
|
||||
if (entity == null) return;
|
||||
if (!entity.getRealm().getId().equals(realm.getId())) return;
|
||||
em.remove(entity);
|
||||
em.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1651,7 +1651,7 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
|
||||
@Override
|
||||
public AuthenticationFlowModel getAuthenticationFlowById(String id) {
|
||||
AuthenticationFlowEntity entity = em.find(AuthenticationFlowEntity.class, id);
|
||||
AuthenticationFlowEntity entity = getAuthenticationFlowEntity(id, false);
|
||||
if (entity == null) return null;
|
||||
return entityToModel(entity);
|
||||
}
|
||||
|
@ -1661,15 +1661,15 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
if (KeycloakModelUtils.isFlowUsed(this, model)) {
|
||||
throw new ModelException("Cannot remove authentication flow, it is currently in use");
|
||||
}
|
||||
AuthenticationFlowEntity entity = em.find(AuthenticationFlowEntity.class, model.getId(), LockModeType.PESSIMISTIC_WRITE);
|
||||
|
||||
AuthenticationFlowEntity entity = getAuthenticationFlowEntity(model.getId(), true);
|
||||
if (entity == null) return;
|
||||
em.remove(entity);
|
||||
em.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAuthenticationFlow(AuthenticationFlowModel model) {
|
||||
AuthenticationFlowEntity entity = em.find(AuthenticationFlowEntity.class, model.getId());
|
||||
AuthenticationFlowEntity entity = getAuthenticationFlowEntity(model.getId(), false);
|
||||
if (entity == null) return;
|
||||
entity.setAlias(model.getAlias());
|
||||
entity.setDescription(model.getDescription());
|
||||
|
@ -1679,6 +1679,15 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
|
||||
}
|
||||
|
||||
private AuthenticationFlowEntity getAuthenticationFlowEntity(String id, boolean readForRemove) {
|
||||
AuthenticationFlowEntity entity = readForRemove
|
||||
? em.find(AuthenticationFlowEntity.class, id, LockModeType.PESSIMISTIC_WRITE)
|
||||
: em.find(AuthenticationFlowEntity.class, id);
|
||||
if (entity == null) return null;
|
||||
if (!entity.getRealm().equals(getEntity())) return null;
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthenticationFlowModel addAuthenticationFlow(AuthenticationFlowModel model) {
|
||||
AuthenticationFlowEntity entity = new AuthenticationFlowEntity();
|
||||
|
@ -1723,7 +1732,7 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
|
||||
@Override
|
||||
public AuthenticationExecutionModel getAuthenticationExecutionById(String id) {
|
||||
AuthenticationExecutionEntity entity = em.find(AuthenticationExecutionEntity.class, id);
|
||||
AuthenticationExecutionEntity entity = getAuthenticationExecution(id, false);
|
||||
if (entity == null) return null;
|
||||
return entityToModel(entity);
|
||||
}
|
||||
|
@ -1761,7 +1770,7 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
|
||||
@Override
|
||||
public void updateAuthenticatorExecution(AuthenticationExecutionModel model) {
|
||||
AuthenticationExecutionEntity entity = em.find(AuthenticationExecutionEntity.class, model.getId());
|
||||
AuthenticationExecutionEntity entity = getAuthenticationExecution(model.getId(), false);
|
||||
if (entity == null) return;
|
||||
entity.setAutheticatorFlow(model.isAuthenticatorFlow());
|
||||
entity.setAuthenticator(model.getAuthenticator());
|
||||
|
@ -1778,13 +1787,22 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
|
||||
@Override
|
||||
public void removeAuthenticatorExecution(AuthenticationExecutionModel model) {
|
||||
AuthenticationExecutionEntity entity = em.find(AuthenticationExecutionEntity.class, model.getId(), LockModeType.PESSIMISTIC_WRITE);
|
||||
AuthenticationExecutionEntity entity = getAuthenticationExecution(model.getId(), true);
|
||||
if (entity == null) return;
|
||||
em.remove(entity);
|
||||
em.flush();
|
||||
|
||||
}
|
||||
|
||||
private AuthenticationExecutionEntity getAuthenticationExecution(String id, boolean readForRemove) {
|
||||
AuthenticationExecutionEntity entity = readForRemove
|
||||
? em.find(AuthenticationExecutionEntity.class, id, LockModeType.PESSIMISTIC_WRITE)
|
||||
: em.find(AuthenticationExecutionEntity.class, id);
|
||||
if (entity == null) return null;
|
||||
if (!entity.getRealm().equals(getEntity())) return null;
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthenticatorConfigModel addAuthenticatorConfig(AuthenticatorConfigModel model) {
|
||||
AuthenticatorConfigEntity auth = new AuthenticatorConfigEntity();
|
||||
|
@ -1801,7 +1819,7 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
|
||||
@Override
|
||||
public void removeAuthenticatorConfig(AuthenticatorConfigModel model) {
|
||||
AuthenticatorConfigEntity entity = em.find(AuthenticatorConfigEntity.class, model.getId(), LockModeType.PESSIMISTIC_WRITE);
|
||||
AuthenticatorConfigEntity entity = getAuthenticatorConfigEntity(model.getId(), true);
|
||||
if (entity == null) return;
|
||||
em.remove(entity);
|
||||
em.flush();
|
||||
|
@ -1810,7 +1828,7 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
|
||||
@Override
|
||||
public AuthenticatorConfigModel getAuthenticatorConfigById(String id) {
|
||||
AuthenticatorConfigEntity entity = em.find(AuthenticatorConfigEntity.class, id);
|
||||
AuthenticatorConfigEntity entity = getAuthenticatorConfigEntity(id, false);
|
||||
if (entity == null) return null;
|
||||
return entityToModel(entity);
|
||||
}
|
||||
|
@ -1827,7 +1845,7 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
|
||||
@Override
|
||||
public void updateAuthenticatorConfig(AuthenticatorConfigModel model) {
|
||||
AuthenticatorConfigEntity entity = em.find(AuthenticatorConfigEntity.class, model.getId());
|
||||
AuthenticatorConfigEntity entity = getAuthenticatorConfigEntity(model.getId(), false);
|
||||
if (entity == null) return;
|
||||
entity.setAlias(model.getAlias());
|
||||
if (entity.getConfig() == null) {
|
||||
|
@ -1842,6 +1860,15 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
|
||||
}
|
||||
|
||||
private AuthenticatorConfigEntity getAuthenticatorConfigEntity(String id, boolean readForRemove) {
|
||||
AuthenticatorConfigEntity entity = readForRemove
|
||||
? em.find(AuthenticatorConfigEntity.class, id, LockModeType.PESSIMISTIC_WRITE)
|
||||
: em.find(AuthenticatorConfigEntity.class, id);
|
||||
if (entity == null) return null;
|
||||
if (!entity.getRealm().equals(getEntity())) return null;
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AuthenticatorConfigModel> getAuthenticatorConfigs() {
|
||||
Collection<AuthenticatorConfigEntity> entities = realm.getAuthenticatorConfigs();
|
||||
|
@ -1875,7 +1902,7 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
|
||||
@Override
|
||||
public void removeRequiredActionProvider(RequiredActionProviderModel model) {
|
||||
RequiredActionProviderEntity entity = em.find(RequiredActionProviderEntity.class, model.getId(), LockModeType.PESSIMISTIC_WRITE);
|
||||
RequiredActionProviderEntity entity = getRequiredProviderEntity(model.getId(), true);
|
||||
if (entity == null) return;
|
||||
em.remove(entity);
|
||||
em.flush();
|
||||
|
@ -1884,7 +1911,7 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
|
||||
@Override
|
||||
public RequiredActionProviderModel getRequiredActionProviderById(String id) {
|
||||
RequiredActionProviderEntity entity = em.find(RequiredActionProviderEntity.class, id);
|
||||
RequiredActionProviderEntity entity = getRequiredProviderEntity(id, false);
|
||||
if (entity == null) return null;
|
||||
return entityToModel(entity);
|
||||
}
|
||||
|
@ -1906,7 +1933,7 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
|
||||
@Override
|
||||
public void updateRequiredActionProvider(RequiredActionProviderModel model) {
|
||||
RequiredActionProviderEntity entity = em.find(RequiredActionProviderEntity.class, model.getId());
|
||||
RequiredActionProviderEntity entity = getRequiredProviderEntity(model.getId(), false);
|
||||
if (entity == null) return;
|
||||
entity.setAlias(model.getAlias());
|
||||
entity.setProviderId(model.getProviderId());
|
||||
|
@ -1938,6 +1965,15 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
return Collections.unmodifiableList(actions);
|
||||
}
|
||||
|
||||
private RequiredActionProviderEntity getRequiredProviderEntity(String id, boolean readForRemove) {
|
||||
RequiredActionProviderEntity entity = readForRemove
|
||||
? em.find(RequiredActionProviderEntity.class, id, LockModeType.PESSIMISTIC_WRITE)
|
||||
: em.find(RequiredActionProviderEntity.class, id);
|
||||
if (entity == null) return null;
|
||||
if (!entity.getRealm().equals(getEntity())) return null;
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequiredActionProviderModel getRequiredActionProviderByAlias(String alias) {
|
||||
for (RequiredActionProviderModel action : getRequiredActionProviders()) {
|
||||
|
@ -2178,7 +2214,7 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
public void updateComponent(ComponentModel component) {
|
||||
ComponentUtil.getComponentFactory(session, component).validateConfiguration(session, this, component);
|
||||
|
||||
ComponentEntity c = em.find(ComponentEntity.class, component.getId());
|
||||
ComponentEntity c = getComponentEntity(component.getId());
|
||||
if (c == null) return;
|
||||
ComponentModel old = entityToModel(c);
|
||||
c.setName(component.getName());
|
||||
|
@ -2194,7 +2230,7 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
|
||||
@Override
|
||||
public void removeComponent(ComponentModel component) {
|
||||
ComponentEntity c = em.find(ComponentEntity.class, component.getId());
|
||||
ComponentEntity c = getComponentEntity(component.getId());
|
||||
if (c == null) return;
|
||||
session.users().preRemove(this, component);
|
||||
ComponentUtil.notifyPreRemove(session, this, component);
|
||||
|
@ -2260,8 +2296,14 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
|
||||
@Override
|
||||
public ComponentModel getComponent(String id) {
|
||||
ComponentEntity c = getComponentEntity(id);
|
||||
return c==null ? null : entityToModel(c);
|
||||
}
|
||||
|
||||
private ComponentEntity getComponentEntity(String id) {
|
||||
ComponentEntity c = em.find(ComponentEntity.class, id);
|
||||
if (c == null) return null;
|
||||
return entityToModel(c);
|
||||
if (!c.getRealm().equals(getEntity())) return null;
|
||||
return c;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,547 @@
|
|||
/*
|
||||
* Copyright 2019 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.model;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.component.ComponentModel;
|
||||
import org.keycloak.models.AuthenticationExecutionModel;
|
||||
import org.keycloak.models.AuthenticationFlowModel;
|
||||
import org.keycloak.models.AuthenticatorConfigModel;
|
||||
import org.keycloak.models.ClientInitialAccessModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ModelException;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RealmProvider;
|
||||
import org.keycloak.models.RequiredActionProviderModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.models.utils.DefaultAuthenticationFlows;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.testsuite.AbstractKeycloakTest;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude;
|
||||
import org.keycloak.testsuite.arquillian.annotation.ModelTest;
|
||||
import org.keycloak.testsuite.util.RealmBuilder;
|
||||
import org.keycloak.testsuite.util.UserBuilder;
|
||||
|
||||
import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson;
|
||||
|
||||
/**
|
||||
* Test for the CRUD scenarios when the operation is called on the object, which is owned by different realm
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
@AuthServerContainerExclude(AuthServerContainerExclude.AuthServer.REMOTE)
|
||||
public class OwnerReplacementTest extends AbstractKeycloakTest {
|
||||
|
||||
|
||||
@Override
|
||||
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
||||
log.debug("Adding test realm for import from testrealm.json");
|
||||
RealmRepresentation testRealm = loadJson(getClass().getResourceAsStream("/testrealm.json"), RealmRepresentation.class);
|
||||
testRealms.add(testRealm);
|
||||
|
||||
UserRepresentation user = UserBuilder.create()
|
||||
.username("foo@user")
|
||||
.email("foo@user.com")
|
||||
.password("password")
|
||||
.build();
|
||||
|
||||
RealmRepresentation realm2 = RealmBuilder.create()
|
||||
.name("foo")
|
||||
.user(user)
|
||||
.build();
|
||||
realm2.setId("foo");
|
||||
testRealms.add(realm2);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@ModelTest
|
||||
public void componentsTest(KeycloakSession session1) {
|
||||
doTest(session1,
|
||||
// Get ID of some component from realm1
|
||||
((session, realm1) -> {
|
||||
|
||||
List<ComponentModel> components = realm1.getComponents();
|
||||
return components.get(0).getId();
|
||||
|
||||
}),
|
||||
// Test lookup realm1 component in realm2 should not work
|
||||
((session, realm2, realm1ComponentId) -> {
|
||||
|
||||
ComponentModel component = realm2.getComponent(realm1ComponentId);
|
||||
Assert.assertNull(component);
|
||||
|
||||
}),
|
||||
// Try to update some component in realm1 through the realm2
|
||||
((session, realm1, realm2, realm1ComponentId) -> {
|
||||
|
||||
ComponentModel component = realm1.getComponent(realm1ComponentId);
|
||||
component.put("key1", "Val1");
|
||||
realm2.updateComponent(component);
|
||||
|
||||
}),
|
||||
// Test update from above was not successful
|
||||
((session, realm1, realm1ComponentId) -> {
|
||||
|
||||
ComponentModel component = realm1.getComponent(realm1ComponentId);
|
||||
Assert.assertNull(component.get("key1"));
|
||||
|
||||
}),
|
||||
// Try remove component from realm1 in the context of realm2
|
||||
((session, realm1, realm2, realm1ComponentId) -> {
|
||||
|
||||
ComponentModel component = realm1.getComponent(realm1ComponentId);
|
||||
realm2.removeComponent(component);
|
||||
|
||||
}),
|
||||
// Test remove from above was not successful
|
||||
((session, realm1, realm1ComponentId) -> {
|
||||
|
||||
ComponentModel component = realm1.getComponent(realm1ComponentId);
|
||||
Assert.assertNotNull(component);
|
||||
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ModelTest
|
||||
public void requiredActionProvidersTest(KeycloakSession session1) {
|
||||
doTest(session1,
|
||||
// Get ID of some object from realm1
|
||||
((session, realm1) -> {
|
||||
|
||||
List<RequiredActionProviderModel> reqActions = realm1.getRequiredActionProviders();
|
||||
return reqActions.get(0).getId();
|
||||
|
||||
}),
|
||||
// Test lookup realm1 object in realm2 should not work
|
||||
((session, realm2, realm1ReqActionId) -> {
|
||||
|
||||
RequiredActionProviderModel reqAction = realm2.getRequiredActionProviderById(realm1ReqActionId);
|
||||
Assert.assertNull(reqAction);
|
||||
|
||||
}),
|
||||
// Try to update some object in realm1 through the realm2
|
||||
((session, realm1, realm2, realm1ReqActionId) -> {
|
||||
|
||||
RequiredActionProviderModel reqAction = realm1.getRequiredActionProviderById(realm1ReqActionId);
|
||||
reqAction.getConfig().put("key1", "Val1");
|
||||
realm2.updateRequiredActionProvider(reqAction);
|
||||
|
||||
}),
|
||||
// Test update from above was not successful
|
||||
((session, realm1, realm1ReqActionId) -> {
|
||||
|
||||
RequiredActionProviderModel reqAction = realm1.getRequiredActionProviderById(realm1ReqActionId);
|
||||
Assert.assertNull(reqAction.getConfig().get("key1"));
|
||||
|
||||
}),
|
||||
// Try remove object from realm1 in the context of realm2
|
||||
((session, realm1, realm2, realm1ReqActionId) -> {
|
||||
|
||||
RequiredActionProviderModel reqAction = realm1.getRequiredActionProviderById(realm1ReqActionId);
|
||||
realm2.removeRequiredActionProvider(reqAction);
|
||||
|
||||
}),
|
||||
// Test remove from above was not successful
|
||||
((session, realm1, realm1ReqActionId) -> {
|
||||
|
||||
RequiredActionProviderModel reqAction = realm1.getRequiredActionProviderById(realm1ReqActionId);
|
||||
Assert.assertNotNull(reqAction);
|
||||
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@ModelTest
|
||||
public void authenticationFlowsTest(KeycloakSession session1) {
|
||||
doTest(session1,
|
||||
// Get ID of some object from realm1
|
||||
((session, realm1) -> {
|
||||
|
||||
AuthenticationFlowModel flow = realm1.getFlowByAlias(DefaultAuthenticationFlows.BROWSER_FLOW);
|
||||
return flow.getId();
|
||||
|
||||
}),
|
||||
// Test lookup realm1 object in realm2 should not work
|
||||
((session, realm2, realm1FlowId) -> {
|
||||
|
||||
AuthenticationFlowModel flow = realm2.getAuthenticationFlowById(realm1FlowId);
|
||||
Assert.assertNull(flow);
|
||||
|
||||
}),
|
||||
// Try to update some object in realm1 through the realm2
|
||||
((session, realm1, realm2, realm1FlowId) -> {
|
||||
|
||||
AuthenticationFlowModel flow = realm1.getAuthenticationFlowById(realm1FlowId);
|
||||
flow.setDescription("foo");
|
||||
realm2.updateAuthenticationFlow(flow);
|
||||
|
||||
}),
|
||||
// Test update from above was not successful
|
||||
((session, realm1, realm1FlowId) -> {
|
||||
|
||||
AuthenticationFlowModel flow = realm1.getAuthenticationFlowById(realm1FlowId);
|
||||
Assert.assertNotEquals("foo", flow.getDescription());
|
||||
|
||||
}),
|
||||
// Try remove object from realm1 in the context of realm2
|
||||
((session, realm1, realm2, realm1FlowId) -> {
|
||||
|
||||
AuthenticationFlowModel flow = realm1.getAuthenticationFlowById(realm1FlowId);
|
||||
realm2.removeAuthenticationFlow(flow);
|
||||
|
||||
}),
|
||||
// Test remove from above was not successful
|
||||
((session, realm1, realm1FlowId) -> {
|
||||
|
||||
AuthenticationFlowModel flow = realm1.getAuthenticationFlowById(realm1FlowId);
|
||||
Assert.assertNotNull(flow);
|
||||
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@ModelTest
|
||||
public void authenticationExecutionsTest(KeycloakSession session1) {
|
||||
doTest(session1,
|
||||
// Get ID of some object from realm1
|
||||
((session, realm1) -> {
|
||||
|
||||
AuthenticationFlowModel flow = realm1.getFlowByAlias(DefaultAuthenticationFlows.BROWSER_FLOW);
|
||||
List<AuthenticationExecutionModel> executions = realm1.getAuthenticationExecutions(flow.getId());
|
||||
return executions.get(0).getId();
|
||||
|
||||
}),
|
||||
// Test lookup realm1 object in realm2 should not work
|
||||
((session, realm2, realm1ExecutionId) -> {
|
||||
|
||||
AuthenticationExecutionModel execution = realm2.getAuthenticationExecutionById(realm1ExecutionId);
|
||||
Assert.assertNull(execution);
|
||||
|
||||
}),
|
||||
// Try to update some object in realm1 through the realm2
|
||||
((session, realm1, realm2, realm1ExecutionId) -> {
|
||||
|
||||
AuthenticationExecutionModel execution = realm1.getAuthenticationExecutionById(realm1ExecutionId);
|
||||
execution.setPriority(1234);
|
||||
realm2.updateAuthenticatorExecution(execution);
|
||||
|
||||
}),
|
||||
// Test update from above was not successful
|
||||
((session, realm1, realm1ExecutionId) -> {
|
||||
|
||||
AuthenticationExecutionModel execution = realm1.getAuthenticationExecutionById(realm1ExecutionId);
|
||||
Assert.assertNotEquals(1234, execution.getPriority());
|
||||
|
||||
}),
|
||||
// Try remove object from realm1 in the context of realm2
|
||||
((session, realm1, realm2, realm1ExecutionId) -> {
|
||||
|
||||
AuthenticationExecutionModel execution = realm1.getAuthenticationExecutionById(realm1ExecutionId);
|
||||
realm2.removeAuthenticatorExecution(execution);
|
||||
|
||||
}),
|
||||
// Test remove from above was not successful
|
||||
((session,realm1, realm1ExecutionId) -> {
|
||||
|
||||
AuthenticationExecutionModel execution = realm1.getAuthenticationExecutionById(realm1ExecutionId);
|
||||
Assert.assertNotNull(execution);
|
||||
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@ModelTest
|
||||
public void authenticationConfigsTest(KeycloakSession session1) {
|
||||
doTest(session1,
|
||||
// Get ID of some object from realm1
|
||||
((session, realm1) -> {
|
||||
|
||||
List<AuthenticatorConfigModel> configs = realm1.getAuthenticatorConfigs();
|
||||
return configs.get(0).getId();
|
||||
|
||||
}),
|
||||
// Test lookup realm1 object in realm2 should not work
|
||||
((session, realm2, realm1AuthConfigId) -> {
|
||||
|
||||
AuthenticatorConfigModel config = realm2.getAuthenticatorConfigById(realm1AuthConfigId);
|
||||
Assert.assertNull(config);
|
||||
|
||||
}),
|
||||
// Try to update some object in realm1 through the realm2
|
||||
((session, realm1, realm2, realm1AuthConfigId) -> {
|
||||
|
||||
AuthenticatorConfigModel config = realm1.getAuthenticatorConfigById(realm1AuthConfigId);
|
||||
config.getConfig().put("key1", "val1");
|
||||
realm2.updateAuthenticatorConfig(config);
|
||||
|
||||
}),
|
||||
// Test update from above was not successful
|
||||
((session, realm1, realm1AuthConfigId) -> {
|
||||
|
||||
AuthenticatorConfigModel config = realm1.getAuthenticatorConfigById(realm1AuthConfigId);
|
||||
Assert.assertNull(config.getConfig().get("key1"));
|
||||
|
||||
}),
|
||||
// Try remove object from realm1 in the context of realm2
|
||||
((session, realm1, realm2, realm1AuthConfigId) -> {
|
||||
|
||||
AuthenticatorConfigModel config = realm1.getAuthenticatorConfigById(realm1AuthConfigId);
|
||||
realm2.removeAuthenticatorConfig(config);
|
||||
|
||||
}),
|
||||
// Test remove from above was not successful
|
||||
((session, realm1, realm1AuthConfigId) -> {
|
||||
|
||||
AuthenticatorConfigModel config = realm1.getAuthenticatorConfigById(realm1AuthConfigId);
|
||||
Assert.assertNotNull(config);
|
||||
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@ModelTest
|
||||
public void clientInitialAccessTest(KeycloakSession session1) {
|
||||
doTest(session1,
|
||||
// Get ID of some object from realm1
|
||||
((session, realm1) -> {
|
||||
|
||||
ClientInitialAccessModel clientInitialAccess = session.getProvider(RealmProvider.class).createClientInitialAccessModel(realm1, 10, 20);
|
||||
return clientInitialAccess.getId();
|
||||
|
||||
}),
|
||||
// Test lookup realm1 object in realm2 should not work
|
||||
((session, realm2, realm1ClientInitialAccessId) -> {
|
||||
|
||||
ClientInitialAccessModel clientInitialAccess = session.getProvider(RealmProvider.class).getClientInitialAccessModel(realm2, realm1ClientInitialAccessId);
|
||||
Assert.assertNull(clientInitialAccess);
|
||||
|
||||
}),
|
||||
// Try to update some object in realm1 through the realm2
|
||||
((session, realm1, realm2, realm1ClientInitialAccessId) -> {
|
||||
|
||||
// No-op, update not supported for clientInitialAccessModel
|
||||
|
||||
}),
|
||||
// Test update from above was not successful
|
||||
((session, realm1, realm1ClientInitialAccessId) -> {
|
||||
|
||||
// No-op, update not supported for clientInitialAccessModel
|
||||
|
||||
}),
|
||||
// Try remove object from realm1 in the context of realm2
|
||||
((session, realm1, realm2, realm1ClientInitialAccessId) -> {
|
||||
|
||||
session.getProvider(RealmProvider.class).removeClientInitialAccessModel(realm2, realm1ClientInitialAccessId);
|
||||
|
||||
}),
|
||||
// Test remove from above was not successful
|
||||
((session, realm1, realm1ClientInitialAccessId) -> {
|
||||
|
||||
ClientInitialAccessModel clientInitialAccess = session.getProvider(RealmProvider.class).getClientInitialAccessModel(realm1, realm1ClientInitialAccessId);
|
||||
Assert.assertNotNull(clientInitialAccess);
|
||||
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ModelTest
|
||||
public void rolesTest(KeycloakSession session1) {
|
||||
doTest(session1,
|
||||
// Get ID of some object from realm1
|
||||
((session, realm1) -> {
|
||||
|
||||
RoleModel role = session.getProvider(RealmProvider.class).addRealmRole(realm1, "foo");
|
||||
realm1.addDefaultRole("foo");
|
||||
return role.getId();
|
||||
|
||||
}),
|
||||
// Test lookup realm1 object in realm2 should not work
|
||||
((session, realm2, realm1RoleId) -> {
|
||||
|
||||
RoleModel role = session.getProvider(RealmProvider.class).getRoleById(realm1RoleId, realm2);
|
||||
Assert.assertNull(role);
|
||||
|
||||
}),
|
||||
// Try to update some object in realm1 through the realm2
|
||||
((session, realm1, realm2, realm1RoleId) -> {
|
||||
|
||||
// No-op, update done directly by calling operations on RoleModel. No explicit updateRole method on the RealmModel
|
||||
|
||||
}),
|
||||
// Test update from above was not successful
|
||||
((session, realm1, realm1RoleId) -> {
|
||||
|
||||
// No-op, update done directly by calling operations on RoleModel. No explicit updateRole method on the RealmModel
|
||||
|
||||
}),
|
||||
// Try remove object from realm1 in the context of realm2
|
||||
((session, realm1, realm2, realm1RoleId) -> {
|
||||
|
||||
RoleModel role = session.getProvider(RealmProvider.class).getRoleById(realm1RoleId, realm1);
|
||||
session.getProvider(RealmProvider.class).removeRole(realm2, role);
|
||||
|
||||
}),
|
||||
// Test remove from above was not successful
|
||||
((session, realm1, realm1RoleId) -> {
|
||||
|
||||
RoleModel role = session.getProvider(RealmProvider.class).getRoleById(realm1RoleId, realm1);
|
||||
Assert.assertNotNull(role);
|
||||
Assert.assertTrue(realm1.getDefaultRoles().contains("foo"));
|
||||
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ModelTest
|
||||
public void userSessionsTest(KeycloakSession session1) {
|
||||
doTest(session1,
|
||||
// Get ID of some object from realm1
|
||||
((session, realm1) -> {
|
||||
|
||||
UserModel user = session.users().getUserByUsername("test-user@localhost", realm1);
|
||||
UserSessionModel userSession = session.sessions().createUserSession(realm1, user, user.getUsername(), "1.2.3.4", "bar", false, null, null);
|
||||
return userSession.getId();
|
||||
|
||||
}),
|
||||
// Test lookup realm1 object in realm2 should not work
|
||||
((session, realm2, realm1SessionId) -> {
|
||||
|
||||
UserSessionModel userSession = session.sessions().getUserSession(realm2, realm1SessionId);
|
||||
Assert.assertNull(userSession);
|
||||
|
||||
}),
|
||||
// Try to update some object in realm1 through the realm2
|
||||
((session, realm1, realm2, realm1SessionId) -> {
|
||||
|
||||
// No-op, update done directly by calling operations on UserSessionModel. No explicit update method
|
||||
|
||||
}),
|
||||
// Test update from above was not successful
|
||||
((session, realm1, realm1SessionId) -> {
|
||||
|
||||
// No-op, update done directly by calling operations on UserSessionModel. No explicit update method.
|
||||
|
||||
}),
|
||||
// Try remove object from realm1 in the context of realm2
|
||||
((session, realm1, realm2, realm1SessionId) -> {
|
||||
|
||||
UserSessionModel userSession = session.sessions().getUserSession(realm1, realm1SessionId);
|
||||
session.sessions().removeUserSession(realm2, userSession);
|
||||
|
||||
}),
|
||||
// Test remove from above was not successful
|
||||
((session, realm1, realm1SessionId) -> {
|
||||
|
||||
UserSessionModel userSession = session.sessions().getUserSession(realm1, realm1SessionId);
|
||||
Assert.assertNotNull(userSession);
|
||||
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
private void doTest(KeycloakSession session1,
|
||||
BiFunction<KeycloakSession, RealmModel, String> realm1ObjectIdProducer,
|
||||
TriConsumer<KeycloakSession, RealmModel, String> testLookupRealm1ObjectInRealm2,
|
||||
TetraConsumer<KeycloakSession, RealmModel, RealmModel, String> updaterRealm1ObjectInRealm2,
|
||||
TriConsumer<KeycloakSession, RealmModel, String> testUpdateFailed,
|
||||
TetraConsumer<KeycloakSession, RealmModel, RealmModel, String> removeRealm1ObjectInRealm2,
|
||||
TriConsumer<KeycloakSession, RealmModel, String> testRemoveFailed
|
||||
) {
|
||||
|
||||
// Transaction 1 - Lookup object of realm1
|
||||
AtomicReference<String> realm1ObjectId = new AtomicReference<>();
|
||||
KeycloakModelUtils.runJobInTransaction(session1.getKeycloakSessionFactory(), (KeycloakSession session) -> {
|
||||
|
||||
RealmModel realm1 = session.getProvider(RealmProvider.class).getRealm("test");
|
||||
|
||||
realm1ObjectId.set(realm1ObjectIdProducer.apply(session, realm1));
|
||||
|
||||
});
|
||||
|
||||
// Transaction 2
|
||||
KeycloakModelUtils.runJobInTransaction(session1.getKeycloakSessionFactory(), (KeycloakSession session) -> {
|
||||
|
||||
RealmModel realm1 = session.getProvider(RealmProvider.class).getRealm("test");
|
||||
RealmModel realm2 = session.getProvider(RealmProvider.class).getRealm("foo");
|
||||
|
||||
testLookupRealm1ObjectInRealm2.accept(session, realm2, realm1ObjectId.get());
|
||||
updaterRealm1ObjectInRealm2.accept(session, realm1, realm2, realm1ObjectId.get());
|
||||
|
||||
});
|
||||
|
||||
// Transaction 3
|
||||
KeycloakModelUtils.runJobInTransaction(session1.getKeycloakSessionFactory(), (KeycloakSession session) -> {
|
||||
RealmModel realm1 = session.getProvider(RealmProvider.class).getRealm("test");
|
||||
|
||||
testUpdateFailed.accept(session, realm1, realm1ObjectId.get());
|
||||
});
|
||||
|
||||
// Transaction 4
|
||||
try {
|
||||
KeycloakModelUtils.runJobInTransaction(session1.getKeycloakSessionFactory(), (KeycloakSession session) -> {
|
||||
RealmModel realm1 = session.getProvider(RealmProvider.class).getRealm("test");
|
||||
RealmModel realm2 = session.getProvider(RealmProvider.class).getRealm("foo");
|
||||
removeRealm1ObjectInRealm2.accept(session, realm1, realm2, realm1ObjectId.get());
|
||||
|
||||
});
|
||||
} catch (ModelException e) {
|
||||
// This is fine. Attempt to remove on incorrect object can throw an exception in some cases, which will enforce transaction rollback
|
||||
}
|
||||
|
||||
// Transaction 5
|
||||
KeycloakModelUtils.runJobInTransaction(session1.getKeycloakSessionFactory(), (KeycloakSession session) -> {
|
||||
RealmModel realm1 = session.getProvider(RealmProvider.class).getRealm("test");
|
||||
|
||||
testRemoveFailed.accept(session, realm1, realm1ObjectId.get());
|
||||
});
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface TriConsumer<T, U, V> {
|
||||
void accept(T var1, U var2, V var3);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface TetraConsumer<T, U, V, W> {
|
||||
void accept(T var1, U var2, V var3, W var4);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue