Add API method to allow activating a workflow for all eligible resources

Closes #44643

Signed-off-by: Stefan Guilhen <sguilhen@redhat.com>
This commit is contained in:
Stefan Guilhen
2025-12-03 15:05:37 -03:00
committed by Pedro Igor
parent 2f81a2fb76
commit 484980dbbe
7 changed files with 43 additions and 44 deletions

View File

@@ -8,7 +8,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.core.MediaType;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.Response;
import org.keycloak.representations.workflows.WorkflowRepresentation;
@@ -28,19 +28,24 @@ public interface WorkflowResource {
@Produces(APPLICATION_JSON)
WorkflowRepresentation toRepresentation();
@Path("activate-all")
@POST
void activateAll();
@Path("activate-all")
@POST
void activateAll(@QueryParam("notBefore") String notBefore);
@Path("activate/{type}/{resourceId}")
@POST
@Consumes(MediaType.APPLICATION_JSON)
void activate(@PathParam("type") String type, @PathParam("resourceId") String resourceId);
@Path("activate/{type}/{resourceId}")
@POST
@Consumes(MediaType.APPLICATION_JSON)
void activate(@PathParam("type") String type, @PathParam("resourceId") String resourceId, String notBefore);
void activate(@PathParam("type") String type, @PathParam("resourceId") String resourceId, @QueryParam("notBefore") String notBefore);
@Path("deactivate/{type}/{resourceId}")
@POST
@Consumes(MediaType.APPLICATION_JSON)
void deactivate(@PathParam("type") String type, @PathParam("resourceId") String resourceId);
}

View File

