Add optional parameter in WorkflowResource.toRepresentation to allow retrieval of the rep without the ids

Closes #44183

Signed-off-by: Stefan Guilhen <sguilhen@redhat.com>
This commit is contained in:
Stefan Guilhen
2025-11-12 18:51:53 -03:00
committed by Pedro Igor
parent 70e1dba2c3
commit 3319e8d9b5
18 changed files with 127 additions and 191 deletions

View File

@@ -82,24 +82,6 @@ public abstract class AbstractWorkflowComponentRepresentation {
} }
} }
protected <T> T getConfigValuesOrSingle(String key) {
if (config == null) {
return null;
}
List<String> 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) { protected void setConfigValue(String key, Object... values) {
if (values == null || values.length == 0) { if (values == null || values.length == 0) {
return; return;

View File

@@ -1,11 +1,7 @@
package org.keycloak.representations.workflows; package org.keycloak.representations.workflows;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects; import java.util.Objects;
import org.keycloak.common.util.MultivaluedHashMap; import org.keycloak.common.util.MultivaluedHashMap;
@@ -147,16 +143,10 @@ public final class WorkflowRepresentation extends AbstractWorkflowComponentRepre
public static class Builder { public static class Builder {
private final Map<WorkflowRepresentation, List<WorkflowStepRepresentation>> steps = new HashMap<>();
private List<Builder> builders = new ArrayList<>();
private WorkflowRepresentation representation; private WorkflowRepresentation representation;
private Builder() { private Builder() {
} this.representation = new WorkflowRepresentation();
private Builder(WorkflowRepresentation representation, List<Builder> builders) {
this.representation = representation;
this.builders = builders;
} }
public Builder onEvent(String operation) { public Builder onEvent(String operation) {
@@ -188,7 +178,7 @@ public final class WorkflowRepresentation extends AbstractWorkflowComponentRepre
} }
public Builder withSteps(WorkflowStepRepresentation... steps) { public Builder withSteps(WorkflowStepRepresentation... steps) {
this.steps.computeIfAbsent(representation, (k) -> new ArrayList<>()).addAll(Arrays.asList(steps)); representation.setSteps(Arrays.asList(steps));
return this; return this;
} }
@@ -203,30 +193,12 @@ public final class WorkflowRepresentation extends AbstractWorkflowComponentRepre
} }
public Builder withName(String name) { public Builder withName(String name) {
WorkflowRepresentation representation = new WorkflowRepresentation();
representation.setName(name); representation.setName(name);
Builder builder = new Builder(representation, builders); return this;
builders.add(builder);
return builder;
} }
public WorkflowSetRepresentation build() { public WorkflowRepresentation build() {
List<WorkflowRepresentation> workflows = new ArrayList<>(); return representation;
for (Builder builder : builders) {
if (builder.steps.isEmpty()) {
continue;
}
for (Entry<WorkflowRepresentation, List<WorkflowStepRepresentation>> entry : builder.steps.entrySet()) {
WorkflowRepresentation workflow = entry.getKey();
workflow.setSteps(entry.getValue());
workflows.add(workflow);
}
}
return new WorkflowSetRepresentation(workflows);
} }
} }
} }

View File

@@ -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<WorkflowRepresentation> workflows;
public WorkflowSetRepresentation() {
}
public WorkflowSetRepresentation(List<WorkflowRepresentation> workflows) {
this.workflows = workflows;
}
public void setWorkflows(List<WorkflowRepresentation> workflows) {
this.workflows = workflows;
}
public List<WorkflowRepresentation> getWorkflows() {
return workflows;
}
}

View File

