mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-10 15:32:05 -03:30
Add enabled config option to resource policies
Closes #42104 Signed-off-by: Stefan Guilhen <sguilhen@redhat.com>
This commit is contained in:
parent
ca93863d60
commit
05fa5cb552
@ -63,4 +63,8 @@ public class ResourcePolicy {
|
||||
public MultivaluedHashMap<String, String> getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return config != null && Boolean.parseBoolean(config.getFirstOrDefault("enabled", "true"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -219,12 +219,14 @@ public class ResourcePolicyManager {
|
||||
}
|
||||
|
||||
public void scheduleAllEligibleResources(ResourcePolicy policy) {
|
||||
ResourcePolicyProvider provider = getPolicyProvider(policy);
|
||||
ResourceAction firstAction = getFirstAction(policy);
|
||||
provider.getEligibleResourcesForInitialAction().forEach(resourceId -> {
|
||||
// TODO run each scheduling task in a separate tx as other txs might schedule an action while this is running.
|
||||
this.policyStateProvider.scheduleAction(policy, firstAction, resourceId);
|
||||
});
|
||||
if (policy.isEnabled()) {
|
||||
ResourcePolicyProvider provider = getPolicyProvider(policy);
|
||||
ResourceAction firstAction = getFirstAction(policy);
|
||||
provider.getEligibleResourcesForInitialAction().forEach(resourceId -> {
|
||||
// TODO run each scheduling task in a separate tx as other txs might schedule an action while this is running.
|
||||
this.policyStateProvider.scheduleAction(policy, firstAction, resourceId);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void processEvent(ResourcePolicyEvent event) {
|
||||
@ -235,7 +237,7 @@ public class ResourcePolicyManager {
|
||||
|
||||
// iterate through the policies, and for those not yet assigned to the user check if they can be assigned
|
||||
policies.stream()
|
||||
.filter(policy -> !getActions(policy).isEmpty())
|
||||
.filter(policy -> policy.isEnabled() && !getActions(policy).isEmpty())
|
||||
.forEach(policy -> {
|
||||
ResourcePolicyProvider provider = getPolicyProvider(policy);
|
||||
if (!currentlyAssignedPolicies.contains(policy.getId())) {
|
||||
@ -253,7 +255,7 @@ public class ResourcePolicyManager {
|
||||
}
|
||||
|
||||
public void runScheduledTasks() {
|
||||
for (ResourcePolicy policy : getPolicies()) {
|
||||
this.getPolicies().stream().filter(ResourcePolicy::isEnabled).forEach(policy -> {
|
||||
|
||||
for (ScheduledAction scheduled : policyStateProvider.getDueScheduledActions(policy)) {
|
||||
List<ResourceAction> actions = getActions(policy);
|
||||
@ -274,7 +276,7 @@ public class ResourcePolicyManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void removePolicy(String id) {
|
||||
|
||||
@ -20,6 +20,7 @@ package org.keycloak.tests.admin.model.policy;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@ -347,6 +348,114 @@ public class ResourcePolicyManagementTest {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisableResourcePolicy() {
|
||||
// create a test policy
|
||||
managedRealm.admin().resources().policies().create(ResourcePolicyRepresentation.create()
|
||||
.of(UserCreationTimeResourcePolicyProviderFactory.ID)
|
||||
.name("test-policy")
|
||||
.withConfig("enabled", "true")
|
||||
.withActions(
|
||||
ResourcePolicyActionRepresentation.create().of(NotifyUserActionProviderFactory.ID)
|
||||
.after(Duration.ofDays(5))
|
||||
.build(),
|
||||
ResourcePolicyActionRepresentation.create().of(DisableUserActionProviderFactory.ID)
|
||||
.after(Duration.ofDays(10))
|
||||
.build()
|
||||
).build()).close();
|
||||
|
||||
RealmResourcePolicies policies = managedRealm.admin().resources().policies();
|
||||
List<ResourcePolicyRepresentation> actualPolicies = policies.list();
|
||||
assertThat(actualPolicies, Matchers.hasSize(1));
|
||||
ResourcePolicyRepresentation policy = actualPolicies.get(0);
|
||||
assertThat(policy.getName(), is("test-policy"));
|
||||
|
||||
// create a new user - should bind the user to the policy and setup the first action
|
||||
managedRealm.admin().users().create(UserConfigBuilder.create().username("testuser").build());
|
||||
|
||||
runOnServer.run((RunOnServer) session -> {
|
||||
RealmModel realm = configureSessionContext(session);
|
||||
ResourcePolicyManager manager = new ResourcePolicyManager(session);
|
||||
|
||||
try {
|
||||
// Advance time so the user is eligible for the first action, then run the scheduled actions so they transition to the next one.
|
||||
Time.setOffset(Math.toIntExact(Duration.ofDays(6).toSeconds()));
|
||||
manager.runScheduledTasks();
|
||||
|
||||
UserModel user = session.users().getUserByUsername(realm, "testuser");
|
||||
// Verify that ONLY the first action (notify) was executed.
|
||||
assertNotNull(user.getAttributes().get("message"), "The first action (notify) should have run.");
|
||||
assertTrue(user.isEnabled(), "The second action (disable) should NOT have run.");
|
||||
} finally {
|
||||
Time.setOffset(0);
|
||||
}
|
||||
});
|
||||
|
||||
// disable the policy - scheduled actions should be paused and policy should not activate for new users
|
||||
policy.getConfig().putSingle("enabled", "false");
|
||||
managedRealm.admin().resources().policies().policy(policy.getId()).update(policy).close();
|
||||
|
||||
// create another user - should NOT bind the user to the policy as it is disabled
|
||||
managedRealm.admin().users().create(UserConfigBuilder.create().username("anotheruser").build());
|
||||
|
||||
runOnServer.run((RunOnServer) session -> {
|
||||
RealmModel realm = configureSessionContext(session);
|
||||
ResourcePolicyManager manager = new ResourcePolicyManager(session);
|
||||
|
||||
List<ResourcePolicy> registeredPolicies = manager.getPolicies();
|
||||
assertEquals(1, registeredPolicies.size());
|
||||
ResourcePolicyStateProvider stateProvider = session.getKeycloakSessionFactory().getProviderFactory(ResourcePolicyStateProvider.class).create(session);
|
||||
List<ResourcePolicyStateProvider.ScheduledAction> scheduledActions = stateProvider.getScheduledActionsByPolicy(registeredPolicies.get(0));
|
||||
|
||||
// verify that there's only one scheduled action, for the first user
|
||||
assertEquals(1, scheduledActions.size());
|
||||
UserModel scheduledActionUser = session.users().getUserById(realm, scheduledActions.get(0).resourceId());
|
||||
assertNotNull(scheduledActionUser);
|
||||
assertTrue(scheduledActionUser.getUsername().startsWith("testuser"));
|
||||
|
||||
try {
|
||||
// Advance time so the first user would be eligible for the second action, then run the scheduled actions.
|
||||
Time.setOffset(Math.toIntExact(Duration.ofDays(12).toSeconds()));
|
||||
manager.runScheduledTasks();
|
||||
|
||||
UserModel user = session.users().getUserByUsername(realm, "testuser");
|
||||
// Verify that the action was NOT executed as the policy is disabled.
|
||||
assertTrue(user.isEnabled(), "The second action (disable) should NOT have run as the policy is disabled.");
|
||||
} finally {
|
||||
Time.setOffset(0);
|
||||
}
|
||||
});
|
||||
|
||||
// re-enable the policy - scheduled actions should resume and new users should be bound to the policy
|
||||
policy.getConfig().putSingle("enabled", "true");
|
||||
managedRealm.admin().resources().policies().policy(policy.getId()).update(policy).close();
|
||||
|
||||
// create a third user - should bind the user to the policy as it is enabled again
|
||||
managedRealm.admin().users().create(UserConfigBuilder.create().username("thirduser").build());
|
||||
|
||||
runOnServer.run((RunOnServer) session -> {
|
||||
RealmModel realm = configureSessionContext(session);
|
||||
ResourcePolicyManager manager = new ResourcePolicyManager(session);
|
||||
|
||||
try {
|
||||
// Advance time so the first user would be eligible for the second action, and third user would be eligible for the first action, then run the scheduled actions.
|
||||
Time.setOffset(Math.toIntExact(Duration.ofDays(12).toSeconds()));
|
||||
manager.runScheduledTasks();
|
||||
|
||||
UserModel user = session.users().getUserByUsername(realm, "testuser");
|
||||
// Verify that the action was executed as the policy was re-enabled.
|
||||
assertFalse(user.isEnabled(), "The second action (disable) should have run as the policy was re-enabled.");
|
||||
|
||||
// Verify that the third user was bound to the policy and had the first action executed.
|
||||
user = session.users().getUserByUsername(realm, "thirduser");
|
||||
assertNotNull(user.getAttributes().get("message"), "The first action (notify) should have run.");
|
||||
assertTrue(user.isEnabled(), "The second action (disable) should NOT have run");
|
||||
} finally {
|
||||
Time.setOffset(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static RealmModel configureSessionContext(KeycloakSession session) {
|
||||
RealmModel realm = session.realms().getRealmByName(REALM_NAME);
|
||||
session.getContext().setRealm(realm);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user