From 4d5ae5dd68395ba0cdc257ab2083ad355b2858bc Mon Sep 17 00:00:00 2001 From: Bill Burke Date: Fri, 1 Apr 2016 14:50:26 -0400 Subject: [PATCH] KEYCLOAK-2512 --- .../org/keycloak/models/jpa/RealmAdapter.java | 9 ++++- .../mongo/keycloak/adapters/RealmAdapter.java | 7 ++++ .../models/utils/KeycloakModelUtils.java | 35 +++++++++++++++++++ .../testsuite/model/ClientModelTest.java | 20 +++++++++++ 4 files changed, 70 insertions(+), 1 deletion(-) diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java index f517782360..4167ebc1a0 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java @@ -30,6 +30,7 @@ import org.keycloak.models.IdentityProviderMapperModel; import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.ModelDuplicateException; +import org.keycloak.models.ModelException; import org.keycloak.models.OTPPolicy; import org.keycloak.models.PasswordPolicy; import org.keycloak.models.RealmModel; @@ -1716,8 +1717,11 @@ public class RealmAdapter implements RealmModel, JpaModel { @Override public void removeAuthenticationFlow(AuthenticationFlowModel model) { + 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()); - if (entity == null) return; + em.remove(entity); em.flush(); } @@ -2063,6 +2067,9 @@ public class RealmAdapter implements RealmModel, JpaModel { if (id == null) return false; ClientTemplateModel client = getClientTemplateById(id); if (client == null) return false; + if (KeycloakModelUtils.isClientTemplateUsed(this, client)) { + throw new ModelException("Cannot remove client template, it is currently in use"); + } ClientTemplateEntity clientEntity = null; Iterator it = realm.getClientTemplates().iterator(); diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java index b5d6d7ccac..6fff8d5815 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java @@ -32,6 +32,7 @@ import org.keycloak.models.IdentityProviderMapperModel; import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.ModelDuplicateException; +import org.keycloak.models.ModelException; import org.keycloak.models.OTPPolicy; import org.keycloak.models.PasswordPolicy; import org.keycloak.models.RealmModel; @@ -1558,6 +1559,9 @@ public class RealmAdapter extends AbstractMongoAdapter impleme @Override public void removeAuthenticationFlow(AuthenticationFlowModel model) { + if (KeycloakModelUtils.isFlowUsed(this, model)) { + throw new ModelException("Cannot remove authentication flow, it is currently in use"); + } AuthenticationFlowEntity toDelete = getFlowEntity(model.getId()); if (toDelete == null) return; getMongoEntity().getAuthenticationFlows().remove(toDelete); @@ -2032,6 +2036,9 @@ public class RealmAdapter extends AbstractMongoAdapter impleme ClientTemplateModel client = getClientTemplateById(id); if (client == null) return false; + if (KeycloakModelUtils.isClientTemplateUsed(this, client)) { + throw new ModelException("Cannot remove client template, it is currently in use"); + } return getMongoStore().removeEntity(MongoClientTemplateEntity.class, id, invocationContext); } diff --git a/server-spi/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java b/server-spi/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java index f75bf11027..98ac227123 100755 --- a/server-spi/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java +++ b/server-spi/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java @@ -22,8 +22,10 @@ import org.keycloak.common.util.Base64Url; import org.keycloak.models.AuthenticationExecutionModel; import org.keycloak.models.AuthenticationFlowModel; import org.keycloak.models.ClientModel; +import org.keycloak.models.ClientTemplateModel; import org.keycloak.models.Constants; import org.keycloak.models.GroupModel; +import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.KeycloakSessionTask; @@ -598,4 +600,37 @@ public final class KeycloakModelUtils { } } + /** + * Check to see if a flow is currently in use + * + * @param realm + * @param model + * @return + */ + public static boolean isFlowUsed(RealmModel realm, AuthenticationFlowModel model) { + AuthenticationFlowModel realmFlow = null; + + if ((realmFlow = realm.getBrowserFlow()) != null && realmFlow.getId().equals(model.getId())) return true; + if ((realmFlow = realm.getRegistrationFlow()) != null && realmFlow.getId().equals(model.getId())) return true; + if ((realmFlow = realm.getClientAuthenticationFlow()) != null && realmFlow.getId().equals(model.getId())) return true; + if ((realmFlow = realm.getDirectGrantFlow()) != null && realmFlow.getId().equals(model.getId())) return true; + if ((realmFlow = realm.getResetCredentialsFlow()) != null && realmFlow.getId().equals(model.getId())) return true; + + for (IdentityProviderModel idp : realm.getIdentityProviders()) { + if (model.getId().equals(idp.getFirstBrokerLoginFlowId())) return true; + if (model.getId().equals(idp.getPostBrokerLoginFlowId())) return true; + } + + return false; + + } + + public static boolean isClientTemplateUsed(RealmModel realm, ClientTemplateModel template) { + for (ClientModel client : realm.getClients()) { + if (client.getClientTemplate() != null && client.getClientTemplate().getId().equals(template.getId())) return true; + } + return false; + } + + } diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java index 24161a2b08..595dccd777 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java @@ -21,6 +21,8 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.keycloak.models.ClientModel; +import org.keycloak.models.ClientTemplateModel; +import org.keycloak.models.ModelException; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.utils.ModelToRepresentation; @@ -101,6 +103,24 @@ public class ClientModelTest extends AbstractModelTest { Assert.assertNotNull(client); } + @Test + public void testCannotRemoveBoundClientTemplate() { + ClientModel client = realm.addClient("templatized"); + ClientTemplateModel template = realm.addClientTemplate("template"); + client.setClientTemplate(template); + commit(); + realm = realmManager.getRealmByName("original"); + try { + realm.removeClientTemplate(template.getId()); + Assert.fail(); + } catch (ModelException e) { + + } + realm.removeClient(client.getId()); + realm.removeClientTemplate(template.getId()); + commit(); + } + public static void assertEquals(ClientModel expected, ClientModel actual) { Assert.assertEquals(expected.getClientId(), actual.getClientId());