Move User Storage SPI, introduce ExportImportManager

This commit is contained in:
Alexander Schwartz 2022-04-26 16:57:10 +02:00 committed by Hynek Mlnařík
parent 703e868a51
commit 82094d113e
63 changed files with 1680 additions and 1482 deletions

View file

@ -27,6 +27,7 @@ import org.keycloak.provider.ProviderFactory;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.UserStorageUtil;
import javax.naming.directory.SearchControls;
import java.util.List;
@ -52,7 +53,7 @@ public class MigrateTo1_3_0 implements Migration {
}
private void migrateLDAPProviders(KeycloakSession session, RealmModel realm) {
realm.getUserStorageProvidersStream().forEachOrdered(fedProvider -> {
UserStorageUtil.getUserStorageProvidersStream(realm).forEachOrdered(fedProvider -> {
if (fedProvider.getProviderId().equals(LDAPConstants.LDAP_PROVIDER)) {
fedProvider = new UserStorageProviderModel(fedProvider); // copy don't want to muck with cache
MultivaluedHashMap<String, String> config = fedProvider.getConfig();

View file

@ -29,6 +29,7 @@ import org.keycloak.models.utils.DefaultAuthenticationFlows;
import org.keycloak.models.utils.DefaultRequiredActions;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.storage.UserStorageUtil;
import java.util.Arrays;
import java.util.List;
@ -67,7 +68,7 @@ public class MigrateTo1_4_0 implements Migration {
private void migrateLDAPMappers(KeycloakSession session, RealmModel realm) {
List<String> mandatoryInLdap = Arrays.asList("username", "username-cn", "first name", "last name");
realm.getUserStorageProvidersStream()
UserStorageUtil.getUserStorageProvidersStream(realm)
.filter(providerModel -> Objects.equals(providerModel.getProviderId(), LDAPConstants.LDAP_PROVIDER))
.forEachOrdered(providerModel -> realm.getComponentsStream(providerModel.getId())
.filter(mapper -> mandatoryInLdap.contains(mapper.getName()))

View file

@ -25,6 +25,7 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.UserStorageUtil;
import java.util.Objects;
@ -50,7 +51,7 @@ public class MigrateTo1_8_0 implements Migration {
}
protected void migrateRealm(RealmModel realm) {
realm.getUserStorageProvidersStream()
UserStorageUtil.getUserStorageProvidersStream(realm)
.filter(fedProvider -> Objects.equals(fedProvider.getProviderId(), LDAPConstants.LDAP_PROVIDER))
.filter(this::isActiveDirectory)
.filter(fedProvider -> Objects.isNull(getMapperByName(realm, fedProvider, "MSAD account controls")))

View file

@ -12,13 +12,14 @@ import org.keycloak.models.cache.UserCache;
import org.keycloak.storage.ClientScopeStorageManager;
import org.keycloak.storage.ClientStorageManager;
import org.keycloak.storage.DatastoreProvider;
import org.keycloak.storage.ExportImportManager;
import org.keycloak.storage.GroupStorageManager;
import org.keycloak.storage.LegacyStoreManagers;
import org.keycloak.storage.MigrationManager;
import org.keycloak.storage.RoleStorageManager;
import org.keycloak.storage.UserStorageManager;
public class LegacyDatastoreProvider implements DatastoreProvider, LegacyStoreManagers {
private final LegacyDatastoreProviderFactory factory;
private final KeycloakSession session;
@ -184,4 +185,15 @@ public class LegacyDatastoreProvider implements DatastoreProvider, LegacyStoreMa
}
return userProvider;
}
@Override
public ExportImportManager getExportImportManager() {
return new LegacyExportImportManager(session);
}
@Override
public MigrationManager getMigrationManager() {
return new LegacyMigrationManager(session);
}
}

View file

@ -0,0 +1,181 @@
package org.keycloak.storage.datastore;
import org.jboss.logging.Logger;
import org.keycloak.common.Version;
import org.keycloak.migration.MigrationModel;
import org.keycloak.migration.ModelVersion;
import org.keycloak.migration.migrators.MigrateTo12_0_0;
import org.keycloak.migration.migrators.MigrateTo14_0_0;
import org.keycloak.migration.migrators.MigrateTo18_0_0;
import org.keycloak.migration.migrators.MigrateTo1_2_0;
import org.keycloak.migration.migrators.MigrateTo1_3_0;
import org.keycloak.migration.migrators.MigrateTo1_4_0;
import org.keycloak.migration.migrators.MigrateTo1_5_0;
import org.keycloak.migration.migrators.MigrateTo1_6_0;
import org.keycloak.migration.migrators.MigrateTo1_7_0;
import org.keycloak.migration.migrators.MigrateTo1_8_0;
import org.keycloak.migration.migrators.MigrateTo1_9_0;
import org.keycloak.migration.migrators.MigrateTo1_9_2;
import org.keycloak.migration.migrators.MigrateTo2_0_0;
import org.keycloak.migration.migrators.MigrateTo2_1_0;
import org.keycloak.migration.migrators.MigrateTo2_2_0;
import org.keycloak.migration.migrators.MigrateTo2_3_0;
import org.keycloak.migration.migrators.MigrateTo2_5_0;
import org.keycloak.migration.migrators.MigrateTo3_0_0;
import org.keycloak.migration.migrators.MigrateTo3_1_0;
import org.keycloak.migration.migrators.MigrateTo3_2_0;
import org.keycloak.migration.migrators.MigrateTo3_4_0;
import org.keycloak.migration.migrators.MigrateTo3_4_1;
import org.keycloak.migration.migrators.MigrateTo3_4_2;
import org.keycloak.migration.migrators.MigrateTo4_0_0;
import org.keycloak.migration.migrators.MigrateTo4_2_0;
import org.keycloak.migration.migrators.MigrateTo4_6_0;
import org.keycloak.migration.migrators.MigrateTo6_0_0;
import org.keycloak.migration.migrators.MigrateTo8_0_0;
import org.keycloak.migration.migrators.MigrateTo8_0_2;
import org.keycloak.migration.migrators.MigrateTo9_0_0;
import org.keycloak.migration.migrators.MigrateTo9_0_4;
import org.keycloak.migration.migrators.Migration;
import org.keycloak.models.Constants;
import org.keycloak.models.DeploymentStateProvider;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.storage.MigrationManager;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.regex.Pattern;
/**
* This wraps the functionality for migrations of the legacy storage. This will be handled differently for the new map storage,
* therefore, it has been extracted.
*
* @author Alexander Schwartz
*/
public class LegacyMigrationManager implements MigrationManager {
private static final Logger logger = Logger.getLogger(LegacyMigrationManager.class);
private static final Migration[] migrations = {
new MigrateTo1_2_0(),
new MigrateTo1_3_0(),
new MigrateTo1_4_0(),
new MigrateTo1_5_0(),
new MigrateTo1_6_0(),
new MigrateTo1_7_0(),
new MigrateTo1_8_0(),
new MigrateTo1_9_0(),
new MigrateTo1_9_2(),
new MigrateTo2_0_0(),
new MigrateTo2_1_0(),
new MigrateTo2_2_0(),
new MigrateTo2_3_0(),
new MigrateTo2_5_0(),
new MigrateTo3_0_0(),
new MigrateTo3_1_0(),
new MigrateTo3_2_0(),
new MigrateTo3_4_0(),
new MigrateTo3_4_1(),
new MigrateTo3_4_2(),
new MigrateTo4_0_0(),
new MigrateTo4_2_0(),
new MigrateTo4_6_0(),
new MigrateTo6_0_0(),
new MigrateTo8_0_0(),
new MigrateTo8_0_2(),
new MigrateTo9_0_0(),
new MigrateTo9_0_4(),
new MigrateTo12_0_0(),
new MigrateTo14_0_0(),
new MigrateTo18_0_0()
};
private final KeycloakSession session;
public LegacyMigrationManager(KeycloakSession session) {
this.session = session;
}
public void migrate() {
session.setAttribute(Constants.STORAGE_BATCH_ENABLED, Boolean.getBoolean("keycloak.migration.batch-enabled"));
session.setAttribute(Constants.STORAGE_BATCH_SIZE, Integer.getInteger("keycloak.migration.batch-size"));
MigrationModel model = session.getProvider(DeploymentStateProvider.class).getMigrationModel();
ModelVersion currentVersion = new ModelVersion(Version.VERSION_KEYCLOAK);
ModelVersion latestUpdate = migrations[migrations.length-1].getVersion();
ModelVersion databaseVersion = model.getStoredVersion() != null ? new ModelVersion(model.getStoredVersion()) : null;
if (databaseVersion == null || databaseVersion.lessThan(latestUpdate)) {
for (Migration m : migrations) {
if (databaseVersion == null || databaseVersion.lessThan(m.getVersion())) {
if (databaseVersion != null) {
logger.debugf("Migrating older model to %s", m.getVersion());
}
m.migrate(session);
}
}
}
if (databaseVersion == null || databaseVersion.lessThan(currentVersion)) {
model.setStoredVersion(currentVersion.toString());
}
Version.RESOURCES_VERSION = model.getResourcesTag();
}
public static final ModelVersion RHSSO_VERSION_7_0_KEYCLOAK_VERSION = new ModelVersion("1.9.8");
public static final ModelVersion RHSSO_VERSION_7_1_KEYCLOAK_VERSION = new ModelVersion("2.5.5");
public static final ModelVersion RHSSO_VERSION_7_2_KEYCLOAK_VERSION = new ModelVersion("3.4.3");
public static final ModelVersion RHSSO_VERSION_7_3_KEYCLOAK_VERSION = new ModelVersion("4.8.3");
public static final ModelVersion RHSSO_VERSION_7_4_KEYCLOAK_VERSION = new ModelVersion("9.0.3");
private static final Map<Pattern, ModelVersion> PATTERN_MATCHER = new LinkedHashMap<>();
static {
PATTERN_MATCHER.put(Pattern.compile("^7\\.0\\.\\d+\\.GA$"), RHSSO_VERSION_7_0_KEYCLOAK_VERSION);
PATTERN_MATCHER.put(Pattern.compile("^7\\.1\\.\\d+\\.GA$"), RHSSO_VERSION_7_1_KEYCLOAK_VERSION);
PATTERN_MATCHER.put(Pattern.compile("^7\\.2\\.\\d+\\.GA$"), RHSSO_VERSION_7_2_KEYCLOAK_VERSION);
PATTERN_MATCHER.put(Pattern.compile("^7\\.3\\.\\d+\\.GA$"), RHSSO_VERSION_7_3_KEYCLOAK_VERSION);
PATTERN_MATCHER.put(Pattern.compile("^7\\.4\\.\\d+\\.GA$"), RHSSO_VERSION_7_4_KEYCLOAK_VERSION);
}
public void migrate(RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
ModelVersion stored = null;
if (rep.getKeycloakVersion() != null) {
stored = convertRHSSOVersionToKeycloakVersion(rep.getKeycloakVersion());
if (stored == null) {
stored = new ModelVersion(rep.getKeycloakVersion());
}
}
if (stored == null) {
stored = migrations[0].getVersion();
}
for (Migration m : migrations) {
if (stored == null || stored.lessThan(m.getVersion())) {
if (stored != null) {
logger.debugf("Migrating older json representation to %s", m.getVersion());
}
try {
m.migrateImport(session, realm, rep, skipUserDependent);
} catch (Exception e) {
logger.error("Failed to migrate json representation for version: " + m.getVersion(), e);
}
}
}
}
public static ModelVersion convertRHSSOVersionToKeycloakVersion(String version) {
// look for the keycloakVersion pattern to identify it as RH SSO
for (Pattern pattern : PATTERN_MATCHER.keySet()) {
if (pattern.matcher(version).find()) {
return PATTERN_MATCHER.get(pattern);
}
}
// chceck if the version is in format for CD releases, e.g.: "keycloakVersion": "6"
if (Pattern.compile("^[0-9]*$").matcher(version).find()) {
return new ModelVersion(Integer.parseInt(version), 0, 0);
}
return null;
}
}

View file

@ -31,6 +31,7 @@ import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderFactory;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.UserStorageUtil;
import org.keycloak.storage.user.ImportSynchronization;
import org.keycloak.storage.user.SynchronizationResult;
import org.keycloak.timer.TimerProvider;
@ -61,7 +62,7 @@ public class UserStorageSyncManager {
public void run(KeycloakSession session) {
Stream<RealmModel> realms = session.realms().getRealmsWithProviderTypeStream(UserStorageProvider.class);
realms.forEach(realm -> {
Stream<UserStorageProviderModel> providers = realm.getUserStorageProvidersStream();
Stream<UserStorageProviderModel> providers = UserStorageUtil.getUserStorageProvidersStream(realm);
providers.forEachOrdered(provider -> {
UserStorageProviderFactory factory = (UserStorageProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(UserStorageProvider.class, provider.getProviderId());
if (factory instanceof ImportSynchronization && provider.isImportEnabled()) {
@ -165,7 +166,7 @@ public class UserStorageSyncManager {
public static void notifyToRefreshPeriodicSyncAll(KeycloakSession session, RealmModel realm, boolean removed) {
realm.getUserStorageProvidersStream().forEachOrdered(fedProvider ->
UserStorageUtil.getUserStorageProvidersStream(realm).forEachOrdered(fedProvider ->
notifyToRefreshPeriodicSync(session, realm, fedProvider, removed));
}
@ -267,7 +268,7 @@ public class UserStorageSyncManager {
@Override
public void run(KeycloakSession session) {
RealmModel persistentRealm = session.realms().getRealm(realmId);
persistentRealm.getUserStorageProvidersStream()
UserStorageUtil.getUserStorageProvidersStream(persistentRealm)
.filter(persistentFedProvider -> Objects.equals(provider.getId(), persistentFedProvider.getId()))
.forEachOrdered(persistentFedProvider -> {
// Update persistent provider in DB

View file

@ -0,0 +1,71 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.models.datastore;
import org.junit.Assert;
import org.junit.Test;
import org.keycloak.migration.ModelVersion;
import static org.keycloak.storage.datastore.LegacyMigrationManager.RHSSO_VERSION_7_0_KEYCLOAK_VERSION;
import static org.keycloak.storage.datastore.LegacyMigrationManager.RHSSO_VERSION_7_1_KEYCLOAK_VERSION;
import static org.keycloak.storage.datastore.LegacyMigrationManager.RHSSO_VERSION_7_2_KEYCLOAK_VERSION;
import static org.keycloak.storage.datastore.LegacyMigrationManager.RHSSO_VERSION_7_3_KEYCLOAK_VERSION;
import static org.keycloak.storage.datastore.LegacyMigrationManager.RHSSO_VERSION_7_4_KEYCLOAK_VERSION;
import static org.keycloak.storage.datastore.LegacyMigrationManager.convertRHSSOVersionToKeycloakVersion;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class LegacyMigrationManagerTest {
@Test
public void testRHSSOVersionToKeycloakVersionConversion() {
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.0.0.GA"), is(equalTo(RHSSO_VERSION_7_0_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.0.1.GA"), is(equalTo(RHSSO_VERSION_7_0_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.0.2.GA"), is(equalTo(RHSSO_VERSION_7_0_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.1.0.GA"), is(equalTo(RHSSO_VERSION_7_1_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.1.1.GA"), is(equalTo(RHSSO_VERSION_7_1_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.1.2.GA"), is(equalTo(RHSSO_VERSION_7_1_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.2.0.GA"), is(equalTo(RHSSO_VERSION_7_2_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.2.1.GA"), is(equalTo(RHSSO_VERSION_7_2_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.2.2.GA"), is(equalTo(RHSSO_VERSION_7_2_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.3.0.GA"), is(equalTo(RHSSO_VERSION_7_3_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.3.1.GA"), is(equalTo(RHSSO_VERSION_7_3_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.3.2.GA"), is(equalTo(RHSSO_VERSION_7_3_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.3.10.GA"), is(equalTo(RHSSO_VERSION_7_3_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.4.0.GA"), is(equalTo(RHSSO_VERSION_7_4_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.4.15.GA"), is(equalTo(RHSSO_VERSION_7_4_KEYCLOAK_VERSION)));
// check the conversion doesn't change version for keycloak
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.0.0"), is(nullValue()));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("8.0.0"), is(nullValue()));
// check for CD releases
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("6"), is(equalTo(new ModelVersion("6.0.0"))));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7"), is(equalTo(new ModelVersion("7.0.0"))));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("10"), is(equalTo(new ModelVersion("10.0.0"))));
}
}

View file

@ -25,7 +25,7 @@ import org.keycloak.events.admin.OperationType;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.services.ServicesLogger;
import org.keycloak.services.managers.UserStorageSyncManager;
import org.keycloak.storage.managers.UserStorageSyncManager;
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel;

View file

@ -0,0 +1,21 @@
package org.keycloak.storage;
import org.keycloak.models.RealmModel;
import java.util.stream.Stream;
/**
* @author Alexander Schwartz
*/
public class UserStorageUtil {
/**
* Returns sorted {@link UserStorageProviderModel UserStorageProviderModel} as a stream.
* It should be used with forEachOrdered if the ordering is required.
* @return Sorted stream of {@link UserStorageProviderModel}. Never returns {@code null}.
*/
public static Stream<UserStorageProviderModel> getUserStorageProvidersStream(RealmModel realm) {
return realm.getComponentsStream(realm.getId(), UserStorageProvider.class.getName())
.map(UserStorageProviderModel::new)
.sorted(UserStorageProviderModel.comparator);
}
}

View file

@ -21,7 +21,6 @@ import org.keycloak.Config;
import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.map.storage.ldap.role.config.LdapMapRoleMapperConfig;
import org.keycloak.storage.UserStorageProvider;
import javax.naming.directory.SearchControls;
import java.util.Collection;
@ -271,15 +270,6 @@ public class LdapMapConfig {
return Boolean.parseBoolean(config.getFirst(LDAPConstants.START_TLS));
}
public UserStorageProvider.EditMode getEditMode() {
String editModeString = config.getFirst(LDAPConstants.EDIT_MODE);
if (editModeString == null) {
return UserStorageProvider.EditMode.READ_ONLY;
} else {
return UserStorageProvider.EditMode.valueOf(editModeString);
}
}
public void addBinaryAttribute(String attrName) {
binaryAttributeNames.add(attrName);
}

View file

@ -48,7 +48,6 @@ import org.keycloak.models.map.storage.ModelCriteriaBuilder.Operator;
import org.keycloak.models.map.storage.criteria.DefaultModelCriteria;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.storage.StorageId;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.client.ClientStorageProvider;
import java.util.Collection;
@ -456,9 +455,6 @@ public class MapUserProvider implements UserProvider.Streams, UserCredentialStor
public void preRemove(RealmModel realm, ComponentModel component) {
String componentId = component.getId();
LOG.tracef("preRemove[ComponentModel](%s, %s)%s", realm, componentId, getShortStackTrace());
if (component.getProviderType().equals(UserStorageProvider.class.getName())) {
removeImportedUsers(realm, componentId);
}
if (component.getProviderType().equals(ClientStorageProvider.class.getName())) {
DefaultModelCriteria<UserModel> mcb = criteria();
mcb = mcb.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId())

View file

@ -17,169 +17,25 @@
package org.keycloak.migration;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.regex.Pattern;
import org.jboss.logging.Logger;
import org.keycloak.common.Version;
import org.keycloak.migration.migrators.MigrateTo12_0_0;
import org.keycloak.migration.migrators.MigrateTo14_0_0;
import org.keycloak.migration.migrators.MigrateTo18_0_0;
import org.keycloak.migration.migrators.MigrateTo1_2_0;
import org.keycloak.migration.migrators.MigrateTo1_3_0;
import org.keycloak.migration.migrators.MigrateTo1_4_0;
import org.keycloak.migration.migrators.MigrateTo1_5_0;
import org.keycloak.migration.migrators.MigrateTo1_6_0;
import org.keycloak.migration.migrators.MigrateTo1_7_0;
import org.keycloak.migration.migrators.MigrateTo1_8_0;
import org.keycloak.migration.migrators.MigrateTo1_9_0;
import org.keycloak.migration.migrators.MigrateTo1_9_2;
import org.keycloak.migration.migrators.MigrateTo2_0_0;
import org.keycloak.migration.migrators.MigrateTo2_1_0;
import org.keycloak.migration.migrators.MigrateTo2_2_0;
import org.keycloak.migration.migrators.MigrateTo2_3_0;
import org.keycloak.migration.migrators.MigrateTo2_5_0;
import org.keycloak.migration.migrators.MigrateTo3_0_0;
import org.keycloak.migration.migrators.MigrateTo3_1_0;
import org.keycloak.migration.migrators.MigrateTo3_2_0;
import org.keycloak.migration.migrators.MigrateTo3_4_0;
import org.keycloak.migration.migrators.MigrateTo3_4_1;
import org.keycloak.migration.migrators.MigrateTo3_4_2;
import org.keycloak.migration.migrators.MigrateTo4_0_0;
import org.keycloak.migration.migrators.MigrateTo4_2_0;
import org.keycloak.migration.migrators.MigrateTo4_6_0;
import org.keycloak.migration.migrators.MigrateTo6_0_0;
import org.keycloak.migration.migrators.MigrateTo8_0_0;
import org.keycloak.migration.migrators.MigrateTo8_0_2;
import org.keycloak.migration.migrators.MigrateTo9_0_0;
import org.keycloak.migration.migrators.MigrateTo9_0_4;
import org.keycloak.migration.migrators.Migration;
import org.keycloak.models.Constants;
import org.keycloak.models.DeploymentStateProvider;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.storage.DatastoreProvider;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Deprecated // as this will be moved to a legacy module
public class MigrationModelManager {
private static Logger logger = Logger.getLogger(MigrationModelManager.class);
private static final Migration[] migrations = {
new MigrateTo1_2_0(),
new MigrateTo1_3_0(),
new MigrateTo1_4_0(),
new MigrateTo1_5_0(),
new MigrateTo1_6_0(),
new MigrateTo1_7_0(),
new MigrateTo1_8_0(),
new MigrateTo1_9_0(),
new MigrateTo1_9_2(),
new MigrateTo2_0_0(),
new MigrateTo2_1_0(),
new MigrateTo2_2_0(),
new MigrateTo2_3_0(),
new MigrateTo2_5_0(),
new MigrateTo3_0_0(),
new MigrateTo3_1_0(),
new MigrateTo3_2_0(),
new MigrateTo3_4_0(),
new MigrateTo3_4_1(),
new MigrateTo3_4_2(),
new MigrateTo4_0_0(),
new MigrateTo4_2_0(),
new MigrateTo4_6_0(),
new MigrateTo6_0_0(),
new MigrateTo8_0_0(),
new MigrateTo8_0_2(),
new MigrateTo9_0_0(),
new MigrateTo9_0_4(),
new MigrateTo12_0_0(),
new MigrateTo14_0_0(),
new MigrateTo18_0_0()
};
public static void migrate(KeycloakSession session) {
session.setAttribute(Constants.STORAGE_BATCH_ENABLED, Boolean.getBoolean("keycloak.migration.batch-enabled"));
session.setAttribute(Constants.STORAGE_BATCH_SIZE, Integer.getInteger("keycloak.migration.batch-size"));
MigrationModel model = session.getProvider(DeploymentStateProvider.class).getMigrationModel();
ModelVersion currentVersion = new ModelVersion(Version.VERSION_KEYCLOAK);
ModelVersion latestUpdate = migrations[migrations.length-1].getVersion();
ModelVersion databaseVersion = model.getStoredVersion() != null ? new ModelVersion(model.getStoredVersion()) : null;
if (databaseVersion == null || databaseVersion.lessThan(latestUpdate)) {
for (Migration m : migrations) {
if (databaseVersion == null || databaseVersion.lessThan(m.getVersion())) {
if (databaseVersion != null) {
logger.debugf("Migrating older model to %s", m.getVersion());
}
m.migrate(session);
}
}
}
if (databaseVersion == null || databaseVersion.lessThan(currentVersion)) {
model.setStoredVersion(currentVersion.toString());
}
Version.RESOURCES_VERSION = model.getResourcesTag();
}
public static final ModelVersion RHSSO_VERSION_7_0_KEYCLOAK_VERSION = new ModelVersion("1.9.8");
public static final ModelVersion RHSSO_VERSION_7_1_KEYCLOAK_VERSION = new ModelVersion("2.5.5");
public static final ModelVersion RHSSO_VERSION_7_2_KEYCLOAK_VERSION = new ModelVersion("3.4.3");
public static final ModelVersion RHSSO_VERSION_7_3_KEYCLOAK_VERSION = new ModelVersion("4.8.3");
public static final ModelVersion RHSSO_VERSION_7_4_KEYCLOAK_VERSION = new ModelVersion("9.0.3");
private static final Map<Pattern, ModelVersion> PATTERN_MATCHER = new LinkedHashMap<>();
static {
PATTERN_MATCHER.put(Pattern.compile("^7\\.0\\.\\d+\\.GA$"), RHSSO_VERSION_7_0_KEYCLOAK_VERSION);
PATTERN_MATCHER.put(Pattern.compile("^7\\.1\\.\\d+\\.GA$"), RHSSO_VERSION_7_1_KEYCLOAK_VERSION);
PATTERN_MATCHER.put(Pattern.compile("^7\\.2\\.\\d+\\.GA$"), RHSSO_VERSION_7_2_KEYCLOAK_VERSION);
PATTERN_MATCHER.put(Pattern.compile("^7\\.3\\.\\d+\\.GA$"), RHSSO_VERSION_7_3_KEYCLOAK_VERSION);
PATTERN_MATCHER.put(Pattern.compile("^7\\.4\\.\\d+\\.GA$"), RHSSO_VERSION_7_4_KEYCLOAK_VERSION);
session.getProvider(DatastoreProvider.class).getMigrationManager().migrate();
}
public static void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
ModelVersion stored = null;
if (rep.getKeycloakVersion() != null) {
stored = convertRHSSOVersionToKeycloakVersion(rep.getKeycloakVersion());
if (stored == null) {
stored = new ModelVersion(rep.getKeycloakVersion());
}
}
if (stored == null) {
stored = migrations[0].getVersion();
session.getProvider(DatastoreProvider.class).getMigrationManager().migrate(realm, rep, skipUserDependent);
}
for (Migration m : migrations) {
if (stored == null || stored.lessThan(m.getVersion())) {
if (stored != null) {
logger.debugf("Migrating older json representation to %s", m.getVersion());
}
try {
m.migrateImport(session, realm, rep, skipUserDependent);
} catch (Exception e) {
logger.error("Failed to migrate json representation for version: " + m.getVersion(), e);
}
}
}
}
public static ModelVersion convertRHSSOVersionToKeycloakVersion(String version) {
// look for the keycloakVersion pattern to identify it as RH SSO
for (Pattern pattern : PATTERN_MATCHER.keySet()) {
if (pattern.matcher(version).find()) {
return PATTERN_MATCHER.get(pattern);
}
}
// chceck if the version is in format for CD releases, e.g.: "keycloakVersion": "6"
if (Pattern.compile("^[0-9]*$").matcher(version).find()) {
return new ModelVersion(Integer.parseInt(version), 0, 0);
}
return null;
}
}

View file

@ -45,7 +45,6 @@ import org.keycloak.models.RoleModel;
import org.keycloak.models.ScopeContainerModel;
import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.CertificateRepresentation;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.transaction.JtaTransactionManagerLookup;
import javax.crypto.spec.SecretKeySpec;
@ -392,24 +391,6 @@ public final class KeycloakModelUtils {
// USER FEDERATION RELATED STUFF
public static UserStorageProviderModel findUserStorageProviderByName(String displayName, RealmModel realm) {
if (displayName == null) {
return null;
}
return realm.getUserStorageProvidersStream()
.filter(fedProvider -> Objects.equals(fedProvider.getName(), displayName))
.findFirst()
.orElse(null);
}
public static UserStorageProviderModel findUserStorageProviderById(String fedProviderId, RealmModel realm) {
return realm.getUserStorageProvidersStream()
.filter(fedProvider -> Objects.equals(fedProvider.getId(), fedProviderId))
.findFirst()
.orElse(null);
}
public static ComponentModel createComponentModel(String name, String parentId, String providerId, String providerType, String... config) {
ComponentModel mapperModel = new ComponentModel();
mapperModel.setParentId(parentId);

View file

@ -22,4 +22,7 @@ public interface DatastoreProvider extends Provider {
public UserProvider users();
ExportImportManager getExportImportManager();
MigrationManager getMigrationManager();
}

View file

@ -0,0 +1,16 @@
package org.keycloak.storage;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.representations.idm.RealmRepresentation;
/**
* Manage importing and updating of realms for the legacy store.
*
* @author Alexander Schwartz
*/
public interface ExportImportManager {
void importRealm(RealmRepresentation rep, RealmModel newRealm, boolean skipUserDependent);
void updateRealm(RealmRepresentation rep, RealmModel realm);
}

View file

@ -0,0 +1,18 @@
package org.keycloak.storage;
import org.keycloak.models.RealmModel;
import org.keycloak.representations.idm.RealmRepresentation;
/**
* Handle the migration of the datastore and an imported realm representation.
* Will eventually be handled by the store directly.
*
* @author Alexander Schwartz
*/
@Deprecated
public interface MigrationManager {
void migrate();
void migrate(RealmModel realm, RealmRepresentation rep, boolean skipUserDependent);
}

View file

@ -21,11 +21,6 @@ import org.junit.Assert;
import org.junit.Test;
import org.keycloak.migration.ModelVersion;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.keycloak.migration.MigrationModelManager.*;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
@ -100,35 +95,4 @@ public class MigrationVersionTest {
Assert.assertNull(versionProduct.getQualifier());
}
@Test
public void testRHSSOVersionToKeycloakVersionConversion() {
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.0.0.GA"), is(equalTo(RHSSO_VERSION_7_0_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.0.1.GA"), is(equalTo(RHSSO_VERSION_7_0_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.0.2.GA"), is(equalTo(RHSSO_VERSION_7_0_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.1.0.GA"), is(equalTo(RHSSO_VERSION_7_1_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.1.1.GA"), is(equalTo(RHSSO_VERSION_7_1_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.1.2.GA"), is(equalTo(RHSSO_VERSION_7_1_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.2.0.GA"), is(equalTo(RHSSO_VERSION_7_2_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.2.1.GA"), is(equalTo(RHSSO_VERSION_7_2_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.2.2.GA"), is(equalTo(RHSSO_VERSION_7_2_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.3.0.GA"), is(equalTo(RHSSO_VERSION_7_3_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.3.1.GA"), is(equalTo(RHSSO_VERSION_7_3_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.3.2.GA"), is(equalTo(RHSSO_VERSION_7_3_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.3.10.GA"), is(equalTo(RHSSO_VERSION_7_3_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.4.0.GA"), is(equalTo(RHSSO_VERSION_7_4_KEYCLOAK_VERSION)));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.4.15.GA"), is(equalTo(RHSSO_VERSION_7_4_KEYCLOAK_VERSION)));
// check the conversion doesn't change version for keycloak
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7.0.0"), is(nullValue()));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("8.0.0"), is(nullValue()));
// check for CD releases
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("6"), is(equalTo(new ModelVersion("6.0.0"))));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("7"), is(equalTo(new ModelVersion("7.0.0"))));
Assert.assertThat(convertRHSSOVersionToKeycloakVersion("10"), is(equalTo(new ModelVersion("10.0.0"))));
}
}

View file

@ -23,8 +23,6 @@ import org.keycloak.component.ComponentModel;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderEvent;
import org.keycloak.storage.SearchableModelField;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.client.ClientStorageProvider;
import org.keycloak.storage.client.ClientStorageProviderModel;
import org.keycloak.storage.role.RoleStorageProvider;
@ -662,25 +660,6 @@ public interface RealmModel extends RoleContainerModel {
ComponentModel getComponent(String id);
/**
* @deprecated Use {@link #getUserStorageProvidersStream() getUserStorageProvidersStream} instead.
*/
@Deprecated
default List<UserStorageProviderModel> getUserStorageProviders() {
return getUserStorageProvidersStream().collect(Collectors.toList());
}
/**
* Returns sorted {@link UserStorageProviderModel UserStorageProviderModel} as a stream.
* It should be used with forEachOrdered if the ordering is required.
* @return Sorted stream of {@link UserStorageProviderModel}. Never returns {@code null}.
*/
default Stream<UserStorageProviderModel> getUserStorageProvidersStream() {
return getComponentsStream(getId(), UserStorageProvider.class.getName())
.map(UserStorageProviderModel::new)
.sorted(UserStorageProviderModel.comparator);
}
/**
* @deprecated Use {@link #getClientStorageProvidersStream() getClientStorageProvidersStream} instead.
*/

View file

@ -162,9 +162,9 @@ public class CacheableStorageProviderModel extends PrioritizedComponentModel {
}
public long getLifespan() {
UserStorageProviderModel.CachePolicy policy = getCachePolicy();
CachePolicy policy = getCachePolicy();
long lifespan = -1;
if (policy == null || policy == UserStorageProviderModel.CachePolicy.DEFAULT) {
if (policy == null || policy == CachePolicy.DEFAULT) {
lifespan = -1;
} else if (policy == CacheableStorageProviderModel.CachePolicy.EVICT_DAILY) {
if (getEvictionHour() > -1 && getEvictionMinute() > -1) {

View file

@ -21,7 +21,7 @@ import org.keycloak.models.RoleModel;
/**
* This is an optional capability interface that is intended to be implemented by any
* {@link org.keycloak.storage.UserStorageProvider UserStorageProvider} that supports bulk operations.
* <code>UserStorageProvider</code> that supports bulk operations.
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $

View file

@ -21,7 +21,7 @@ import org.keycloak.models.UserModel;
/**
* This is an optional capability interface that is intended to be implemented by any
* {@link org.keycloak.storage.UserStorageProvider UserStorageProvider} that supports basic user querying. You must
* <code>UserStorageProvider</code> that supports basic user querying. You must
* implement this interface if you want to be able to log in to keycloak using users from your storage.
* <p/>
* Note that all methods in this interface should limit search only to data available within the storage that is

View file

@ -31,7 +31,7 @@ import java.util.stream.Stream;
/**
*
* This is an optional capability interface that is intended to be implemented by any
* {@link org.keycloak.storage.UserStorageProvider UserStorageProvider} that supports complex user querying. You must
* <code>UserStorageProvider</code> that supports complex user querying. You must
* implement this interface if you want to view and manage users from the administration console.
* <p/>
* Note that all methods in this interface should limit search only to data available within the storage that is

View file

@ -22,7 +22,7 @@ import org.keycloak.models.UserModel;
/**
* This is an optional capability interface that is intended to be implemented by any
* {@link org.keycloak.storage.UserStorageProvider UserStorageProvider} that supports addition of new users. You must
* <code>UserStorageProvider</code> that supports addition of new users. You must
* implement this interface if you want to use this storage for registering new users.
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>

View file

@ -25,11 +25,11 @@ import org.keycloak.models.UserModel;
import org.keycloak.models.cache.CachedUserModel;
import org.keycloak.models.cache.OnUserCache;
import org.keycloak.models.cache.UserCache;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.storage.AbstractStorageManager;
import org.keycloak.storage.CacheableStorageProviderModel;
import org.keycloak.storage.StorageId;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderFactory;
import org.keycloak.storage.UserStorageProviderModel;
import java.util.Arrays;
import java.util.LinkedList;
@ -41,11 +41,11 @@ import java.util.stream.Stream;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UserCredentialStoreManager extends AbstractStorageManager<UserStorageProvider, UserStorageProviderModel>
public class UserCredentialStoreManager extends AbstractStorageManager<Provider, CacheableStorageProviderModel>
implements UserCredentialManager.Streams, OnUserCache {
public UserCredentialStoreManager(KeycloakSession session) {
super(session, UserStorageProviderFactory.class, UserStorageProvider.class, UserStorageProviderModel::new, "user");
super(session, ProviderFactory.class, Provider.class, componentModel -> null, "user");
}
protected UserCredentialStore getStoreForUser(UserModel user) {
@ -143,6 +143,7 @@ public class UserCredentialStoreManager extends AbstractStorageManager<UserStora
List<CredentialInput> toValidate = new LinkedList<>(inputs);
String providerId = StorageId.isLocalStorage(user) ? user.getFederationLink() : StorageId.resolveProviderId(user);
if (providerId != null) {
/*
UserStorageProviderModel model = getStorageProviderModel(realm, providerId);
if (model == null || !model.isEnabled()) return false;
@ -150,6 +151,7 @@ public class UserCredentialStoreManager extends AbstractStorageManager<UserStora
if (validator != null) {
validate(realm, user, toValidate, validator);
}
*/
}
if (toValidate.isEmpty()) return true;
@ -176,6 +178,7 @@ public class UserCredentialStoreManager extends AbstractStorageManager<UserStora
if (!StorageId.isLocalStorage(user)) throwExceptionIfInvalidUser(user);
if (providerId != null) {
/*
UserStorageProviderModel model = getStorageProviderModel(realm, providerId);
if (model == null || !model.isEnabled()) return false;
@ -183,6 +186,7 @@ public class UserCredentialStoreManager extends AbstractStorageManager<UserStora
if (updater != null && updater.supportsCredentialType(input.getType())) {
if (updater.updateCredential(realm, user, input)) return true;
}
*/
}
return getCredentialProviders(session, CredentialInputUpdater.class)
@ -195,6 +199,7 @@ public class UserCredentialStoreManager extends AbstractStorageManager<UserStora
String providerId = StorageId.isLocalStorage(user) ? user.getFederationLink() : StorageId.resolveProviderId(user);
if (!StorageId.isLocalStorage(user)) throwExceptionIfInvalidUser(user);
if (providerId != null) {
/*
UserStorageProviderModel model = getStorageProviderModel(realm, providerId);
if (model == null || !model.isEnabled()) return;
@ -202,6 +207,8 @@ public class UserCredentialStoreManager extends AbstractStorageManager<UserStora
if (updater.supportsCredentialType(credentialType)) {
updater.disableCredentialType(realm, user, credentialType);
}
*/
}
getCredentialProviders(session, CredentialInputUpdater.class)
@ -214,11 +221,13 @@ public class UserCredentialStoreManager extends AbstractStorageManager<UserStora
Stream<String> types = Stream.empty();
String providerId = StorageId.isLocalStorage(user) ? user.getFederationLink() : StorageId.resolveProviderId(user);
if (providerId != null) {
/*
UserStorageProviderModel model = getStorageProviderModel(realm, providerId);
if (model == null || !model.isEnabled()) return types;
CredentialInputUpdater updater = getStorageProviderInstance(model, CredentialInputUpdater.class);
if (updater != null) types = updater.getDisableableCredentialTypesStream(realm, user);
*/
}
return Stream.concat(types, getCredentialProviders(session, CredentialInputUpdater.class)
@ -251,6 +260,7 @@ public class UserCredentialStoreManager extends AbstractStorageManager<UserStora
private UserStorageCredentialConfigured isConfiguredThroughUserStorage(RealmModel realm, UserModel user, String type) {
String providerId = StorageId.isLocalStorage(user) ? user.getFederationLink() : StorageId.resolveProviderId(user);
if (providerId != null) {
/*
UserStorageProviderModel model = getStorageProviderModel(realm, providerId);
if (model == null || !model.isEnabled()) return UserStorageCredentialConfigured.USER_STORAGE_DISABLED;
@ -258,6 +268,7 @@ public class UserCredentialStoreManager extends AbstractStorageManager<UserStora
if (validator != null && validator.supportsCredentialType(type) && validator.isConfiguredFor(realm, user, type)) {
return UserStorageCredentialConfigured.CONFIGURED;
}
*/
}
return UserStorageCredentialConfigured.NOT_CONFIGURED;

View file

@ -148,7 +148,7 @@ public class LDAPSyncTest extends AbstractLDAPTest {
// Assert lastSync time updated
Assert.assertTrue(ctx.getLdapModel().getLastSync() > 0);
testRealm.getUserStorageProvidersStream().forEachOrdered(persistentFedModel -> {
UserStorageUtil.getUserStorageProvidersStream(testRealm).forEachOrdered(persistentFedModel -> {
if (LDAPStorageProviderFactory.PROVIDER_NAME.equals(persistentFedModel.getProviderId())) {
Assert.assertTrue(persistentFedModel.getLastSync() > 0);
} else {

View file

@ -9,6 +9,7 @@ import org.keycloak.models.RealmModel;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderFactory;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.UserStorageUtil;
import java.util.stream.Stream;
@ -22,10 +23,6 @@ public class UserStorageProvidersTestUtils {
return model.isEnabled();
}
public static Stream<UserStorageProviderModel> getStorageProviders(RealmModel realm) {
return realm.getUserStorageProvidersStream();
}
private static UserStorageProviderFactory getUserStorageProviderFactory(UserStorageProviderModel model, KeycloakSession session) {
return (UserStorageProviderFactory) session.getKeycloakSessionFactory()
.getProviderFactory(UserStorageProvider.class, model.getProviderId());
@ -50,7 +47,7 @@ public class UserStorageProvidersTestUtils {
}
public static <T> Stream<UserStorageProviderModel> getStorageProviders(RealmModel realm, KeycloakSession session, Class<T> type) {
return realm.getUserStorageProvidersStream()
return UserStorageUtil.getUserStorageProvidersStream(realm)
.filter(model -> {
UserStorageProviderFactory factory = getUserStorageProviderFactory(model, session);
if (factory == null) {

View file

@ -25,7 +25,7 @@ import org.junit.runners.MethodSorters;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
import org.keycloak.services.managers.UserStorageSyncManager;
import org.keycloak.storage.managers.UserStorageSyncManager;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.user.SynchronizationResult;

View file

@ -20,9 +20,11 @@ package org.keycloak.testsuite.util.cli;
import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.services.managers.UserStorageSyncManager;
import org.keycloak.storage.managers.UserStorageSyncManager;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.UserStorageUtil;
import java.util.Objects;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@ -35,7 +37,7 @@ public class SyncDummyFederationProviderCommand extends AbstractCommand {
int changedSyncPeriod = getIntArg(1);
RealmModel realm = session.realms().getRealmByName("master");
UserStorageProviderModel fedProviderModel = KeycloakModelUtils.findUserStorageProviderByName("cluster-dummy", realm);
UserStorageProviderModel fedProviderModel = findUserStorageProviderByName(session, "cluster-dummy", realm);
if (fedProviderModel == null) {
MultivaluedHashMap<String, String> cfg = fedProviderModel.getConfig();
updateConfig(cfg, waitTime);
@ -64,6 +66,16 @@ public class SyncDummyFederationProviderCommand extends AbstractCommand {
cfg.putSingle("wait-time", String.valueOf(waitTime));
}
public static UserStorageProviderModel findUserStorageProviderByName(KeycloakSession session, String displayName, RealmModel realm) {
if (displayName == null) {
return null;
}
return UserStorageUtil.getUserStorageProvidersStream(realm)
.filter(fedProvider -> Objects.equals(fedProvider.getName(), displayName))
.findFirst()
.orElse(null);
}
@Override
public String getName() {