@@ -6,6 +6,7 @@ import java.util.Objects;
import org.keycloak.common.util.MultivaluedHashMap; import org.keycloak.common.util.MultivaluedHashMap;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 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_USES;
import static org.keycloak.representations.workflows.WorkflowConstants.CONFIG_WITH; 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) @JsonInclude(JsonInclude.Include.NON_EMPTY)
public final class WorkflowStepRepresentation extends AbstractWorkflowComponentRepresentation { public final class WorkflowStepRepresentation extends AbstractWorkflowComponentRepresentation {
@@ -39,6 +40,11 @@ public final class WorkflowStepRepresentation extends AbstractWorkflowComponentR
this.uses = uses; this.uses = uses;
} }
@JsonIgnore
public String getId() {
return super.getId();
}
public String getUses() { public String getUses() {
return this.uses; return this.uses;
} }
@@ -95,11 +101,6 @@ public final class WorkflowStepRepresentation extends AbstractWorkflowComponentR
return this; return this;
} }
public Builder id(String id) {
step.setId(id);
return this;
}
public Builder withConfig(String key, String value) { public Builder withConfig(String key, String value) {
step.setConfig(key, value); step.setConfig(key, value);
return this; return this;

View File

@@ -32,18 +32,15 @@ public class WorkflowDefinitionTest {
expected.setSteps(Arrays.asList( expected.setSteps(Arrays.asList(
WorkflowStepRepresentation.create() WorkflowStepRepresentation.create()
.of("step-1") .of("step-1")
.id("1")
.withConfig("key1", "v1") .withConfig("key1", "v1")
.after(Duration.ofSeconds(10)) .after(Duration.ofSeconds(10))
.build(), .build(),
WorkflowStepRepresentation.create() WorkflowStepRepresentation.create()
.of("step-2") .of("step-2")
.id("2")
.withConfig("key1", "v1", "v2") .withConfig("key1", "v1", "v2")
.build(), .build(),
WorkflowStepRepresentation.create() WorkflowStepRepresentation.create()
.of("step-1") .of("step-1")
.id("3")
.withConfig("key1", "v1") .withConfig("key1", "v1")
.build())); .build()));

View File

@@ -13,7 +13,6 @@ import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
import org.keycloak.representations.workflows.WorkflowRepresentation; import org.keycloak.representations.workflows.WorkflowRepresentation;
import org.keycloak.representations.workflows.WorkflowSetRepresentation;
import com.fasterxml.jackson.jakarta.rs.yaml.YAMLMediaTypes; import com.fasterxml.jackson.jakarta.rs.yaml.YAMLMediaTypes;
@@ -29,11 +28,6 @@ public interface WorkflowsResource {
@Consumes({MediaType.APPLICATION_JSON, YAMLMediaTypes.APPLICATION_JACKSON_YAML}) @Consumes({MediaType.APPLICATION_JSON, YAMLMediaTypes.APPLICATION_JACKSON_YAML})
Response create(WorkflowRepresentation representation); Response create(WorkflowRepresentation representation);
@Path("set")
@POST
@Consumes({MediaType.APPLICATION_JSON, YAMLMediaTypes.APPLICATION_JACKSON_YAML})
Response create(WorkflowSetRepresentation representation);
@GET @GET
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
List<WorkflowRepresentation> list(); List<WorkflowRepresentation> list();

View File

@@ -60,6 +60,7 @@ export default function WorkflowDetailForm() {
} }
return adminClient.workflows.findOne({ return adminClient.workflows.findOne({
id: id!, id: id!,
includeId: false,
}); });
}, },
(workflow) => { (workflow) => {

View File

@@ -19,12 +19,13 @@ export class Workflows extends Resource<{ realm?: string }> {
}); });
public findOne = this.makeRequest< public findOne = this.makeRequest<
{ id: string }, { id: string; includeId: boolean },
WorkflowRepresentation | undefined WorkflowRepresentation | undefined
>({ >({
method: "GET", method: "GET",
path: "/{id}", path: "/{id}",
urlParamKeys: ["id"], urlParamKeys: ["id"],
queryParamKeys: ["includeId"],
catchNotFound: true, catchNotFound: true,
}); });

View File

