KEYCLOAK-15264 Import realm using directory provider twice with IGNORE_EXISTING will cause NPE for clientId

This commit is contained in:
Martin Bartoš 2020-11-27 12:10:51 +01:00 committed by Hynek Mlnařík
parent 8c0c542f09
commit 873a69305f
2 changed files with 63 additions and 4 deletions

View file

@ -57,6 +57,7 @@ import org.keycloak.services.clientregistration.policy.DefaultClientRegistration
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import org.keycloak.utils.ReservedCharValidator;
/**
@ -719,7 +720,15 @@ public class RealmManager {
ClientManager clientManager = new ClientManager(this);
for (ClientRepresentation client : clients) {
ClientModel clientModel = this.getRealmByName(rep.getRealm()).getClientById(client.getId());
RealmModel realmModel = this.getRealmByName(rep.getRealm());
ClientModel clientModel = Optional.ofNullable(client.getId())
.map(realmModel::getClientById)
.orElseGet(() -> realmModel.getClientByClientId(client.getClientId()));
if (clientModel == null) {
throw new RuntimeException("Cannot find provided client by dir import.");
}
UserModel serviceAccount = null;
if (clientModel.isServiceAccountsEnabled()) {

View file

@ -17,12 +17,15 @@
package org.keycloak.testsuite.exportimport;
import org.apache.commons.io.FileUtils;
import org.hamcrest.Matchers;
import org.jboss.arquillian.container.spi.client.container.LifecycleException;
import org.junit.After;
import org.junit.Test;
import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.authentication.requiredactions.WebAuthnRegisterFactory;
import org.keycloak.exportimport.ExportImportConfig;
import org.keycloak.exportimport.Strategy;
import org.keycloak.exportimport.dir.DirExportProvider;
import org.keycloak.exportimport.dir.DirExportProviderFactory;
import org.keycloak.exportimport.singlefile.SingleFileExportProviderFactory;
@ -36,10 +39,12 @@ import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.testsuite.AbstractKeycloakTest;
import org.keycloak.testsuite.Assert;
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude;
import org.keycloak.testsuite.client.resources.TestingExportImportResource;
import org.keycloak.testsuite.runonserver.RunHelpers;
import org.keycloak.testsuite.util.UserBuilder;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
import java.util.HashMap;
@ -233,17 +238,62 @@ public class ExportImportTest extends AbstractKeycloakTest {
addTestRealmToTestRealmReps("import-without-clients");
}
@Test
public void testImportIgnoreExistingMissingClientId() {
TestingExportImportResource resource = testingClient.testing().exportImport();
resource.setStrategy(Strategy.IGNORE_EXISTING);
resource.setProvider(DirExportProviderFactory.PROVIDER_ID);
String targetDirPath = resource.getExportImportTestDirectory() + File.separator + "dirRealmExport";
File dest = new File(targetDirPath);
try {
DirExportProvider.recursiveDeleteDir(dest);
resource.setDir(targetDirPath);
resource.setAction(ExportImportConfig.ACTION_EXPORT);
URL url = ExportImportTest.class.getResource("/model/testrealm.json");
File testRealm = new File(url.getFile());
assertThat(testRealm, Matchers.notNullValue());
File newFile = new File("test-new-realm.json");
try {
FileUtils.copyFile(testRealm, newFile);
FileUtils.copyFileToDirectory(newFile, dest);
} catch (IOException e) {
Assert.fail("Cannot copy file. Details: " + e.getMessage());
}
File existingFile = FileUtils.getFile(dest, newFile.getName());
assertThat(existingFile, Matchers.notNullValue());
resource.runExport();
resource.setAction(ExportImportConfig.ACTION_IMPORT);
try {
resource.runImport();
resource.runImport();
} catch (Exception e) {
Assert.fail("Error with realm importing twice. Details: " + e.getMessage());
}
} finally {
DirExportProvider.recursiveDeleteDir(dest);
}
}
private boolean isRealmPresent(String realmId) {
return adminClient.realms().findAll().stream().filter(realm -> realmId.equals(realm.getId())).findFirst().isPresent();
return adminClient.realms().findAll().stream().anyMatch(realm -> realmId.equals(realm.getId()));
}
/*
* non-JavaDoc
*
* Adds a testTealm to TestContext.testRealmReps (which are after testClass removed)
*
*
* It prevents from affecting other tests. (auth-server-undertow)
*
*
*/
private void addTestRealmToTestRealmReps(String realm) {
testContext.addTestRealmToTestRealmReps(adminClient.realms().realm(realm).toRepresentation());