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 b45409f9fed..35bf4375a09 100644 --- a/core/src/main/java/org/keycloak/representations/workflows/AbstractWorkflowComponentRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/workflows/AbstractWorkflowComponentRepresentation.java @@ -82,24 +82,6 @@ public abstract class AbstractWorkflowComponentRepresentation { } } - protected T getConfigValuesOrSingle(String key) { - if (config == null) { - return null; - } - - List values = config.get(key); - - if (values == null || values.isEmpty()) { - return null; - } - - if (values.size() == 1) { - return (T) values.get(0); - } - - return (T) values; - } - protected void setConfigValue(String key, Object... values) { if (values == null || values.length == 0) { return; diff --git a/core/src/main/java/org/keycloak/representations/workflows/WorkflowRepresentation.java b/core/src/main/java/org/keycloak/representations/workflows/WorkflowRepresentation.java index f0805f90476..80c19768f57 100644 --- a/core/src/main/java/org/keycloak/representations/workflows/WorkflowRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/workflows/WorkflowRepresentation.java @@ -1,11 +1,7 @@ package org.keycloak.representations.workflows; -import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; import java.util.Objects; import org.keycloak.common.util.MultivaluedHashMap; @@ -147,16 +143,10 @@ public final class WorkflowRepresentation extends AbstractWorkflowComponentRepre public static class Builder { - private final Map> steps = new HashMap<>(); - private List builders = new ArrayList<>(); private WorkflowRepresentation representation; private Builder() { - } - - private Builder(WorkflowRepresentation representation, List builders) { - this.representation = representation; - this.builders = builders; + this.representation = new WorkflowRepresentation(); } public Builder onEvent(String operation) { @@ -188,7 +178,7 @@ public final class WorkflowRepresentation extends AbstractWorkflowComponentRepre } public Builder withSteps(WorkflowStepRepresentation... steps) { - this.steps.computeIfAbsent(representation, (k) -> new ArrayList<>()).addAll(Arrays.asList(steps)); + representation.setSteps(Arrays.asList(steps)); return this; } @@ -203,30 +193,12 @@ public final class WorkflowRepresentation extends AbstractWorkflowComponentRepre } public Builder withName(String name) { - WorkflowRepresentation representation = new WorkflowRepresentation(); representation.setName(name); - Builder builder = new Builder(representation, builders); - builders.add(builder); - return builder; + return this; } - public WorkflowSetRepresentation build() { - List workflows = new ArrayList<>(); - - for (Builder builder : builders) { - if (builder.steps.isEmpty()) { - continue; - } - for (Entry> entry : builder.steps.entrySet()) { - WorkflowRepresentation workflow = entry.getKey(); - - workflow.setSteps(entry.getValue()); - - workflows.add(workflow); - } - } - - return new WorkflowSetRepresentation(workflows); + public WorkflowRepresentation build() { + return representation; } } } diff --git a/core/src/main/java/org/keycloak/representations/workflows/WorkflowSetRepresentation.java b/core/src/main/java/org/keycloak/representations/workflows/WorkflowSetRepresentation.java deleted file mode 100644 index 509d0ec82ce..00000000000 --- a/core/src/main/java/org/keycloak/representations/workflows/WorkflowSetRepresentation.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.keycloak.representations.workflows; - -import java.util.List; - -import com.fasterxml.jackson.annotation.JsonUnwrapped; - -public final class WorkflowSetRepresentation { - - @JsonUnwrapped - private List workflows; - - public WorkflowSetRepresentation() { - - } - - public WorkflowSetRepresentation(List workflows) { - this.workflows = workflows; - } - - public void setWorkflows(List workflows) { - this.workflows = workflows; - } - - public List getWorkflows() { - return workflows; - } -} diff --git a/core/src/main/java/org/keycloak/representations/workflows/WorkflowStepRepresentation.java b/core/src/main/java/org/keycloak/representations/workflows/WorkflowStepRepresentation.java index 483d3dc9ba3..b20bcd99ce6 100644 --- a/core/src/main/java/org/keycloak/representations/workflows/WorkflowStepRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/workflows/WorkflowStepRepresentation.java @@ -6,6 +6,7 @@ import java.util.Objects; import org.keycloak.common.util.MultivaluedHashMap; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; @@ -16,7 +17,7 @@ import static org.keycloak.representations.workflows.WorkflowConstants.CONFIG_PR import static org.keycloak.representations.workflows.WorkflowConstants.CONFIG_USES; import static org.keycloak.representations.workflows.WorkflowConstants.CONFIG_WITH; -@JsonPropertyOrder({"id", CONFIG_USES, CONFIG_AFTER, CONFIG_PRIORITY, CONFIG_WITH}) +@JsonPropertyOrder({CONFIG_USES, CONFIG_AFTER, CONFIG_PRIORITY, CONFIG_WITH}) @JsonInclude(JsonInclude.Include.NON_EMPTY) public final class WorkflowStepRepresentation extends AbstractWorkflowComponentRepresentation { @@ -39,6 +40,11 @@ public final class WorkflowStepRepresentation extends AbstractWorkflowComponentR this.uses = uses; } + @JsonIgnore + public String getId() { + return super.getId(); + } + public String getUses() { return this.uses; } @@ -95,11 +101,6 @@ public final class WorkflowStepRepresentation extends AbstractWorkflowComponentR return this; } - public Builder id(String id) { - step.setId(id); - return this; - } - public Builder withConfig(String key, String value) { step.setConfig(key, value); return this; diff --git a/core/src/test/java/org/keycloak/representations/workflows/WorkflowDefinitionTest.java b/core/src/test/java/org/keycloak/representations/workflows/WorkflowDefinitionTest.java index 3a9edf22f73..2c9d90e3606 100644 --- a/core/src/test/java/org/keycloak/representations/workflows/WorkflowDefinitionTest.java +++ b/core/src/test/java/org/keycloak/representations/workflows/WorkflowDefinitionTest.java @@ -32,18 +32,15 @@ public class WorkflowDefinitionTest { expected.setSteps(Arrays.asList( WorkflowStepRepresentation.create() .of("step-1") - .id("1") .withConfig("key1", "v1") .after(Duration.ofSeconds(10)) .build(), WorkflowStepRepresentation.create() .of("step-2") - .id("2") .withConfig("key1", "v1", "v2") .build(), WorkflowStepRepresentation.create() .of("step-1") - .id("3") .withConfig("key1", "v1") .build())); 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 9fa796442c1..25fb7bdc053 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 @@ -13,7 +13,6 @@ import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import org.keycloak.representations.workflows.WorkflowRepresentation; -import org.keycloak.representations.workflows.WorkflowSetRepresentation; import com.fasterxml.jackson.jakarta.rs.yaml.YAMLMediaTypes; @@ -29,11 +28,6 @@ public interface WorkflowsResource { @Consumes({MediaType.APPLICATION_JSON, YAMLMediaTypes.APPLICATION_JACKSON_YAML}) Response create(WorkflowRepresentation representation); - @Path("set") - @POST - @Consumes({MediaType.APPLICATION_JSON, YAMLMediaTypes.APPLICATION_JACKSON_YAML}) - Response create(WorkflowSetRepresentation representation); - @GET @Produces(MediaType.APPLICATION_JSON) List list(); diff --git a/js/apps/admin-ui/src/workflows/WorkflowDetailForm.tsx b/js/apps/admin-ui/src/workflows/WorkflowDetailForm.tsx index e2395898671..685ad8252c3 100644 --- a/js/apps/admin-ui/src/workflows/WorkflowDetailForm.tsx +++ b/js/apps/admin-ui/src/workflows/WorkflowDetailForm.tsx @@ -60,6 +60,7 @@ export default function WorkflowDetailForm() { } return adminClient.workflows.findOne({ id: id!, + includeId: false, }); }, (workflow) => { diff --git a/js/libs/keycloak-admin-client/src/resources/workflows.ts b/js/libs/keycloak-admin-client/src/resources/workflows.ts index ee3c6cbe528..a277d8bb5de 100644 --- a/js/libs/keycloak-admin-client/src/resources/workflows.ts +++ b/js/libs/keycloak-admin-client/src/resources/workflows.ts @@ -19,12 +19,13 @@ export class Workflows extends Resource<{ realm?: string }> { }); public findOne = this.makeRequest< - { id: string }, + { id: string; includeId: boolean }, WorkflowRepresentation | undefined >({ method: "GET", path: "/{id}", urlParamKeys: ["id"], + queryParamKeys: ["includeId"], catchNotFound: true, }); diff --git a/services/src/main/java/org/keycloak/workflow/admin/resource/WorkflowResource.java b/services/src/main/java/org/keycloak/workflow/admin/resource/WorkflowResource.java index 1ae1951e80d..6f11808ce1c 100644 --- a/services/src/main/java/org/keycloak/workflow/admin/resource/WorkflowResource.java +++ b/services/src/main/java/org/keycloak/workflow/admin/resource/WorkflowResource.java @@ -9,6 +9,7 @@ import jakarta.ws.rs.PUT; import jakarta.ws.rs.Path; import jakarta.ws.rs.PathParam; import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; @@ -20,6 +21,7 @@ import org.keycloak.representations.workflows.WorkflowRepresentation; import org.keycloak.services.ErrorResponse; import com.fasterxml.jackson.jakarta.rs.yaml.YAMLMediaTypes; +import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; public class WorkflowResource { @@ -54,8 +56,14 @@ public class WorkflowResource { @GET @Produces({MediaType.APPLICATION_JSON, YAMLMediaTypes.APPLICATION_JACKSON_YAML}) - public WorkflowRepresentation toRepresentation() { - return provider.toRepresentation(workflow); + public WorkflowRepresentation toRepresentation( + @Parameter(description = "Indicates whether the workflow id should be included in the representation or not - defaults to true") @QueryParam("includeId") Boolean includeId + ) { + WorkflowRepresentation rep = provider.toRepresentation(workflow); + if (Boolean.FALSE.equals(includeId)) { + rep.setId(null); + } + return rep; } /** diff --git a/services/src/main/java/org/keycloak/workflow/admin/resource/WorkflowsResource.java b/services/src/main/java/org/keycloak/workflow/admin/resource/WorkflowsResource.java index 944929c2d7f..0bb0f60da24 100644 --- a/services/src/main/java/org/keycloak/workflow/admin/resource/WorkflowsResource.java +++ b/services/src/main/java/org/keycloak/workflow/admin/resource/WorkflowsResource.java @@ -22,7 +22,6 @@ import org.keycloak.models.ModelException; import org.keycloak.models.workflow.Workflow; import org.keycloak.models.workflow.WorkflowProvider; import org.keycloak.representations.workflows.WorkflowRepresentation; -import org.keycloak.representations.workflows.WorkflowSetRepresentation; import org.keycloak.services.ErrorResponse; import org.keycloak.services.resources.admin.fgap.AdminPermissionEvaluator; @@ -57,18 +56,6 @@ public class WorkflowsResource { } } - @Path("set") - @POST - @Consumes({MediaType.APPLICATION_JSON, YAMLMediaTypes.APPLICATION_JACKSON_YAML}) - public Response createAll(WorkflowSetRepresentation workflows) { - auth.realm().requireManageRealm(); - - for (WorkflowRepresentation workflow : Optional.ofNullable(workflows.getWorkflows()).orElse(List.of())) { - create(workflow).close(); - } - return Response.created(session.getContext().getUri().getRequestUri()).build(); - } - @Path("{id}") public WorkflowResource get(@PathParam("id") String id) { auth.realm().requireManageRealm(); diff --git a/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/AdhocWorkflowTest.java b/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/AdhocWorkflowTest.java index e2346c48006..ff0b7fad2cd 100644 --- a/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/AdhocWorkflowTest.java +++ b/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/AdhocWorkflowTest.java @@ -54,21 +54,23 @@ public class AdhocWorkflowTest extends AbstractWorkflowTest { @Test public void testBindAdHocScheduledWithImmediateWorkflow() { - managedRealm.admin().workflows().create(WorkflowRepresentation.withName("myworkflow") + String workflowId; + try (Response response = managedRealm.admin().workflows().create(WorkflowRepresentation.withName("myworkflow") .withSteps(WorkflowStepRepresentation.create() .of(SetUserAttributeStepProviderFactory.ID) .withConfig("message", "message") .build()) - .build()).close(); + .build())) { + workflowId = ApiUtil.getCreatedId(response); + } List workflows = managedRealm.admin().workflows().list(); assertThat(workflows, hasSize(1)); - WorkflowRepresentation workflow = workflows.get(0); try (Response response = managedRealm.admin().users().create(getUserRepresentation("alice", "Alice", "Wonderland", "alice@wornderland.org"))) { String id = ApiUtil.getCreatedId(response); try { - managedRealm.admin().workflows().workflow(workflow.getId()).activate(ResourceType.USERS.name(), id, "5D"); + managedRealm.admin().workflows().workflow(workflowId).activate(ResourceType.USERS.name(), id, "5D"); } catch (Exception e) { assertThat(e, instanceOf(BadRequestException.class)); } @@ -77,40 +79,44 @@ public class AdhocWorkflowTest extends AbstractWorkflowTest { @Test public void testRunAdHocScheduledWorkflow() { - managedRealm.admin().workflows().create(WorkflowRepresentation.withName("myworkflow") + String workflowId; + try (Response response = managedRealm.admin().workflows().create(WorkflowRepresentation.withName("myworkflow") .withSteps(WorkflowStepRepresentation.create() .of(SetUserAttributeStepProviderFactory.ID) .after(Duration.ofDays(5)) .withConfig("message", "message") .build()) - .build()).close(); + .build())) { + workflowId = ApiUtil.getCreatedId(response); + } List workflows = managedRealm.admin().workflows().list(); assertThat(workflows, hasSize(1)); - WorkflowRepresentation workflow = workflows.get(0); try (Response response = managedRealm.admin().users().create(getUserRepresentation("alice", "Alice", "Wonderland", "alice@wornderland.org"))) { String id = ApiUtil.getCreatedId(response); - managedRealm.admin().workflows().workflow(workflow.getId()).activate(ResourceType.USERS.name(), id); + managedRealm.admin().workflows().workflow(workflowId).activate(ResourceType.USERS.name(), id); } } @Test public void testRunAdHocImmediateWorkflow() { - managedRealm.admin().workflows().create(WorkflowRepresentation.withName("myworkflow") + String workflowId; + try (Response response = managedRealm.admin().workflows().create(WorkflowRepresentation.withName("myworkflow") .withSteps(WorkflowStepRepresentation.create() .of(SetUserAttributeStepProviderFactory.ID) .withConfig("message", "message") .build()) - .build()).close(); + .build())) { + workflowId = ApiUtil.getCreatedId(response); + } List workflows = managedRealm.admin().workflows().list(); assertThat(workflows, hasSize(1)); - WorkflowRepresentation workflow = workflows.get(0); try (Response response = managedRealm.admin().users().create(getUserRepresentation("alice", "Alice", "Wonderland", "alice@wornderland.org"))) { String id = ApiUtil.getCreatedId(response); - managedRealm.admin().workflows().workflow(workflow.getId()).activate(ResourceType.USERS.name(), id); + managedRealm.admin().workflows().workflow(workflowId).activate(ResourceType.USERS.name(), id); } runScheduledSteps(Duration.ZERO); @@ -124,21 +130,23 @@ public class AdhocWorkflowTest extends AbstractWorkflowTest { @Test public void testRunAdHocTimedWorkflow() { - managedRealm.admin().workflows().create(WorkflowRepresentation.withName("myworkflow") + String workflowId; + try (Response response = managedRealm.admin().workflows().create(WorkflowRepresentation.withName("myworkflow") .withSteps(WorkflowStepRepresentation.create() .of(SetUserAttributeStepProviderFactory.ID) .withConfig("message", "message") .build()) - .build()).close(); + .build())) { + workflowId = ApiUtil.getCreatedId(response); + } List workflows = managedRealm.admin().workflows().list(); assertThat(workflows, hasSize(1)); - WorkflowRepresentation workflow = workflows.get(0); - String id; + String resourceId; try (Response response = managedRealm.admin().users().create(getUserRepresentation("alice", "Alice", "Wonderland", "alice@wornderland.org"))) { - id = ApiUtil.getCreatedId(response); - managedRealm.admin().workflows().workflow(workflow.getId()).activate(ResourceType.USERS.name(), id, "5D"); + resourceId = ApiUtil.getCreatedId(response); + managedRealm.admin().workflows().workflow(workflowId).activate(ResourceType.USERS.name(), resourceId, "5D"); } runScheduledSteps(Duration.ZERO); @@ -162,7 +170,7 @@ public class AdhocWorkflowTest extends AbstractWorkflowTest { })); // using seconds as the notBefore parameter just to check if this format is also working properly - managedRealm.admin().workflows().workflow(workflow.getId()).activate(ResourceType.USERS.name(), id, String.valueOf(Duration.ofDays(10).toSeconds())); + managedRealm.admin().workflows().workflow(workflowId).activate(ResourceType.USERS.name(), resourceId, String.valueOf(Duration.ofDays(10).toSeconds())); runScheduledSteps(Duration.ZERO); @@ -204,7 +212,8 @@ public class AdhocWorkflowTest extends AbstractWorkflowTest { .after(Duration.ofDays(5)) .build() ) - .withName("Two") + .build()).close(); + managedRealm.admin().workflows().create(WorkflowRepresentation.withName("Two") .onEvent(USER_ADDED.name()) .withSteps( WorkflowStepRepresentation.create() diff --git a/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/BrokeredUserSessionRefreshTimeWorkflowTest.java b/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/BrokeredUserSessionRefreshTimeWorkflowTest.java index 61ac8369227..9cc993e29a3 100644 --- a/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/BrokeredUserSessionRefreshTimeWorkflowTest.java +++ b/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/BrokeredUserSessionRefreshTimeWorkflowTest.java @@ -21,6 +21,8 @@ import java.time.Duration; import java.util.List; import java.util.Map; +import jakarta.ws.rs.core.Response; + import org.keycloak.admin.client.resource.UsersResource; import org.keycloak.models.RealmModel; import org.keycloak.models.UserModel; @@ -58,6 +60,7 @@ import org.keycloak.testframework.ui.annotations.InjectPage; import org.keycloak.testframework.ui.annotations.InjectWebDriver; import org.keycloak.testframework.ui.page.ConsentPage; import org.keycloak.testframework.ui.page.LoginPage; +import org.keycloak.testframework.util.ApiUtil; import org.awaitility.Awaitility; import org.junit.jupiter.api.Assertions; @@ -127,19 +130,22 @@ public class BrokeredUserSessionRefreshTimeWorkflowTest extends AbstractWorkflow @Test public void testInvalidateWorkflowOnIdentityProviderRemoval() { - consumerRealm.admin().workflows().create(WorkflowRepresentation.withName("myworkflow") + String workflowId; + try (Response response = consumerRealm.admin().workflows().create(WorkflowRepresentation.withName("myworkflow") .onEvent(USER_ADDED.toString(), USER_LOGGED_IN.toString()) .onCondition(IDP_CONDITION) .withSteps( WorkflowStepRepresentation.create().of(DeleteUserStepProviderFactory.ID) - .after(Duration.ofDays(1)) - .build() - ).build()).close(); + .after(Duration.ofDays(1)) + .build()) + .build())) { + workflowId = ApiUtil.getCreatedId(response); + } List workflows = consumerRealm.admin().workflows().list(); assertThat(workflows, hasSize(1)); - WorkflowRepresentation workflowRep = consumerRealm.admin().workflows().workflow(workflows.get(0).getId()).toRepresentation(); + WorkflowRepresentation workflowRep = consumerRealm.admin().workflows().workflow(workflowId).toRepresentation(); assertThat(workflowRep.getConfig().getFirst("enabled"), nullValue()); // remove IDP @@ -152,7 +158,7 @@ public class BrokeredUserSessionRefreshTimeWorkflowTest extends AbstractWorkflow .timeout(Duration.ofSeconds(30)) .pollInterval(Duration.ofSeconds(1)) .untilAsserted(() -> { - var rep = consumerRealm.admin().workflows().workflow(workflows.get(0).getId()).toRepresentation(); + var rep = consumerRealm.admin().workflows().workflow(workflowId).toRepresentation(); assertThat(rep.getEnabled(), allOf(notNullValue(), is(false))); WorkflowStateRepresentation status = rep.getState(); assertThat(status, notNullValue()); diff --git a/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/ExpressionConditionWorkflowTest.java b/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/ExpressionConditionWorkflowTest.java index 47a2f532a7c..ffac4d185f6 100644 --- a/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/ExpressionConditionWorkflowTest.java +++ b/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/ExpressionConditionWorkflowTest.java @@ -15,7 +15,6 @@ import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.RoleRepresentation; import org.keycloak.representations.userprofile.config.UPConfig; import org.keycloak.representations.workflows.WorkflowRepresentation; -import org.keycloak.representations.workflows.WorkflowSetRepresentation; import org.keycloak.representations.workflows.WorkflowStepRepresentation; import org.keycloak.testframework.annotations.KeycloakIntegrationTest; import org.keycloak.testframework.realm.GroupConfigBuilder; @@ -175,7 +174,7 @@ public class ExpressionConditionWorkflowTest extends AbstractWorkflowTest { } private String createWorkflow(String expression) { - WorkflowSetRepresentation expectedWorkflows = WorkflowRepresentation.withName("myworkflow") + WorkflowRepresentation expectedWorkflow = WorkflowRepresentation.withName("myworkflow") .onEvent("user-logged-in(test-app)") .onCondition(expression) .withSteps( @@ -188,7 +187,7 @@ public class ExpressionConditionWorkflowTest extends AbstractWorkflowTest { WorkflowsResource workflows = managedRealm.admin().workflows(); - try (Response response = workflows.create(expectedWorkflows.getWorkflows().get(0))) { + try (Response response = workflows.create(expectedWorkflow)) { assertThat(response.getStatus(), is(Response.Status.CREATED.getStatusCode())); return ApiUtil.getCreatedId(response); } diff --git a/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/GroupMembershipJoinWorkflowTest.java b/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/GroupMembershipJoinWorkflowTest.java index 2c53c8ac525..448a57929c9 100644 --- a/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/GroupMembershipJoinWorkflowTest.java +++ b/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/GroupMembershipJoinWorkflowTest.java @@ -16,7 +16,6 @@ import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.userprofile.config.UPConfig; import org.keycloak.representations.userprofile.config.UPConfig.UnmanagedAttributePolicy; import org.keycloak.representations.workflows.WorkflowRepresentation; -import org.keycloak.representations.workflows.WorkflowSetRepresentation; import org.keycloak.representations.workflows.WorkflowStateRepresentation; import org.keycloak.representations.workflows.WorkflowStepRepresentation; import org.keycloak.testframework.annotations.KeycloakIntegrationTest; @@ -57,7 +56,7 @@ public class GroupMembershipJoinWorkflowTest extends AbstractWorkflowTest { groupId = ApiUtil.getCreatedId(response); } - WorkflowSetRepresentation expectedWorkflows = WorkflowRepresentation.withName("myworkflow") + WorkflowRepresentation expectedWorkflow = WorkflowRepresentation.withName("myworkflow") .onEvent(ResourceOperationType.USER_GROUP_MEMBERSHIP_ADDED.name()) .onCondition(GROUP_CONDITION) .withSteps( @@ -70,7 +69,7 @@ public class GroupMembershipJoinWorkflowTest extends AbstractWorkflowTest { WorkflowsResource workflows = managedRealm.admin().workflows(); - try (Response response = workflows.create(expectedWorkflows)) { + try (Response response = workflows.create(expectedWorkflow)) { assertThat(response.getStatus(), is(Status.CREATED.getStatusCode())); } @@ -95,25 +94,27 @@ public class GroupMembershipJoinWorkflowTest extends AbstractWorkflowTest { @Test public void testRemoveAssociatedGroup() { String groupId; - try (Response response = managedRealm.admin().groups().add(GroupConfigBuilder.create() .name("generic-group").build())) { groupId = ApiUtil.getCreatedId(response); } - managedRealm.admin().workflows().create(WorkflowRepresentation.withName("myworkflow") + String workflowId; + try (Response response = managedRealm.admin().workflows().create(WorkflowRepresentation.withName("myworkflow") .onEvent(USER_ADDED.toString(), USER_LOGGED_IN.toString()) .onCondition(GROUP_CONDITION) .withSteps( WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID) .after(Duration.ofDays(1)) - .build() - ).build()).close(); + .build()) + .build())) { + workflowId = ApiUtil.getCreatedId(response); + } List workflows = managedRealm.admin().workflows().list(); assertThat(workflows, hasSize(1)); - WorkflowRepresentation workflowRep = managedRealm.admin().workflows().workflow(workflows.get(0).getId()).toRepresentation(); + WorkflowRepresentation workflowRep = managedRealm.admin().workflows().workflow(workflowId).toRepresentation(); assertThat(workflowRep.getConfig().getFirst("enabled"), nullValue()); // remove group @@ -126,7 +127,7 @@ public class GroupMembershipJoinWorkflowTest extends AbstractWorkflowTest { .timeout(Duration.ofSeconds(30)) .pollInterval(Duration.ofSeconds(1)) .untilAsserted(() -> { - var rep = managedRealm.admin().workflows().workflow(workflows.get(0).getId()).toRepresentation(); + var rep = managedRealm.admin().workflows().workflow(workflowId).toRepresentation(); assertThat(rep.getEnabled(), allOf(notNullValue(), is(false))); WorkflowStateRepresentation status = rep.getState(); assertThat(status, notNullValue()); diff --git a/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/RoleWorkflowConditionTest.java b/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/RoleWorkflowConditionTest.java index 54d07b1700e..49c47d8a63f 100644 --- a/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/RoleWorkflowConditionTest.java +++ b/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/RoleWorkflowConditionTest.java @@ -19,7 +19,6 @@ import org.keycloak.representations.idm.RoleRepresentation; import org.keycloak.representations.userprofile.config.UPConfig; import org.keycloak.representations.userprofile.config.UPConfig.UnmanagedAttributePolicy; import org.keycloak.representations.workflows.WorkflowRepresentation; -import org.keycloak.representations.workflows.WorkflowSetRepresentation; import org.keycloak.representations.workflows.WorkflowStepRepresentation; import org.keycloak.testframework.annotations.KeycloakIntegrationTest; import org.keycloak.testframework.realm.RoleConfigBuilder; @@ -114,7 +113,7 @@ public class RoleWorkflowConditionTest extends AbstractWorkflowTest { .map(role -> RoleWorkflowConditionFactory.ID + "(" + role + ")") .reduce((a, b) -> a + " AND " + b).orElse(null); - WorkflowSetRepresentation expectedWorkflows = WorkflowRepresentation.withName("myworkflow") + WorkflowRepresentation expectedWorkflow = WorkflowRepresentation.withName("myworkflow") .onEvent(ResourceOperationType.USER_ROLE_ADDED.name()) .onCondition(roleCondition) .withSteps( @@ -130,7 +129,7 @@ public class RoleWorkflowConditionTest extends AbstractWorkflowTest { WorkflowsResource workflows = managedRealm.admin().workflows(); - try (Response response = workflows.create(expectedWorkflows)) { + try (Response response = workflows.create(expectedWorkflow)) { assertThat(response.getStatus(), is(Status.CREATED.getStatusCode())); } } diff --git a/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/UserAttributeWorkflowConditionTest.java b/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/UserAttributeWorkflowConditionTest.java index 0ca37bdccea..bec72074ac1 100644 --- a/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/UserAttributeWorkflowConditionTest.java +++ b/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/UserAttributeWorkflowConditionTest.java @@ -18,7 +18,6 @@ import org.keycloak.models.workflow.conditions.UserAttributeWorkflowConditionFac import org.keycloak.representations.userprofile.config.UPConfig; import org.keycloak.representations.userprofile.config.UPConfig.UnmanagedAttributePolicy; import org.keycloak.representations.workflows.WorkflowRepresentation; -import org.keycloak.representations.workflows.WorkflowSetRepresentation; import org.keycloak.representations.workflows.WorkflowStepRepresentation; import org.keycloak.testframework.annotations.KeycloakIntegrationTest; import org.keycloak.testframework.realm.UserConfigBuilder; @@ -117,7 +116,7 @@ public class UserAttributeWorkflowConditionTest extends AbstractWorkflowTest { .reduce((a, b) -> a + " AND " + b) .orElse(null); - WorkflowSetRepresentation expectedWorkflows = WorkflowRepresentation.withName("myworkflow") + WorkflowRepresentation expectedWorkflow = WorkflowRepresentation.withName("myworkflow") .onEvent(ResourceOperationType.USER_ADDED.name()) .onCondition(attributeCondition) .withSteps( @@ -133,7 +132,7 @@ public class UserAttributeWorkflowConditionTest extends AbstractWorkflowTest { WorkflowsResource workflows = managedRealm.admin().workflows(); - try (Response response = workflows.create(expectedWorkflows)) { + try (Response response = workflows.create(expectedWorkflow)) { assertThat(response.getStatus(), is(Status.CREATED.getStatusCode())); } } diff --git a/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/UserSessionRefreshTimeWorkflowTest.java b/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/UserSessionRefreshTimeWorkflowTest.java index b688374982d..3a4f43aff85 100644 --- a/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/UserSessionRefreshTimeWorkflowTest.java +++ b/tests/base/src/test/java/org/keycloak/tests/admin/model/workflow/UserSessionRefreshTimeWorkflowTest.java @@ -143,9 +143,9 @@ public class UserSessionRefreshTimeWorkflowTest extends AbstractWorkflowTest { .after(Duration.ofDays(5)) .withConfig("custom_subject_key", "notifier1_subject") .withConfig("custom_message", "notifier1_message") - .build() - ) - .withName("myworkflow_2") + .build()) + .build()).close(); + managedRealm.admin().workflows().create(WorkflowRepresentation.withName("myworkflow_2") .onEvent(USER_ADDED.toString(), USER_LOGGED_IN.toString()) .withSteps( WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID) 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 95b1b72a9fe..db768ace2e5 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 @@ -53,7 +53,6 @@ import org.keycloak.models.workflow.conditions.IdentityProviderWorkflowCondition import org.keycloak.representations.idm.ErrorRepresentation; import org.keycloak.representations.idm.IdentityProviderRepresentation; import org.keycloak.representations.workflows.WorkflowRepresentation; -import org.keycloak.representations.workflows.WorkflowSetRepresentation; import org.keycloak.representations.workflows.WorkflowStepRepresentation; import org.keycloak.testframework.annotations.InjectAdminClient; import org.keycloak.testframework.annotations.InjectKeycloakUrls; @@ -63,6 +62,7 @@ import org.keycloak.testframework.mail.annotations.InjectMailServer; import org.keycloak.testframework.realm.UserConfigBuilder; import org.keycloak.testframework.remote.providers.runonserver.RunOnServer; import org.keycloak.testframework.server.KeycloakUrls; +import org.keycloak.testframework.util.ApiUtil; import org.keycloak.tests.utils.MailUtils; import com.fasterxml.jackson.annotation.JsonInclude.Include; @@ -101,7 +101,7 @@ public class WorkflowManagementTest extends AbstractWorkflowTest { @Test public void testCreate() { - WorkflowSetRepresentation expectedWorkflows = WorkflowRepresentation.withName("myworkflow") + WorkflowRepresentation expectedWorkflow = WorkflowRepresentation.withName("myworkflow") .onEvent(USER_ADDED.name()) .withSteps( WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID) @@ -114,7 +114,7 @@ public class WorkflowManagementTest extends AbstractWorkflowTest { WorkflowsResource workflows = managedRealm.admin().workflows(); - try (Response response = workflows.create(expectedWorkflows)) { + try (Response response = workflows.create(expectedWorkflow)) { assertThat(response.getStatus(), is(Response.Status.CREATED.getStatusCode())); } @@ -129,7 +129,7 @@ public class WorkflowManagementTest extends AbstractWorkflowTest { @Test public void testCreateWithNoConditions() { - WorkflowSetRepresentation expectedWorkflows = WorkflowRepresentation.withName("myworkflow") + WorkflowRepresentation expectedWorkflow = WorkflowRepresentation.withName("myworkflow") .withSteps( WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID) .after(Duration.ofDays(5)) @@ -139,16 +139,16 @@ public class WorkflowManagementTest extends AbstractWorkflowTest { .build() ).build(); - expectedWorkflows.getWorkflows().get(0).setConditions(null); + expectedWorkflow.setConditions(null); - try (Response response = managedRealm.admin().workflows().create(expectedWorkflows)) { + try (Response response = managedRealm.admin().workflows().create(expectedWorkflow)) { assertThat(response.getStatus(), is(Response.Status.CREATED.getStatusCode())); } } @Test public void testCreateWithNoWorkflowSetDefaultWorkflow() { - WorkflowSetRepresentation expectedWorkflows = WorkflowRepresentation.withName("default-workflow") + WorkflowRepresentation expectedWorkflow = WorkflowRepresentation.withName("default-workflow") .withSteps( WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID) .after(Duration.ofDays(5)) @@ -158,9 +158,9 @@ public class WorkflowManagementTest extends AbstractWorkflowTest { .build() ).build(); - expectedWorkflows.getWorkflows().get(0).setConditions(null); + expectedWorkflow.setConditions(null); - try (Response response = managedRealm.admin().workflows().create(expectedWorkflows)) { + try (Response response = managedRealm.admin().workflows().create(expectedWorkflow)) { assertThat(response.getStatus(), is(Response.Status.CREATED.getStatusCode())); } @@ -171,16 +171,20 @@ public class WorkflowManagementTest extends AbstractWorkflowTest { public void testDelete() { WorkflowsResource workflows = managedRealm.admin().workflows(); - workflows.create(WorkflowRepresentation.withName("myworkflow") + String workflowId; + try (Response response = workflows.create(WorkflowRepresentation.withName("myworkflow") .onEvent(ResourceOperationType.USER_ADDED.toString()) .withSteps( WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID) .after(Duration.ofDays(5)) .build(), WorkflowStepRepresentation.create().of(RestartWorkflowStepProviderFactory.ID) - .build() - ) - .withName("another-workflow") + .build()) + .build())) { + workflowId = ApiUtil.getCreatedId(response); + } + + workflows.create(WorkflowRepresentation.withName("another-workflow") .onEvent(ResourceOperationType.USER_LOGGED_IN.toString()) .withSteps( WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID) @@ -196,10 +200,7 @@ public class WorkflowManagementTest extends AbstractWorkflowTest { List actualWorkflows = workflows.list(); assertThat(actualWorkflows, Matchers.hasSize(2)); - WorkflowRepresentation workflow = actualWorkflows.stream().filter(p -> "myworkflow".equals(p.getName())).findAny().orElse(null); - assertThat(workflow, notNullValue()); - String id = workflow.getId(); - workflows.workflow(id).delete().close(); + workflows.workflow(workflowId).delete().close(); actualWorkflows = workflows.list(); assertThat(actualWorkflows, Matchers.hasSize(1)); @@ -209,14 +210,14 @@ public class WorkflowManagementTest extends AbstractWorkflowTest { List registeredWorkflows = provider.getWorkflows().toList(); assertEquals(1, registeredWorkflows.size()); WorkflowStateProvider stateProvider = session.getKeycloakSessionFactory().getProviderFactory(WorkflowStateProvider.class).create(session); - List steps = stateProvider.getScheduledStepsByWorkflow(id); + List steps = stateProvider.getScheduledStepsByWorkflow(workflowId); assertTrue(steps.isEmpty()); }); } @Test public void testUpdate() { - WorkflowSetRepresentation expectedWorkflows = WorkflowRepresentation.withName("test-workflow") + WorkflowRepresentation workflowRep = WorkflowRepresentation.withName("test-workflow") .withSteps( WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID) .after(Duration.ofDays(5)) @@ -228,8 +229,10 @@ public class WorkflowManagementTest extends AbstractWorkflowTest { WorkflowsResource workflows = managedRealm.admin().workflows(); - try (Response response = workflows.create(expectedWorkflows)) { + String workflowId; + try (Response response = workflows.create(workflowRep)) { assertThat(response.getStatus(), is(Response.Status.CREATED.getStatusCode())); + workflowId = ApiUtil.getCreatedId(response); } List actualWorkflows = workflows.list(); @@ -238,7 +241,7 @@ public class WorkflowManagementTest extends AbstractWorkflowTest { assertThat(workflow.getName(), is("test-workflow")); workflow.setName("changed"); - managedRealm.admin().workflows().workflow(workflow.getId()).update(workflow).close(); + managedRealm.admin().workflows().workflow(workflowId).update(workflow).close(); actualWorkflows = workflows.list(); workflow = actualWorkflows.get(0); assertThat(workflow.getName(), is("changed")); @@ -246,21 +249,21 @@ public class WorkflowManagementTest extends AbstractWorkflowTest { // now let's try to update another property that we can't update String previousOn = workflow.getOn(); workflow.setOn(ResourceOperationType.USER_LOGGED_IN.toString()); - try (Response response = workflows.workflow(workflow.getId()).update(workflow)) { + try (Response response = workflows.workflow(workflowId).update(workflow)) { assertThat(response.getStatus(), is(Response.Status.BAD_REQUEST.getStatusCode())); } // restore previous value, but change the conditions workflow.setOn(previousOn); workflow.setConditions(IdentityProviderWorkflowConditionFactory.ID + "(someidp)"); - try (Response response = workflows.workflow(workflow.getId()).update(workflow)) { + try (Response response = workflows.workflow(workflowId).update(workflow)) { assertThat(response.getStatus(), is(Response.Status.BAD_REQUEST.getStatusCode())); } // revert conditions, but change one of the steps workflow.setConditions(null); - workflow.getSteps().get(0).setAfter("8D"); // 8 days - try (Response response = workflows.workflow(workflow.getId()).update(workflow)) { + workflow.getSteps().get(0).setAfter("8D"); + try (Response response = workflows.workflow(workflowId).update(workflow)) { assertThat(response.getStatus(), is(Response.Status.BAD_REQUEST.getStatusCode())); } @@ -510,7 +513,8 @@ public class WorkflowManagementTest extends AbstractWorkflowTest { @Test public void testDisableWorkflow() { // create a test workflow - managedRealm.admin().workflows().create(WorkflowRepresentation.withName("test-workflow") + String workflowId; + try (Response response = managedRealm.admin().workflows().create(WorkflowRepresentation.withName("test-workflow") .onEvent(ResourceOperationType.USER_ADDED.toString()) .withSteps( WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID) @@ -519,7 +523,9 @@ public class WorkflowManagementTest extends AbstractWorkflowTest { WorkflowStepRepresentation.create().of(DisableUserStepProviderFactory.ID) .after(Duration.ofDays(5)) .build() - ).build()).close(); + ).build())) { + workflowId = ApiUtil.getCreatedId(response); + } WorkflowsResource workflows = managedRealm.admin().workflows(); List actualWorkflows = workflows.list(); @@ -547,7 +553,7 @@ public class WorkflowManagementTest extends AbstractWorkflowTest { // disable the workflow - scheduled steps should be paused and workflow should not activate for new users workflow.setEnabled(false); - managedRealm.admin().workflows().workflow(workflow.getId()).update(workflow).close(); + managedRealm.admin().workflows().workflow(workflowId).update(workflow).close(); // create another user - should NOT bind the user to the workflow as it is disabled managedRealm.admin().users().create(UserConfigBuilder.create().username("anotheruser").build()).close(); @@ -577,7 +583,7 @@ public class WorkflowManagementTest extends AbstractWorkflowTest { // re-enable the workflow - scheduled steps should resume and new users should be bound to the workflow workflow.getConfig().putSingle("enabled", "true"); - managedRealm.admin().workflows().workflow(workflow.getId()).update(workflow).close(); + managedRealm.admin().workflows().workflow(workflowId).update(workflow).close(); // create a third user - should bind the user to the workflow as it is enabled again managedRealm.admin().users().create(UserConfigBuilder.create().username("thirduser").email("thirduser@example.com").build()).close(); @@ -671,7 +677,7 @@ public class WorkflowManagementTest extends AbstractWorkflowTest { @Test public void testFailCreateWorkflowWithNegativeTime() { - WorkflowSetRepresentation workflows = WorkflowRepresentation.withName("myworkflow") + WorkflowRepresentation workflow = WorkflowRepresentation.withName("myworkflow") .onEvent(USER_ADDED.name()) .withSteps( WorkflowStepRepresentation.create().of(SetUserAttributeStepProviderFactory.ID) @@ -679,7 +685,7 @@ public class WorkflowManagementTest extends AbstractWorkflowTest { .withConfig("key", "value") .build()) .build(); - try (Response response = managedRealm.admin().workflows().create(workflows)) { + try (Response response = managedRealm.admin().workflows().create(workflow)) { assertThat(response.getStatus(), is(Response.Status.BAD_REQUEST.getStatusCode())); assertThat(response.readEntity(ErrorRepresentation.class).getErrorMessage(), equalTo("Step 'after' configuration cannot be negative.")); } @@ -861,7 +867,7 @@ public class WorkflowManagementTest extends AbstractWorkflowTest { WorkflowStepRepresentation.create().of(DisableUserStepProviderFactory.ID) .after(Duration.ofDays(5)) .build() - ).build().getWorkflows().get(0); + ).build(); try (Client httpClient = Keycloak.getClientProvider().newRestEasyClient(null, null, true)) { httpClient.register(JacksonYAMLProvider.class); @@ -872,9 +878,11 @@ public class WorkflowManagementTest extends AbstractWorkflowTest { .path("workflows") .register(new BearerAuthFilter(adminClient.tokenManager())); + String workflowId; try (Response response = workflowsApi.request().post(Entity.entity(yamlMapper.writeValueAsString(expected), YAMLMediaTypes.APPLICATION_JACKSON_YAML))) { assertEquals(Status.CREATED.getStatusCode(), response.getStatus()); + workflowId = ApiUtil.getCreatedId(response); } try (Response response = workflowsApi.request().accept(YAMLMediaTypes.APPLICATION_JACKSON_YAML).get()) { @@ -886,15 +894,14 @@ public class WorkflowManagementTest extends AbstractWorkflowTest { expected = workflows.get(0); } - try (Response response = workflowsApi.path(expected.getId()).request() + try (Response response = workflowsApi.path(workflowId).request() .accept(YAMLMediaTypes.APPLICATION_JACKSON_YAML).get()) { assertEquals(Status.OK.getStatusCode(), response.getStatus()); WorkflowRepresentation actual = yamlMapper.readValue(response.readEntity(String.class), WorkflowRepresentation.class); - assertEquals(expected.getId(), actual.getId()); assertEquals(expected.getName(), actual.getName()); } - try (Response response = workflowsApi.path(expected.getId()).request() + try (Response response = workflowsApi.path(workflowId).request() .put(Entity.entity(yamlMapper.writeValueAsString(expected), YAMLMediaTypes.APPLICATION_JACKSON_YAML))) { assertEquals(Status.NO_CONTENT.getStatusCode(), response.getStatus()); }