@@ -9,6 +9,7 @@ import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path; import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam; import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces; import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
@@ -20,6 +21,7 @@ import org.keycloak.representations.workflows.WorkflowRepresentation;
import org.keycloak.services.ErrorResponse; import org.keycloak.services.ErrorResponse;
import com.fasterxml.jackson.jakarta.rs.yaml.YAMLMediaTypes; import com.fasterxml.jackson.jakarta.rs.yaml.YAMLMediaTypes;
import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
public class WorkflowResource { public class WorkflowResource {
@@ -54,8 +56,14 @@ public class WorkflowResource {
@GET @GET
@Produces({MediaType.APPLICATION_JSON, YAMLMediaTypes.APPLICATION_JACKSON_YAML}) @Produces({MediaType.APPLICATION_JSON, YAMLMediaTypes.APPLICATION_JACKSON_YAML})
public WorkflowRepresentation toRepresentation() { public WorkflowRepresentation toRepresentation(
return provider.toRepresentation(workflow); @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;
} }
/** /**

View File

@@ -22,7 +22,6 @@ import org.keycloak.models.ModelException;
import org.keycloak.models.workflow.Workflow; import org.keycloak.models.workflow.Workflow;
import org.keycloak.models.workflow.WorkflowProvider; import org.keycloak.models.workflow.WorkflowProvider;
import org.keycloak.representations.workflows.WorkflowRepresentation; import org.keycloak.representations.workflows.WorkflowRepresentation;
import org.keycloak.representations.workflows.WorkflowSetRepresentation;
import org.keycloak.services.ErrorResponse; import org.keycloak.services.ErrorResponse;
import org.keycloak.services.resources.admin.fgap.AdminPermissionEvaluator; 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}") @Path("{id}")
public WorkflowResource get(@PathParam("id") String id) { public WorkflowResource get(@PathParam("id") String id) {
auth.realm().requireManageRealm(); auth.realm().requireManageRealm();

View File

@@ -54,21 +54,23 @@ public class AdhocWorkflowTest extends AbstractWorkflowTest {
@Test @Test
public void testBindAdHocScheduledWithImmediateWorkflow() { 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() .withSteps(WorkflowStepRepresentation.create()
.of(SetUserAttributeStepProviderFactory.ID) .of(SetUserAttributeStepProviderFactory.ID)
.withConfig("message", "message") .withConfig("message", "message")
.build()) .build())
.build()).close(); .build())) {
workflowId = ApiUtil.getCreatedId(response);
}
List<WorkflowRepresentation> workflows = managedRealm.admin().workflows().list(); List<WorkflowRepresentation> workflows = managedRealm.admin().workflows().list();
assertThat(workflows, hasSize(1)); assertThat(workflows, hasSize(1));
WorkflowRepresentation workflow = workflows.get(0);
try (Response response = managedRealm.admin().users().create(getUserRepresentation("alice", "Alice", "Wonderland", "alice@wornderland.org"))) { try (Response response = managedRealm.admin().users().create(getUserRepresentation("alice", "Alice", "Wonderland", "alice@wornderland.org"))) {
String id = ApiUtil.getCreatedId(response); String id = ApiUtil.getCreatedId(response);
try { 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) { } catch (Exception e) {
assertThat(e, instanceOf(BadRequestException.class)); assertThat(e, instanceOf(BadRequestException.class));
} }
@@ -77,40 +79,44 @@ public class AdhocWorkflowTest extends AbstractWorkflowTest {
@Test @Test
public void testRunAdHocScheduledWorkflow() { 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() .withSteps(WorkflowStepRepresentation.create()
.of(SetUserAttributeStepProviderFactory.ID) .of(SetUserAttributeStepProviderFactory.ID)
.after(Duration.ofDays(5)) .after(Duration.ofDays(5))
.withConfig("message", "message") .withConfig("message", "message")
.build()) .build())
.build()).close(); .build())) {
workflowId = ApiUtil.getCreatedId(response);
}
List<WorkflowRepresentation> workflows = managedRealm.admin().workflows().list(); List<WorkflowRepresentation> workflows = managedRealm.admin().workflows().list();
assertThat(workflows, hasSize(1)); assertThat(workflows, hasSize(1));
WorkflowRepresentation workflow = workflows.get(0);
try (Response response = managedRealm.admin().users().create(getUserRepresentation("alice", "Alice", "Wonderland", "alice@wornderland.org"))) { try (Response response = managedRealm.admin().users().create(getUserRepresentation("alice", "Alice", "Wonderland", "alice@wornderland.org"))) {
String id = ApiUtil.getCreatedId(response); 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 @Test
public void testRunAdHocImmediateWorkflow() { 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() .withSteps(WorkflowStepRepresentation.create()
.of(SetUserAttributeStepProviderFactory.ID) .of(SetUserAttributeStepProviderFactory.ID)
.withConfig("message", "message") .withConfig("message", "message")
.build()) .build())
.build()).close(); .build())) {
workflowId = ApiUtil.getCreatedId(response);
}
List<WorkflowRepresentation> workflows = managedRealm.admin().workflows().list(); List<WorkflowRepresentation> workflows = managedRealm.admin().workflows().list();
assertThat(workflows, hasSize(1)); assertThat(workflows, hasSize(1));
WorkflowRepresentation workflow = workflows.get(0);
try (Response response = managedRealm.admin().users().create(getUserRepresentation("alice", "Alice", "Wonderland", "alice@wornderland.org"))) { try (Response response = managedRealm.admin().users().create(getUserRepresentation("alice", "Alice", "Wonderland", "alice@wornderland.org"))) {
String id = ApiUtil.getCreatedId(response); 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); runScheduledSteps(Duration.ZERO);
@@ -124,21 +130,23 @@ public class AdhocWorkflowTest extends AbstractWorkflowTest {
@Test @Test
public void testRunAdHocTimedWorkflow() { 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() .withSteps(WorkflowStepRepresentation.create()
.of(SetUserAttributeStepProviderFactory.ID) .of(SetUserAttributeStepProviderFactory.ID)
.withConfig("message", "message") .withConfig("message", "message")
.build()) .build())
.build()).close(); .build())) {
workflowId = ApiUtil.getCreatedId(response);
}
List<WorkflowRepresentation> workflows = managedRealm.admin().workflows().list(); List<WorkflowRepresentation> workflows = managedRealm.admin().workflows().list();
assertThat(workflows, hasSize(1)); assertThat(workflows, hasSize(1));
WorkflowRepresentation workflow = workflows.get(0); String resourceId;
String id;
try (Response response = managedRealm.admin().users().create(getUserRepresentation("alice", "Alice", "Wonderland", "alice@wornderland.org"))) { try (Response response = managedRealm.admin().users().create(getUserRepresentation("alice", "Alice", "Wonderland", "alice@wornderland.org"))) {
id = ApiUtil.getCreatedId(response); resourceId = ApiUtil.getCreatedId(response);
managedRealm.admin().workflows().workflow(workflow.getId()).activate(ResourceType.USERS.name(), id, "5D"); managedRealm.admin().workflows().workflow(workflowId).activate(ResourceType.USERS.name(), resourceId, "5D");
} }
runScheduledSteps(Duration.ZERO); 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 // 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); runScheduledSteps(Duration.ZERO);
@@ -204,7 +212,8 @@ public class AdhocWorkflowTest extends AbstractWorkflowTest {
.after(Duration.ofDays(5)) .after(Duration.ofDays(5))
.build() .build()
) )
.withName("Two") .build()).close();
managedRealm.admin().workflows().create(WorkflowRepresentation.withName("Two")
.onEvent(USER_ADDED.name()) .onEvent(USER_ADDED.name())
.withSteps( .withSteps(
WorkflowStepRepresentation.create() WorkflowStepRepresentation.create()

View File

@@ -21,6 +21,8 @@ import java.time.Duration;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import jakarta.ws.rs.core.Response;
import org.keycloak.admin.client.resource.UsersResource; import org.keycloak.admin.client.resource.UsersResource;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel; 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.annotations.InjectWebDriver;
import org.keycloak.testframework.ui.page.ConsentPage; import org.keycloak.testframework.ui.page.ConsentPage;
import org.keycloak.testframework.ui.page.LoginPage; import org.keycloak.testframework.ui.page.LoginPage;
import org.keycloak.testframework.util.ApiUtil;
import org.awaitility.Awaitility; import org.awaitility.Awaitility;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
@@ -127,19 +130,22 @@ public class BrokeredUserSessionRefreshTimeWorkflowTest extends AbstractWorkflow
@Test @Test
public void testInvalidateWorkflowOnIdentityProviderRemoval() { 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()) .onEvent(USER_ADDED.toString(), USER_LOGGED_IN.toString())
.onCondition(IDP_CONDITION) .onCondition(IDP_CONDITION)
.withSteps( .withSteps(
WorkflowStepRepresentation.create().of(DeleteUserStepProviderFactory.ID) WorkflowStepRepresentation.create().of(DeleteUserStepProviderFactory.ID)
.after(Duration.ofDays(1)) .after(Duration.ofDays(1))
.build() .build())
).build()).close(); .build())) {
workflowId = ApiUtil.getCreatedId(response);
}
List<WorkflowRepresentation> workflows = consumerRealm.admin().workflows().list(); List<WorkflowRepresentation> workflows = consumerRealm.admin().workflows().list();
assertThat(workflows, hasSize(1)); 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()); assertThat(workflowRep.getConfig().getFirst("enabled"), nullValue());
// remove IDP // remove IDP
@@ -152,7 +158,7 @@ public class BrokeredUserSessionRefreshTimeWorkflowTest extends AbstractWorkflow
.timeout(Duration.ofSeconds(30)) .timeout(Duration.ofSeconds(30))
.pollInterval(Duration.ofSeconds(1)) .pollInterval(Duration.ofSeconds(1))
.untilAsserted(() -> { .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))); assertThat(rep.getEnabled(), allOf(notNullValue(), is(false)));
WorkflowStateRepresentation status = rep.getState(); WorkflowStateRepresentation status = rep.getState();
assertThat(status, notNullValue()); assertThat(status, notNullValue());

View File

@@ -15,7 +15,6 @@ import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.RoleRepresentation; import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.userprofile.config.UPConfig; import org.keycloak.representations.userprofile.config.UPConfig;
import org.keycloak.representations.workflows.WorkflowRepresentation; import org.keycloak.representations.workflows.WorkflowRepresentation;
import org.keycloak.representations.workflows.WorkflowSetRepresentation;
import org.keycloak.representations.workflows.WorkflowStepRepresentation; import org.keycloak.representations.workflows.WorkflowStepRepresentation;
import org.keycloak.testframework.annotations.KeycloakIntegrationTest; import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
import org.keycloak.testframework.realm.GroupConfigBuilder; import org.keycloak.testframework.realm.GroupConfigBuilder;
@@ -175,7 +174,7 @@ public class ExpressionConditionWorkflowTest extends AbstractWorkflowTest {
} }
private String createWorkflow(String expression) { private String createWorkflow(String expression) {
WorkflowSetRepresentation expectedWorkflows = WorkflowRepresentation.withName("myworkflow") WorkflowRepresentation expectedWorkflow = WorkflowRepresentation.withName("myworkflow")
.onEvent("user-logged-in(test-app)") .onEvent("user-logged-in(test-app)")
.onCondition(expression) .onCondition(expression)
.withSteps( .withSteps(
@@ -188,7 +187,7 @@ public class ExpressionConditionWorkflowTest extends AbstractWorkflowTest {
WorkflowsResource workflows = managedRealm.admin().workflows(); 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())); assertThat(response.getStatus(), is(Response.Status.CREATED.getStatusCode()));
return ApiUtil.getCreatedId(response); return ApiUtil.getCreatedId(response);
} }

View File

@@ -16,7 +16,6 @@ import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.representations.userprofile.config.UPConfig; import org.keycloak.representations.userprofile.config.UPConfig;
import org.keycloak.representations.userprofile.config.UPConfig.UnmanagedAttributePolicy; import org.keycloak.representations.userprofile.config.UPConfig.UnmanagedAttributePolicy;
import org.keycloak.representations.workflows.WorkflowRepresentation; import org.keycloak.representations.workflows.WorkflowRepresentation;
import org.keycloak.representations.workflows.WorkflowSetRepresentation;
import org.keycloak.representations.workflows.WorkflowStateRepresentation; import org.keycloak.representations.workflows.WorkflowStateRepresentation;
import org.keycloak.representations.workflows.WorkflowStepRepresentation; import org.keycloak.representations.workflows.WorkflowStepRepresentation;
import org.keycloak.testframework.annotations.KeycloakIntegrationTest; import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
@@ -57,7 +56,7 @@ public class GroupMembershipJoinWorkflowTest extends AbstractWorkflowTest {
groupId = ApiUtil.getCreatedId(response); groupId = ApiUtil.getCreatedId(response);
} }
WorkflowSetRepresentation expectedWorkflows = WorkflowRepresentation.withName("myworkflow") WorkflowRepresentation expectedWorkflow = WorkflowRepresentation.withName("myworkflow")
.onEvent(ResourceOperationType.USER_GROUP_MEMBERSHIP_ADDED.name()) .onEvent(ResourceOperationType.USER_GROUP_MEMBERSHIP_ADDED.name())
.onCondition(GROUP_CONDITION) .onCondition(GROUP_CONDITION)
.withSteps( .withSteps(
@@ -70,7 +69,7 @@ public class GroupMembershipJoinWorkflowTest extends AbstractWorkflowTest {
WorkflowsResource workflows = managedRealm.admin().workflows(); WorkflowsResource workflows = managedRealm.admin().workflows();
try (Response response = workflows.create(expectedWorkflows)) { try (Response response = workflows.create(expectedWorkflow)) {
assertThat(response.getStatus(), is(Status.CREATED.getStatusCode())); assertThat(response.getStatus(), is(Status.CREATED.getStatusCode()));
} }
@@ -95,25 +94,27 @@ public class GroupMembershipJoinWorkflowTest extends AbstractWorkflowTest {
@Test @Test
public void testRemoveAssociatedGroup() { public void testRemoveAssociatedGroup() {
String groupId; String groupId;
try (Response response = managedRealm.admin().groups().add(GroupConfigBuilder.create() try (Response response = managedRealm.admin().groups().add(GroupConfigBuilder.create()
.name("generic-group").build())) { .name("generic-group").build())) {
groupId = ApiUtil.getCreatedId(response); 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()) .onEvent(USER_ADDED.toString(), USER_LOGGED_IN.toString())
.onCondition(GROUP_CONDITION) .onCondition(GROUP_CONDITION)
.withSteps( .withSteps(
WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID) WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID)
.after(Duration.ofDays(1)) .after(Duration.ofDays(1))
.build() .build())
).build()).close(); .build())) {
workflowId = ApiUtil.getCreatedId(response);
}
List<WorkflowRepresentation> workflows = managedRealm.admin().workflows().list(); List<WorkflowRepresentation> workflows = managedRealm.admin().workflows().list();
assertThat(workflows, hasSize(1)); 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()); assertThat(workflowRep.getConfig().getFirst("enabled"), nullValue());
// remove group // remove group
@@ -126,7 +127,7 @@ public class GroupMembershipJoinWorkflowTest extends AbstractWorkflowTest {
.timeout(Duration.ofSeconds(30)) .timeout(Duration.ofSeconds(30))
.pollInterval(Duration.ofSeconds(1)) .pollInterval(Duration.ofSeconds(1))
.untilAsserted(() -> { .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))); assertThat(rep.getEnabled(), allOf(notNullValue(), is(false)));
WorkflowStateRepresentation status = rep.getState(); WorkflowStateRepresentation status = rep.getState();
assertThat(status, notNullValue()); assertThat(status, notNullValue());

View File

@@ -19,7 +19,6 @@ import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.userprofile.config.UPConfig; import org.keycloak.representations.userprofile.config.UPConfig;
import org.keycloak.representations.userprofile.config.UPConfig.UnmanagedAttributePolicy; import org.keycloak.representations.userprofile.config.UPConfig.UnmanagedAttributePolicy;
import org.keycloak.representations.workflows.WorkflowRepresentation; import org.keycloak.representations.workflows.WorkflowRepresentation;
import org.keycloak.representations.workflows.WorkflowSetRepresentation;
import org.keycloak.representations.workflows.WorkflowStepRepresentation; import org.keycloak.representations.workflows.WorkflowStepRepresentation;
import org.keycloak.testframework.annotations.KeycloakIntegrationTest; import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
import org.keycloak.testframework.realm.RoleConfigBuilder; import org.keycloak.testframework.realm.RoleConfigBuilder;
@@ -114,7 +113,7 @@ public class RoleWorkflowConditionTest extends AbstractWorkflowTest {
.map(role -> RoleWorkflowConditionFactory.ID + "(" + role + ")") .map(role -> RoleWorkflowConditionFactory.ID + "(" + role + ")")
.reduce((a, b) -> a + " AND " + b).orElse(null); .reduce((a, b) -> a + " AND " + b).orElse(null);
WorkflowSetRepresentation expectedWorkflows = WorkflowRepresentation.withName("myworkflow") WorkflowRepresentation expectedWorkflow = WorkflowRepresentation.withName("myworkflow")
.onEvent(ResourceOperationType.USER_ROLE_ADDED.name()) .onEvent(ResourceOperationType.USER_ROLE_ADDED.name())
.onCondition(roleCondition) .onCondition(roleCondition)
.withSteps( .withSteps(
@@ -130,7 +129,7 @@ public class RoleWorkflowConditionTest extends AbstractWorkflowTest {
WorkflowsResource workflows = managedRealm.admin().workflows(); WorkflowsResource workflows = managedRealm.admin().workflows();
try (Response response = workflows.create(expectedWorkflows)) { try (Response response = workflows.create(expectedWorkflow)) {
assertThat(response.getStatus(), is(Status.CREATED.getStatusCode())); assertThat(response.getStatus(), is(Status.CREATED.getStatusCode()));
} }
} }

View File

@@ -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;
import org.keycloak.representations.userprofile.config.UPConfig.UnmanagedAttributePolicy; import org.keycloak.representations.userprofile.config.UPConfig.UnmanagedAttributePolicy;
import org.keycloak.representations.workflows.WorkflowRepresentation; import org.keycloak.representations.workflows.WorkflowRepresentation;
import org.keycloak.representations.workflows.WorkflowSetRepresentation;
import org.keycloak.representations.workflows.WorkflowStepRepresentation; import org.keycloak.representations.workflows.WorkflowStepRepresentation;
import org.keycloak.testframework.annotations.KeycloakIntegrationTest; import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
import org.keycloak.testframework.realm.UserConfigBuilder; import org.keycloak.testframework.realm.UserConfigBuilder;
@@ -117,7 +116,7 @@ public class UserAttributeWorkflowConditionTest extends AbstractWorkflowTest {
.reduce((a, b) -> a + " AND " + b) .reduce((a, b) -> a + " AND " + b)
.orElse(null); .orElse(null);
WorkflowSetRepresentation expectedWorkflows = WorkflowRepresentation.withName("myworkflow") WorkflowRepresentation expectedWorkflow = WorkflowRepresentation.withName("myworkflow")
.onEvent(ResourceOperationType.USER_ADDED.name()) .onEvent(ResourceOperationType.USER_ADDED.name())
.onCondition(attributeCondition) .onCondition(attributeCondition)
.withSteps( .withSteps(
@@ -133,7 +132,7 @@ public class UserAttributeWorkflowConditionTest extends AbstractWorkflowTest {
WorkflowsResource workflows = managedRealm.admin().workflows(); WorkflowsResource workflows = managedRealm.admin().workflows();
try (Response response = workflows.create(expectedWorkflows)) { try (Response response = workflows.create(expectedWorkflow)) {
assertThat(response.getStatus(), is(Status.CREATED.getStatusCode())); assertThat(response.getStatus(), is(Status.CREATED.getStatusCode()));
} }
} }

View File

@@ -143,9 +143,9 @@ public class UserSessionRefreshTimeWorkflowTest extends AbstractWorkflowTest {
.after(Duration.ofDays(5)) .after(Duration.ofDays(5))
.withConfig("custom_subject_key", "notifier1_subject") .withConfig("custom_subject_key", "notifier1_subject")
.withConfig("custom_message", "notifier1_message") .withConfig("custom_message", "notifier1_message")
.build() .build())
) .build()).close();
.withName("myworkflow_2") managedRealm.admin().workflows().create(WorkflowRepresentation.withName("myworkflow_2")
.onEvent(USER_ADDED.toString(), USER_LOGGED_IN.toString()) .onEvent(USER_ADDED.toString(), USER_LOGGED_IN.toString())
.withSteps( .withSteps(
WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID) WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID)

View File

@@ -53,7 +53,6 @@ import org.keycloak.models.workflow.conditions.IdentityProviderWorkflowCondition
import org.keycloak.representations.idm.ErrorRepresentation; import org.keycloak.representations.idm.ErrorRepresentation;
import org.keycloak.representations.idm.IdentityProviderRepresentation; import org.keycloak.representations.idm.IdentityProviderRepresentation;
import org.keycloak.representations.workflows.WorkflowRepresentation; import org.keycloak.representations.workflows.WorkflowRepresentation;
import org.keycloak.representations.workflows.WorkflowSetRepresentation;
import org.keycloak.representations.workflows.WorkflowStepRepresentation; import org.keycloak.representations.workflows.WorkflowStepRepresentation;
import org.keycloak.testframework.annotations.InjectAdminClient; import org.keycloak.testframework.annotations.InjectAdminClient;
import org.keycloak.testframework.annotations.InjectKeycloakUrls; 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.realm.UserConfigBuilder;
import org.keycloak.testframework.remote.providers.runonserver.RunOnServer; import org.keycloak.testframework.remote.providers.runonserver.RunOnServer;
import org.keycloak.testframework.server.KeycloakUrls; import org.keycloak.testframework.server.KeycloakUrls;
import org.keycloak.testframework.util.ApiUtil;
import org.keycloak.tests.utils.MailUtils; import org.keycloak.tests.utils.MailUtils;
import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonInclude.Include;
@@ -101,7 +101,7 @@ public class WorkflowManagementTest extends AbstractWorkflowTest {
@Test @Test
public void testCreate() { public void testCreate() {
WorkflowSetRepresentation expectedWorkflows = WorkflowRepresentation.withName("myworkflow") WorkflowRepresentation expectedWorkflow = WorkflowRepresentation.withName("myworkflow")
.onEvent(USER_ADDED.name()) .onEvent(USER_ADDED.name())
.withSteps( .withSteps(
WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID) WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID)
@@ -114,7 +114,7 @@ public class WorkflowManagementTest extends AbstractWorkflowTest {
WorkflowsResource workflows = managedRealm.admin().workflows(); 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())); assertThat(response.getStatus(), is(Response.Status.CREATED.getStatusCode()));
} }
@@ -129,7 +129,7 @@ public class WorkflowManagementTest extends AbstractWorkflowTest {
@Test @Test
public void testCreateWithNoConditions() { public void testCreateWithNoConditions() {
WorkflowSetRepresentation expectedWorkflows = WorkflowRepresentation.withName("myworkflow") WorkflowRepresentation expectedWorkflow = WorkflowRepresentation.withName("myworkflow")
.withSteps( .withSteps(
WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID) WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID)
.after(Duration.ofDays(5)) .after(Duration.ofDays(5))
@@ -139,16 +139,16 @@ public class WorkflowManagementTest extends AbstractWorkflowTest {
.build() .build()
).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())); assertThat(response.getStatus(), is(Response.Status.CREATED.getStatusCode()));
} }
} }
@Test @Test
public void testCreateWithNoWorkflowSetDefaultWorkflow() { public void testCreateWithNoWorkflowSetDefaultWorkflow() {
WorkflowSetRepresentation expectedWorkflows = WorkflowRepresentation.withName("default-workflow") WorkflowRepresentation expectedWorkflow = WorkflowRepresentation.withName("default-workflow")
.withSteps( .withSteps(
WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID) WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID)
.after(Duration.ofDays(5)) .after(Duration.ofDays(5))
@@ -158,9 +158,9 @@ public class WorkflowManagementTest extends AbstractWorkflowTest {
.build() .build()
).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())); assertThat(response.getStatus(), is(Response.Status.CREATED.getStatusCode()));
} }
@@ -171,16 +171,20 @@ public class WorkflowManagementTest extends AbstractWorkflowTest {
public void testDelete() { public void testDelete() {
WorkflowsResource workflows = managedRealm.admin().workflows(); 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()) .onEvent(ResourceOperationType.USER_ADDED.toString())
.withSteps( .withSteps(
WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID) WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID)
.after(Duration.ofDays(5)) .after(Duration.ofDays(5))
.build(), .build(),
WorkflowStepRepresentation.create().of(RestartWorkflowStepProviderFactory.ID) WorkflowStepRepresentation.create().of(RestartWorkflowStepProviderFactory.ID)
.build() .build())
) .build())) {
.withName("another-workflow") workflowId = ApiUtil.getCreatedId(response);
}
workflows.create(WorkflowRepresentation.withName("another-workflow")
.onEvent(ResourceOperationType.USER_LOGGED_IN.toString()) .onEvent(ResourceOperationType.USER_LOGGED_IN.toString())
.withSteps( .withSteps(
WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID) WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID)
@@ -196,10 +200,7 @@ public class WorkflowManagementTest extends AbstractWorkflowTest {
List<WorkflowRepresentation> actualWorkflows = workflows.list(); List<WorkflowRepresentation> actualWorkflows = workflows.list();
assertThat(actualWorkflows, Matchers.hasSize(2)); assertThat(actualWorkflows, Matchers.hasSize(2));
WorkflowRepresentation workflow = actualWorkflows.stream().filter(p -> "myworkflow".equals(p.getName())).findAny().orElse(null); workflows.workflow(workflowId).delete().close();
assertThat(workflow, notNullValue());
String id = workflow.getId();
workflows.workflow(id).delete().close();
actualWorkflows = workflows.list(); actualWorkflows = workflows.list();
assertThat(actualWorkflows, Matchers.hasSize(1)); assertThat(actualWorkflows, Matchers.hasSize(1));
@@ -209,14 +210,14 @@ public class WorkflowManagementTest extends AbstractWorkflowTest {
List<Workflow> registeredWorkflows = provider.getWorkflows().toList(); List<Workflow> registeredWorkflows = provider.getWorkflows().toList();
assertEquals(1, registeredWorkflows.size()); assertEquals(1, registeredWorkflows.size());
WorkflowStateProvider stateProvider = session.getKeycloakSessionFactory().getProviderFactory(WorkflowStateProvider.class).create(session); WorkflowStateProvider stateProvider = session.getKeycloakSessionFactory().getProviderFactory(WorkflowStateProvider.class).create(session);
List<ScheduledStep> steps = stateProvider.getScheduledStepsByWorkflow(id); List<ScheduledStep> steps = stateProvider.getScheduledStepsByWorkflow(workflowId);
assertTrue(steps.isEmpty()); assertTrue(steps.isEmpty());
}); });
} }
@Test @Test
public void testUpdate() { public void testUpdate() {
WorkflowSetRepresentation expectedWorkflows = WorkflowRepresentation.withName("test-workflow") WorkflowRepresentation workflowRep = WorkflowRepresentation.withName("test-workflow")
.withSteps( .withSteps(
WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID) WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID)
.after(Duration.ofDays(5)) .after(Duration.ofDays(5))
@@ -228,8 +229,10 @@ public class WorkflowManagementTest extends AbstractWorkflowTest {
WorkflowsResource workflows = managedRealm.admin().workflows(); 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())); assertThat(response.getStatus(), is(Response.Status.CREATED.getStatusCode()));
workflowId = ApiUtil.getCreatedId(response);
} }
List<WorkflowRepresentation> actualWorkflows = workflows.list(); List<WorkflowRepresentation> actualWorkflows = workflows.list();
@@ -238,7 +241,7 @@ public class WorkflowManagementTest extends AbstractWorkflowTest {
assertThat(workflow.getName(), is("test-workflow")); assertThat(workflow.getName(), is("test-workflow"));
workflow.setName("changed"); workflow.setName("changed");
managedRealm.admin().workflows().workflow(workflow.getId()).update(workflow).close(); managedRealm.admin().workflows().workflow(workflowId).update(workflow).close();
actualWorkflows = workflows.list(); actualWorkflows = workflows.list();
workflow = actualWorkflows.get(0); workflow = actualWorkflows.get(0);
assertThat(workflow.getName(), is("changed")); 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 // now let's try to update another property that we can't update
String previousOn = workflow.getOn(); String previousOn = workflow.getOn();
workflow.setOn(ResourceOperationType.USER_LOGGED_IN.toString()); 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())); assertThat(response.getStatus(), is(Response.Status.BAD_REQUEST.getStatusCode()));
} }
// restore previous value, but change the conditions // restore previous value, but change the conditions
workflow.setOn(previousOn); workflow.setOn(previousOn);
workflow.setConditions(IdentityProviderWorkflowConditionFactory.ID + "(someidp)"); 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())); assertThat(response.getStatus(), is(Response.Status.BAD_REQUEST.getStatusCode()));
} }
// revert conditions, but change one of the steps // revert conditions, but change one of the steps
workflow.setConditions(null); workflow.setConditions(null);
workflow.getSteps().get(0).setAfter("8D"); // 8 days workflow.getSteps().get(0).setAfter("8D");
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())); assertThat(response.getStatus(), is(Response.Status.BAD_REQUEST.getStatusCode()));
} }
@@ -510,7 +513,8 @@ public class WorkflowManagementTest extends AbstractWorkflowTest {
@Test @Test
public void testDisableWorkflow() { public void testDisableWorkflow() {
// create a test workflow // 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()) .onEvent(ResourceOperationType.USER_ADDED.toString())
.withSteps( .withSteps(
WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID) WorkflowStepRepresentation.create().of(NotifyUserStepProviderFactory.ID)
@@ -519,7 +523,9 @@ public class WorkflowManagementTest extends AbstractWorkflowTest {
WorkflowStepRepresentation.create().of(DisableUserStepProviderFactory.ID) WorkflowStepRepresentation.create().of(DisableUserStepProviderFactory.ID)
.after(Duration.ofDays(5)) .after(Duration.ofDays(5))
.build() .build()
).build()).close(); ).build())) {
workflowId = ApiUtil.getCreatedId(response);
}
WorkflowsResource workflows = managedRealm.admin().workflows(); WorkflowsResource workflows = managedRealm.admin().workflows();
List<WorkflowRepresentation> actualWorkflows = workflows.list(); List<WorkflowRepresentation> 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 // disable the workflow - scheduled steps should be paused and workflow should not activate for new users
workflow.setEnabled(false); 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 // 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(); 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 // re-enable the workflow - scheduled steps should resume and new users should be bound to the workflow
workflow.getConfig().putSingle("enabled", "true"); 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 // 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(); managedRealm.admin().users().create(UserConfigBuilder.create().username("thirduser").email("thirduser@example.com").build()).close();
@@ -671,7 +677,7 @@ public class WorkflowManagementTest extends AbstractWorkflowTest {
@Test @Test
public void testFailCreateWorkflowWithNegativeTime() { public void testFailCreateWorkflowWithNegativeTime() {
WorkflowSetRepresentation workflows = WorkflowRepresentation.withName("myworkflow") WorkflowRepresentation workflow = WorkflowRepresentation.withName("myworkflow")
.onEvent(USER_ADDED.name()) .onEvent(USER_ADDED.name())
.withSteps( .withSteps(
WorkflowStepRepresentation.create().of(SetUserAttributeStepProviderFactory.ID) WorkflowStepRepresentation.create().of(SetUserAttributeStepProviderFactory.ID)
@@ -679,7 +685,7 @@ public class WorkflowManagementTest extends AbstractWorkflowTest {
.withConfig("key", "value") .withConfig("key", "value")
.build()) .build())
.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.getStatus(), is(Response.Status.BAD_REQUEST.getStatusCode()));
assertThat(response.readEntity(ErrorRepresentation.class).getErrorMessage(), equalTo("Step 'after' configuration cannot be negative.")); 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) WorkflowStepRepresentation.create().of(DisableUserStepProviderFactory.ID)
.after(Duration.ofDays(5)) .after(Duration.ofDays(5))
.build() .build()
).build().getWorkflows().get(0); ).build();
try (Client httpClient = Keycloak.getClientProvider().newRestEasyClient(null, null, true)) { try (Client httpClient = Keycloak.getClientProvider().newRestEasyClient(null, null, true)) {
httpClient.register(JacksonYAMLProvider.class); httpClient.register(JacksonYAMLProvider.class);
@@ -872,9 +878,11 @@ public class WorkflowManagementTest extends AbstractWorkflowTest {
.path("workflows") .path("workflows")
.register(new BearerAuthFilter(adminClient.tokenManager())); .register(new BearerAuthFilter(adminClient.tokenManager()));
String workflowId;
try (Response response = workflowsApi.request().post(Entity.entity(yamlMapper.writeValueAsString(expected), try (Response response = workflowsApi.request().post(Entity.entity(yamlMapper.writeValueAsString(expected),
YAMLMediaTypes.APPLICATION_JACKSON_YAML))) { YAMLMediaTypes.APPLICATION_JACKSON_YAML))) {
assertEquals(Status.CREATED.getStatusCode(), response.getStatus()); assertEquals(Status.CREATED.getStatusCode(), response.getStatus());
workflowId = ApiUtil.getCreatedId(response);
} }
try (Response response = workflowsApi.request().accept(YAMLMediaTypes.APPLICATION_JACKSON_YAML).get()) { try (Response response = workflowsApi.request().accept(YAMLMediaTypes.APPLICATION_JACKSON_YAML).get()) {
@@ -886,15 +894,14 @@ public class WorkflowManagementTest extends AbstractWorkflowTest {
expected = workflows.get(0); 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()) { .accept(YAMLMediaTypes.APPLICATION_JACKSON_YAML).get()) {
assertEquals(Status.OK.getStatusCode(), response.getStatus()); assertEquals(Status.OK.getStatusCode(), response.getStatus());
WorkflowRepresentation actual = yamlMapper.readValue(response.readEntity(String.class), WorkflowRepresentation.class); WorkflowRepresentation actual = yamlMapper.readValue(response.readEntity(String.class), WorkflowRepresentation.class);
assertEquals(expected.getId(), actual.getId());
assertEquals(expected.getName(), actual.getName()); 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))) { .put(Entity.entity(yamlMapper.writeValueAsString(expected), YAMLMediaTypes.APPLICATION_JACKSON_YAML))) {
assertEquals(Status.NO_CONTENT.getStatusCode(), response.getStatus()); assertEquals(Status.NO_CONTENT.getStatusCode(), response.getStatus());
} }