diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplateResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplateResource.java
index 768bf1a..49580b1 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplateResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplateResource.java
@@ -22,6 +22,7 @@ import org.keycloak.events.admin.OperationType;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.ModelException;
import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.models.utils.RepresentationToModel;
@@ -133,11 +134,16 @@ public class ClientTemplateResource {
*/
@DELETE
@NoCache
- public void deleteClientTemplate() {
+ public Response deleteClientTemplate() {
auth.requireManage();
- realm.removeClientTemplate(template.getId());
- adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
+ try {
+ realm.removeClientTemplate(template.getId());
+ adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
+ return Response.noContent().build();
+ } catch (ModelException me) {
+ return ErrorResponse.error(me.getMessage(), Response.Status.BAD_REQUEST);
+ }
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/ClientTemplateTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/ClientTemplateTest.java
index 25e287d..85f05e2 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/ClientTemplateTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/ClientTemplateTest.java
@@ -23,6 +23,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import javax.ws.rs.BadRequestException;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.core.Response;
@@ -35,6 +36,7 @@ import org.keycloak.models.AccountRoles;
import org.keycloak.models.Constants;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.protocol.saml.SamlProtocol;
+import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.ClientTemplateRepresentation;
import org.keycloak.representations.idm.ErrorRepresentation;
import org.keycloak.representations.idm.MappingsRepresentation;
@@ -270,6 +272,40 @@ public class ClientTemplateTest extends AbstractClientTest {
}
+ // KEYCLOAK-2844
+ @Test
+ public void testRemoveTemplateInUse() {
+ // Add client template
+ ClientTemplateRepresentation templateRep = new ClientTemplateRepresentation();
+ templateRep.setName("foo-template");
+ templateRep.setFullScopeAllowed(false);
+ String templateId = createTemplate(templateRep);
+
+ // Add client with the clientTemplate
+ ClientRepresentation clientRep = new ClientRepresentation();
+ clientRep.setClientId("bar-client");
+ clientRep.setName("bar-client");
+ clientRep.setRootUrl("foo");
+ clientRep.setProtocol("openid-connect");
+ clientRep.setClientTemplate("foo-template");
+ String clientDbId = createClient(clientRep);
+
+ // Can't remove clientTemplate
+ try {
+ clientTemplates().get(templateId).remove();
+ } catch (BadRequestException bre) {
+ ErrorRepresentation error = bre.getResponse().readEntity(ErrorRepresentation.class);
+ Assert.assertEquals("Cannot remove client template, it is currently in use", error.getErrorMessage());
+ }
+
+ // Remove client
+ testRealmResource().clients().get(clientDbId).remove();
+
+ // Can remove clientTemplate now
+ clientTemplates().get(templateId).remove();
+ }
+
+
private ClientTemplatesResource clientTemplates() {
return testRealmResource().clientTemplates();
}