Details
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 f517782..4167ebc 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<RealmEntity> {
@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<RealmEntity> {
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<ClientTemplateEntity> 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 b5d6d7c..6fff8d5 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<MongoRealmEntity> 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<MongoRealmEntity> 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 f75bf11..98ac227 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 24161a2..595dccd 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());