From 4d912a9c21c13bc020da17dba1d1c6263cb0259b Mon Sep 17 00:00:00 2001 From: vramik Date: Thu, 30 Oct 2025 21:02:56 +0100 Subject: [PATCH] Support for YAML payloads for Admin client for creation of workflows Closes #43666 Signed-off-by: vramik --- ...stractWorkflowComponentRepresentation.java | 6 +++ integration/admin-client/pom.xml | 4 ++ .../client/resource/WorkflowsResource.java | 5 ++- .../workflow/WorkflowManagementTest.java | 44 ++++++++++++++----- 4 files changed, 45 insertions(+), 14 deletions(-) diff --git a/core/src/main/java/org/keycloak/representations/workflows/AbstractWorkflowComponentRepresentation.java b/core/src/main/java/org/keycloak/representations/workflows/AbstractWorkflowComponentRepresentation.java index c4da2940c0b..bf4df356c21 100644 --- a/core/src/main/java/org/keycloak/representations/workflows/AbstractWorkflowComponentRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/workflows/AbstractWorkflowComponentRepresentation.java @@ -124,6 +124,9 @@ public abstract class AbstractWorkflowComponentRepresentation { } protected void setConfigValue(String key, List values) { + if (values == null) { + return; + } if (this.config == null) { this.config = new MultivaluedHashMap<>(); } @@ -131,6 +134,9 @@ public abstract class AbstractWorkflowComponentRepresentation { } protected void addConfigValue(String key, String value) { + if (value == null) { + return; + } if (this.config == null) { this.config = new MultivaluedHashMap<>(); } diff --git a/integration/admin-client/pom.xml b/integration/admin-client/pom.xml index b818b72628e..f0a1f69c641 100755 --- a/integration/admin-client/pom.xml +++ b/integration/admin-client/pom.xml @@ -79,6 +79,10 @@ resteasy-jaxb-provider ${resteasy.version} + + com.fasterxml.jackson.jakarta.rs + jackson-jakarta-rs-yaml-provider + diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/WorkflowsResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/WorkflowsResource.java index 4e9c7934ed3..5eaba3a1320 100644 --- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/WorkflowsResource.java +++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/WorkflowsResource.java @@ -2,6 +2,7 @@ package org.keycloak.admin.client.resource; import java.util.List; +import com.fasterxml.jackson.jakarta.rs.yaml.YAMLMediaTypes; import jakarta.ws.rs.Consumes; import jakarta.ws.rs.GET; import jakarta.ws.rs.POST; @@ -22,12 +23,12 @@ import org.keycloak.representations.workflows.WorkflowSetRepresentation; public interface WorkflowsResource { @POST - @Consumes(MediaType.APPLICATION_JSON) + @Consumes({MediaType.APPLICATION_JSON, YAMLMediaTypes.APPLICATION_JACKSON_YAML}) Response create(WorkflowRepresentation representation); @Path("set") @POST - @Consumes(MediaType.APPLICATION_JSON) + @Consumes({MediaType.APPLICATION_JSON, YAMLMediaTypes.APPLICATION_JACKSON_YAML}) Response create(WorkflowSetRepresentation representation); @GET diff --git a/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/WorkflowManagementTest.java b/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/WorkflowManagementTest.java index dea907eb45a..a201cc7fd86 100644 --- a/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/WorkflowManagementTest.java +++ b/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/WorkflowManagementTest.java @@ -33,6 +33,8 @@ import java.util.Arrays; import java.util.List; import java.util.UUID; +import com.fasterxml.jackson.jakarta.rs.yaml.JacksonYAMLProvider; +import com.fasterxml.jackson.jakarta.rs.yaml.YAMLMediaTypes; import jakarta.ws.rs.client.Client; import jakarta.ws.rs.client.Entity; import jakarta.ws.rs.client.WebTarget; @@ -86,7 +88,6 @@ import org.keycloak.testframework.remote.runonserver.InjectRunOnServer; import org.keycloak.testframework.remote.runonserver.RunOnServerClient; import org.keycloak.testframework.server.KeycloakUrls; import org.keycloak.tests.utils.MailUtils; -import org.keycloak.util.JsonSerialization; @KeycloakIntegrationTest(config = WorkflowsServerConfig.class) public class WorkflowManagementTest { @@ -884,9 +885,10 @@ public class WorkflowManagementTest { } @Test - public void testCreateUsingYaml() throws IOException { + public void testCreateWorkflowsUsingYaml() throws IOException { WorkflowSetRepresentation expectedWorkflows = WorkflowRepresentation.create() .of(UserCreationTimeWorkflowProviderFactory.ID) + .name(UserCreationTimeWorkflowProviderFactory.ID) .withSteps( WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID) .after(Duration.ofDays(5)) @@ -896,17 +898,35 @@ public class WorkflowManagementTest { .build() ).build(); - Client httpClient = Keycloak.getClientProvider().newRestEasyClient(null, null, true); - WebTarget target = httpClient.target(keycloakUrls.getBaseUrl().toString()) - .path("admin") - .path("realms") - .path(managedRealm.getName()) - .path("workflows") - .path("set") - .register(new BearerAuthFilter(adminClient.tokenManager())); + try (Client httpClient = Keycloak.getClientProvider().newRestEasyClient(null, null, true)) { + httpClient.register(JacksonYAMLProvider.class); + // multiple workflows + WebTarget target = httpClient.target(keycloakUrls.getBaseUrl().toString()) + .path("admin") + .path("realms") + .path(managedRealm.getName()) + .path("workflows") + .path("set") + .register(new BearerAuthFilter(adminClient.tokenManager())); - Response response = target.request().post(Entity.entity(JsonSerialization.writeValueAsString(expectedWorkflows), "application/yaml")); - response.close(); + Entity entitySet = Entity.entity(expectedWorkflows, YAMLMediaTypes.APPLICATION_JACKSON_YAML_TYPE); + try (Response response = target.request().post(entitySet)) { + assertThat(response.getStatus(), is(Response.Status.CREATED.getStatusCode())); + } + + // single workflow + target = httpClient.target(keycloakUrls.getBaseUrl().toString()) + .path("admin") + .path("realms") + .path(managedRealm.getName()) + .path("workflows") + .register(new BearerAuthFilter(adminClient.tokenManager())); + + Entity entity = Entity.entity(expectedWorkflows.getWorkflows().get(0), YAMLMediaTypes.APPLICATION_JACKSON_YAML_TYPE); + try (Response response = target.request().post(entity)) { + assertThat(response.getStatus(), is(Response.Status.CREATED.getStatusCode())); + } + } } public static List findEmailsByRecipient(MailServer mailServer, String expectedRecipient) {