@@ -46,6 +46,7 @@ public class WorkflowResource {
* Update the workflow configuration. The method does not update the workflow steps.
*/
@PUT
@Consumes({YAMLMediaTypes.APPLICATION_JACKSON_YAML, MediaType.APPLICATION_JSON})
public void update(WorkflowRepresentation rep) {
try {
provider.updateWorkflow(workflow, rep);
@@ -76,9 +77,8 @@ public class WorkflowResource {
* an integer followed by 'ms' representing milliseconds from now, or an ISO-8601 date string.
*/
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Path("activate/{type}/{resourceId}")
public void activate(@PathParam("type") ResourceType type, @PathParam("resourceId") String resourceId, String notBefore) {
public void activate(@PathParam("type") ResourceType type, @PathParam("resourceId") String resourceId, @QueryParam("notBefore") String notBefore) {
Object resource = provider.getResourceTypeSelector(type).resolveResource(resourceId);
if (resource == null) {
@@ -92,6 +92,17 @@ public class WorkflowResource {
provider.activate(workflow, type, resourceId);
}
@POST
@Path("activate-all")
public void activateAll(@QueryParam("notBefore") String notBefore) {
if (notBefore != null) {
workflow.setNotBefore(notBefore);
}
provider.activateForAllEligibleResources(workflow);
}
/**
* Deactivate the workflow for the resource.
*

View File

@@ -44,7 +44,7 @@ public class WorkflowsResource {
}
@POST
@Consumes({MediaType.APPLICATION_JSON, YAMLMediaTypes.APPLICATION_JACKSON_YAML})
@Consumes({YAMLMediaTypes.APPLICATION_JACKSON_YAML, MediaType.APPLICATION_JSON})
public Response create(WorkflowRepresentation rep) {
auth.realm().requireManageRealm();
@@ -70,7 +70,7 @@ public class WorkflowsResource {
}
@GET
@Produces({MediaType.APPLICATION_JSON, YAMLMediaTypes.APPLICATION_JACKSON_YAML})
@Produces({YAMLMediaTypes.APPLICATION_JACKSON_YAML, MediaType.APPLICATION_JSON})
public List<WorkflowRepresentation> list(
@Parameter(description = "A String representing the workflow name - either partial or exact") @QueryParam("search") String search,
@Parameter(description = "Boolean which defines whether the param 'search' must match exactly or not") @QueryParam("exact") Boolean exact,

View File

@@ -163,15 +163,10 @@ public class GroupMembershipJoinWorkflowTest extends AbstractWorkflowTest {
.build()
).build()).close();
runOnServer.run((RunOnServer) session -> {
// check the same users are now scheduled to run the second step.
WorkflowProvider provider = session.getProvider(WorkflowProvider.class);
List<Workflow> registeredWorkflows = provider.getWorkflows().toList();
assertThat(registeredWorkflows, hasSize(1));
// activate the workflow for all eligible users
provider.activateForAllEligibleResources(registeredWorkflows.get(0));
});
List<WorkflowRepresentation> workflows = managedRealm.admin().workflows().list();
assertThat(workflows, hasSize(1));
// activate the workflow for all eligible users
managedRealm.admin().workflows().workflow(workflows.get(0).getId()).activateAll();
runOnServer.run((RunOnServer) session -> {
// check the same users are now scheduled to run the second step.

View File

@@ -95,15 +95,10 @@ public class RoleWorkflowConditionTest extends AbstractWorkflowTest {
.build()
).build()).close();
runOnServer.run((RunOnServer) session -> {
// check the same users are now scheduled to run the second step.
WorkflowProvider provider = session.getProvider(WorkflowProvider.class);
List<Workflow> registeredWorkflows = provider.getWorkflows().toList();
assertThat(registeredWorkflows, hasSize(1));
// activate the workflow for all eligible users
provider.activateForAllEligibleResources(registeredWorkflows.get(0));
});
List<WorkflowRepresentation> workflows = managedRealm.admin().workflows().list();
assertThat(workflows, hasSize(1));
// activate the workflow for all eligible users
managedRealm.admin().workflows().workflow(workflows.get(0).getId()).activateAll();
runOnServer.run((RunOnServer) session -> {
// check the same users are now scheduled to run the second step.

View File

@@ -90,14 +90,10 @@ public class UserAttributeWorkflowConditionTest extends AbstractWorkflowTest {
createWorkflow(Map.of("key", List.of("value")));
runOnServer.run((RunOnServer) session -> {
// check the same users are now scheduled to run the second step.
WorkflowProvider provider = session.getProvider(WorkflowProvider.class);
List<Workflow> registeredWorkflows = provider.getWorkflows().toList();
assertThat(registeredWorkflows, hasSize(1));
// activate the workflow for all eligible users
provider.activateForAllEligibleResources(registeredWorkflows.get(0));
});
List<WorkflowRepresentation> workflows = managedRealm.admin().workflows().list();
assertThat(workflows, hasSize(1));
// activate the workflow for all eligible users
managedRealm.admin().workflows().workflow(workflows.get(0).getId()).activateAll();
runOnServer.run((RunOnServer) session -> {
// check the same users are now scheduled to run the second step.

View File

@@ -626,15 +626,12 @@ public class WorkflowManagementTest extends AbstractWorkflowTest {
assertTrue(user.getUsername().startsWith("new-idp-user-"));
});
});
runOnServer.run((RunOnServer) session -> {
// check the same users are now scheduled to run the second step.
WorkflowProvider provider = session.getProvider(WorkflowProvider.class);
List<Workflow> registeredWorkflows = provider.getWorkflows().toList();
assertEquals(1, registeredWorkflows.size());
Workflow workflow = registeredWorkflows.get(0);
// activate the workflow for all eligible users - i.e. only users from the same idp who are not yet assigned to the workflow.
provider.activateForAllEligibleResources(workflow);
});
List<WorkflowRepresentation> workflows = managedRealm.admin().workflows().list();
assertThat(workflows, hasSize(1));
// activate the workflow for all eligible users - i.e. only users from the same idp who are not yet assigned to the workflow.
managedRealm.admin().workflows().workflow(workflows.get(0).getId()).activateAll();
runOnServer.run((RunOnServer) session -> {
RealmModel realm = session.getContext().getRealm();
// check the same users are now scheduled to run the second step.