Skip to content

Commit 5939864

Browse files
ksushant881pedroigor
authored andcommitted
Add action that removes a required action step in workflow
Closes #44647 Signed-off-by: ksushant881 <ksushant881@gmail.com>
1 parent 0885062 commit 5939864

4 files changed

Lines changed: 164 additions & 1 deletion

File tree

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package org.keycloak.models.workflow;
2+
3+
import org.keycloak.component.ComponentModel;
4+
import org.keycloak.models.KeycloakSession;
5+
import org.keycloak.models.RealmModel;
6+
import org.keycloak.models.UserModel;
7+
8+
import org.jboss.logging.Logger;
9+
10+
11+
public class RemoveRequiredActionStepProvider implements WorkflowStepProvider {
12+
13+
public static String REQUIRED_ACTION_KEY = "action";
14+
15+
private final KeycloakSession session;
16+
private final ComponentModel stepModel;
17+
private final Logger log = Logger.getLogger(RemoveRequiredActionStepProvider.class);
18+
19+
public RemoveRequiredActionStepProvider(KeycloakSession session, ComponentModel model) {
20+
this.session = session;
21+
this.stepModel = model;
22+
}
23+
24+
@Override
25+
public void run(WorkflowExecutionContext context) {
26+
RealmModel realm = session.getContext().getRealm();
27+
UserModel user = session.users().getUserById(realm, context.getResourceId());
28+
29+
if (user != null) {
30+
try {
31+
UserModel.RequiredAction action = UserModel.RequiredAction.valueOf(stepModel.getConfig().getFirst(REQUIRED_ACTION_KEY));
32+
log.debugv("Removing required action {0} from user {1})", action, user.getId());
33+
user.removeRequiredAction(action);
34+
} catch (IllegalArgumentException e) {
35+
log.warnv("Invalid required action {0} configured in RemoveRequiredActionStepProvider", stepModel.getConfig().getFirst(REQUIRED_ACTION_KEY));
36+
}
37+
}
38+
}
39+
40+
@Override
41+
public void close() {
42+
}
43+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package org.keycloak.models.workflow;
2+
3+
import java.util.List;
4+
5+
import org.keycloak.Config;
6+
import org.keycloak.component.ComponentModel;
7+
import org.keycloak.models.KeycloakSession;
8+
import org.keycloak.models.KeycloakSessionFactory;
9+
import org.keycloak.provider.ConfiguredProvider;
10+
import org.keycloak.provider.ProviderConfigProperty;
11+
import org.keycloak.provider.ProviderConfigurationBuilder;
12+
13+
public class RemoveRequiredActionStepProviderFactory implements WorkflowStepProviderFactory<RemoveRequiredActionStepProvider>, ConfiguredProvider {
14+
15+
public static final String ID = "remove-user-required-action";
16+
17+
@Override
18+
public RemoveRequiredActionStepProvider create(KeycloakSession session, ComponentModel model) {
19+
return new RemoveRequiredActionStepProvider(session, model);
20+
}
21+
22+
@Override
23+
public void init(Config.Scope config) {
24+
// no-op
25+
}
26+
27+
@Override
28+
public void postInit(KeycloakSessionFactory factory) {
29+
// no-op
30+
}
31+
32+
@Override
33+
public void close() {
34+
// no-op
35+
}
36+
37+
@Override
38+
public String getId() {
39+
return ID;
40+
}
41+
42+
@Override
43+
public List<ProviderConfigProperty> getConfigProperties() {
44+
return ProviderConfigurationBuilder.create()
45+
.property()
46+
.name("action")
47+
.label("Required Action")
48+
.helpText("The required action to remove from the user (e.g., UPDATE_PASSWORD)")
49+
.type(ProviderConfigProperty.STRING_TYPE)
50+
.add()
51+
.build();
52+
}
53+
54+
@Override
55+
public ResourceType getType() {
56+
return ResourceType.USERS;
57+
}
58+
59+
@Override
60+
public String getHelpText() {
61+
return "";
62+
}
63+
}

services/src/main/resources/META-INF/services/org.keycloak.models.workflow.WorkflowStepProviderFactory

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@ org.keycloak.models.workflow.AddRequiredActionStepProviderFactory
2323
org.keycloak.models.workflow.GrantRoleStepProviderFactory
2424
org.keycloak.models.workflow.RevokeRoleStepProviderFactory
2525
org.keycloak.models.workflow.JoinGroupStepProviderFactory
26-
org.keycloak.models.workflow.LeaveGroupStepProviderFactory
26+
org.keycloak.models.workflow.LeaveGroupStepProviderFactory
27+
org.keycloak.models.workflow.RemoveRequiredActionStepProviderFactory
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package org.keycloak.tests.workflow.step;
2+
3+
import java.time.Duration;
4+
5+
import org.keycloak.models.UserModel;
6+
import org.keycloak.models.workflow.RemoveRequiredActionStepProvider;
7+
import org.keycloak.models.workflow.RemoveRequiredActionStepProviderFactory;
8+
import org.keycloak.representations.workflows.WorkflowRepresentation;
9+
import org.keycloak.representations.workflows.WorkflowStepRepresentation;
10+
import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
11+
import org.keycloak.testframework.realm.UserConfigBuilder;
12+
import org.keycloak.tests.workflow.AbstractWorkflowTest;
13+
import org.keycloak.tests.workflow.config.WorkflowsBlockingServerConfig;
14+
15+
import org.awaitility.Awaitility;
16+
import org.junit.jupiter.api.Assertions;
17+
import org.junit.jupiter.api.Test;
18+
19+
import static org.keycloak.models.workflow.ResourceOperationType.USER_CREATED;
20+
21+
import static org.hamcrest.MatcherAssert.assertThat;
22+
import static org.hamcrest.Matchers.hasSize;
23+
24+
/**
25+
* Tests the execution of the 'remove-required-action' workflow step.
26+
*/
27+
@KeycloakIntegrationTest(config = WorkflowsBlockingServerConfig.class)
28+
public class RemoveRequiredActionTest extends AbstractWorkflowTest {
29+
30+
@Test
31+
public void testStepRun() {
32+
managedRealm.admin().workflows().create(WorkflowRepresentation.withName("remove-action-workflow")
33+
.onEvent(USER_CREATED.name())
34+
.withSteps(
35+
WorkflowStepRepresentation.create()
36+
.of(RemoveRequiredActionStepProviderFactory.ID)
37+
.withConfig(RemoveRequiredActionStepProvider.REQUIRED_ACTION_KEY, "UPDATE_PASSWORD")
38+
.build()
39+
).build()).close();
40+
41+
managedRealm.admin().users().create(UserConfigBuilder.create()
42+
.username("testuser_remove")
43+
.requiredActions(UserModel.RequiredAction.UPDATE_PASSWORD.name())
44+
.build()).close();
45+
46+
Awaitility.await()
47+
.timeout(Duration.ofSeconds(30))
48+
.pollInterval(Duration.ofSeconds(1))
49+
.untilAsserted(() -> {
50+
var users = managedRealm.admin().users().search("testuser_remove");
51+
assertThat(users, hasSize(1));
52+
var userRepresentation = users.get(0);
53+
Assertions.assertTrue(userRepresentation.getRequiredActions() == null || userRepresentation.getRequiredActions().isEmpty());
54+
});
55+
}
56+
}

0 commit comments

Comments
 (0)