mirror of
https://github.com/keycloak/keycloak.git
synced 2026-06-11 01:50:04 -04:00
Merge 70aef7583c into 94dcc24a8d
This commit is contained in:
commit
16df2b6d92
2 changed files with 94 additions and 14 deletions
|
|
@ -95,7 +95,6 @@ import org.keycloak.policy.PasswordPolicyNotMetException;
|
|||
import org.keycloak.protocol.oid4vc.resources.admin.UserVerifiableCredentialResource;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
import org.keycloak.protocol.oidc.utils.RedirectUtils;
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.representations.idm.ErrorRepresentation;
|
||||
import org.keycloak.representations.idm.FederatedIdentityRepresentation;
|
||||
|
|
@ -306,18 +305,14 @@ public class UserResource {
|
|||
List<String> reqActions = rep.getRequiredActions();
|
||||
|
||||
if (reqActions != null) {
|
||||
session.getKeycloakSessionFactory()
|
||||
.getProviderFactoriesStream(RequiredActionProvider.class)
|
||||
.map(ProviderFactory::getId)
|
||||
.distinct()
|
||||
.sorted()
|
||||
.forEach(action -> {
|
||||
if (reqActions.contains(action)) {
|
||||
user.addRequiredAction(action);
|
||||
} else if (removeMissingRequiredActions) {
|
||||
user.removeRequiredAction(action);
|
||||
}
|
||||
});
|
||||
if (removeMissingRequiredActions) {
|
||||
user.getRequiredActionsStream().toList().forEach(user::removeRequiredAction);
|
||||
}
|
||||
|
||||
reqActions.stream()
|
||||
.filter(action -> session.getKeycloakSessionFactory()
|
||||
.getProviderFactory(RequiredActionProvider.class, action) != null)
|
||||
.forEach(user::addRequiredAction);
|
||||
}
|
||||
|
||||
List<CredentialRepresentation> credentials = rep.getCredentials();
|
||||
|
|
|
|||
|
|
@ -1,13 +1,19 @@
|
|||
package org.keycloak.tests.admin.user;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.keycloak.admin.client.resource.UserResource;
|
||||
import org.keycloak.events.admin.OperationType;
|
||||
import org.keycloak.events.admin.ResourceType;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.representations.idm.RequiredActionProviderRepresentation;
|
||||
import org.keycloak.representations.idm.RequiredActionProviderSimpleRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
|
||||
import org.keycloak.testframework.events.AdminEventAssertion;
|
||||
import org.keycloak.testframework.server.KeycloakServerConfig;
|
||||
import org.keycloak.testframework.server.KeycloakServerConfigBuilder;
|
||||
import org.keycloak.tests.providers.actions.DummyRequiredActionFactory;
|
||||
import org.keycloak.tests.suites.DatabaseTest;
|
||||
import org.keycloak.tests.utils.admin.AdminEventPaths;
|
||||
|
||||
|
|
@ -17,7 +23,7 @@ import org.junit.jupiter.api.Test;
|
|||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@KeycloakIntegrationTest
|
||||
@KeycloakIntegrationTest(config = UserRequiredActionsTest.CustomProvidersServerConfig.class)
|
||||
public class UserRequiredActionsTest extends AbstractUserTest {
|
||||
|
||||
@Test
|
||||
|
|
@ -77,4 +83,83 @@ public class UserRequiredActionsTest extends AbstractUserTest {
|
|||
managedRealm.admin().flows().updateRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD.toString(), updatePasswordReqAction);
|
||||
AdminEventAssertion.assertEvent(adminEvents.poll(), OperationType.UPDATE, AdminEventPaths.authRequiredActionPath(UserModel.RequiredAction.UPDATE_PASSWORD.toString()), updatePasswordReqAction, ResourceType.REQUIRED_ACTION);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DatabaseTest
|
||||
public void removeCustomRequiredAction() {
|
||||
registerDummyRequiredAction();
|
||||
|
||||
String id = createUser();
|
||||
UserResource user = managedRealm.admin().users().get(id);
|
||||
|
||||
// Add the custom required action to the user
|
||||
UserRepresentation userRep = user.toRepresentation();
|
||||
userRep.getRequiredActions().add(DummyRequiredActionFactory.PROVIDER_ID);
|
||||
updateUser(user, userRep);
|
||||
|
||||
userRep = user.toRepresentation();
|
||||
assertEquals(1, userRep.getRequiredActions().size());
|
||||
assertEquals(DummyRequiredActionFactory.PROVIDER_ID, userRep.getRequiredActions().get(0));
|
||||
|
||||
// Remove the custom required action by sending an empty list
|
||||
userRep.getRequiredActions().clear();
|
||||
updateUser(user, userRep);
|
||||
|
||||
userRep = user.toRepresentation();
|
||||
assertTrue(userRep.getRequiredActions().isEmpty(),
|
||||
"Custom required action should be removed but was still present: " + userRep.getRequiredActions());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DatabaseTest
|
||||
public void removeCustomRequiredActionKeepBuiltIn() {
|
||||
registerDummyRequiredAction();
|
||||
|
||||
String id = createUser();
|
||||
UserResource user = managedRealm.admin().users().get(id);
|
||||
|
||||
// Add both a built-in and custom required action
|
||||
UserRepresentation userRep = user.toRepresentation();
|
||||
userRep.getRequiredActions().add(UserModel.RequiredAction.UPDATE_PASSWORD.toString());
|
||||
userRep.getRequiredActions().add(DummyRequiredActionFactory.PROVIDER_ID);
|
||||
updateUser(user, userRep);
|
||||
|
||||
userRep = user.toRepresentation();
|
||||
assertEquals(2, userRep.getRequiredActions().size());
|
||||
|
||||
// Remove only the custom action, keep the built-in one
|
||||
userRep.setRequiredActions(List.of(UserModel.RequiredAction.UPDATE_PASSWORD.toString()));
|
||||
updateUser(user, userRep);
|
||||
|
||||
userRep = user.toRepresentation();
|
||||
assertEquals(1, userRep.getRequiredActions().size());
|
||||
assertEquals(UserModel.RequiredAction.UPDATE_PASSWORD.toString(), userRep.getRequiredActions().get(0));
|
||||
}
|
||||
|
||||
private void registerDummyRequiredAction() {
|
||||
RequiredActionProviderSimpleRepresentation action = managedRealm.admin().flows().getUnregisteredRequiredActions()
|
||||
.stream()
|
||||
.filter(a -> a.getProviderId().equals(DummyRequiredActionFactory.PROVIDER_ID))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new AssertionError("Dummy required action not found"));
|
||||
managedRealm.admin().flows().registerRequiredAction(action);
|
||||
AdminEventAssertion.assertEvent(adminEvents.poll(), OperationType.CREATE,
|
||||
AdminEventPaths.authMgmtBasePath() + "/register-required-action", action, ResourceType.REQUIRED_ACTION);
|
||||
|
||||
managedRealm.cleanup().add(r -> {
|
||||
try {
|
||||
r.flows().removeRequiredAction(DummyRequiredActionFactory.PROVIDER_ID);
|
||||
} catch (jakarta.ws.rs.NotFoundException ignored) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static class CustomProvidersServerConfig implements KeycloakServerConfig {
|
||||
|
||||
@Override
|
||||
public KeycloakServerConfigBuilder configure(KeycloakServerConfigBuilder config) {
|
||||
return config.dependency("org.keycloak.tests", "keycloak-tests-custom-providers");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue