More cleanup and removed export-import-impl module
This commit is contained in:
1 parent
c14840a4c0
commit
726ce08700
26 files changed
+78
-1599
No files matched your search
@@ -1,236 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
|
||||||
<parent>
|
|
||||||
<artifactId>keycloak-export-import-parent</artifactId>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<version>1.0-beta-4-SNAPSHOT</version>
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
|
||||||
</parent>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<artifactId>keycloak-export-import-impl</artifactId>
|
|
||||||
<name>Keycloak Export Import Impl</name>
|
|
||||||
<description/>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-core</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-model-api</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-export-import-api</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jboss.resteasy</groupId>
|
|
||||||
<artifactId>jaxrs-api</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jboss.resteasy</groupId>
|
|
||||||
<artifactId>resteasy-jaxrs</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>log4j</groupId>
|
|
||||||
<artifactId>log4j</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>slf4j-api</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>slf4j-simple</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jboss.logging</groupId>
|
|
||||||
<artifactId>jboss-logging</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.codehaus.jackson</groupId>
|
|
||||||
<artifactId>jackson-core-asl</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.codehaus.jackson</groupId>
|
|
||||||
<artifactId>jackson-mapper-asl</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.iharder</groupId>
|
|
||||||
<artifactId>base64</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.bouncycastle</groupId>
|
|
||||||
<artifactId>bcprov-jdk16</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<!-- Encrypted ZIP -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>de.idyl</groupId>
|
|
||||||
<artifactId>winzipaes</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-model-tests</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<classifier>tests</classifier>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-invalidation-cache-model</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<!--<dependency>-->
|
|
||||||
<!--<groupId>org.keycloak</groupId>-->
|
|
||||||
<!--<artifactId>keycloak-model-jpa</artifactId>-->
|
|
||||||
<!--<version>${project.version}</version>-->
|
|
||||||
<!--<scope>test</scope>-->
|
|
||||||
<!--</dependency>-->
|
|
||||||
<!--<dependency>-->
|
|
||||||
<!--<groupId>org.keycloak</groupId>-->
|
|
||||||
<!--<artifactId>keycloak-model-jpa</artifactId>-->
|
|
||||||
<!--<version>${project.version}</version>-->
|
|
||||||
<!--<classifier>tests</classifier>-->
|
|
||||||
<!--<scope>test</scope>-->
|
|
||||||
<!--</dependency>-->
|
|
||||||
<!--<dependency>-->
|
|
||||||
<!--<groupId>org.keycloak</groupId>-->
|
|
||||||
<!--<artifactId>keycloak-model-mongo</artifactId>-->
|
|
||||||
<!--<version>${project.version}</version>-->
|
|
||||||
<!--<scope>test</scope>-->
|
|
||||||
<!--</dependency>-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-model-tests</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.hibernate.javax.persistence</groupId>
|
|
||||||
<artifactId>hibernate-jpa-2.0-api</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.hibernate</groupId>
|
|
||||||
<artifactId>hibernate-entitymanager</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.h2database</groupId>
|
|
||||||
<artifactId>h2</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mongodb</groupId>
|
|
||||||
<artifactId>mongo-java-driver</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<keycloak.model.mongo.host>localhost</keycloak.model.mongo.host>
|
|
||||||
<keycloak.model.mongo.port>27018</keycloak.model.mongo.port>
|
|
||||||
<keycloak.model.mongo.db>keycloak</keycloak.model.mongo.db>
|
|
||||||
<keycloak.model.mongo.clearOnStartup>true</keycloak.model.mongo.clearOnStartup>
|
|
||||||
<keycloak.model.mongo.bindIp>127.0.0.1</keycloak.model.mongo.bindIp>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<source>${maven.compiler.source}</source>
|
|
||||||
<target>${maven.compiler.target}</target>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
|
|
||||||
<!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
|
|
||||||
<!--<plugin>-->
|
|
||||||
<!--<groupId>org.apache.maven.plugins</groupId>-->
|
|
||||||
<!--<artifactId>maven-surefire-plugin</artifactId>-->
|
|
||||||
<!--<executions>-->
|
|
||||||
<!--<execution>-->
|
|
||||||
<!--<id>test</id>-->
|
|
||||||
<!--<phase>integration-test</phase>-->
|
|
||||||
<!--<goals>-->
|
|
||||||
<!--<goal>test</goal>-->
|
|
||||||
<!--</goals>-->
|
|
||||||
<!--<configuration>-->
|
|
||||||
<!--<systemPropertyVariables>-->
|
|
||||||
<!--<keycloak.model.mongo.host>${keycloak.model.mongo.host}</keycloak.model.mongo.host>-->
|
|
||||||
<!--<keycloak.model.mongo.port>${keycloak.model.mongo.port}</keycloak.model.mongo.port>-->
|
|
||||||
<!--<keycloak.model.mongo.db>${keycloak.model.mongo.db}</keycloak.model.mongo.db>-->
|
|
||||||
<!--<keycloak.model.mongo.clearOnStartup>${keycloak.model.mongo.clearOnStartup}</keycloak.model.mongo.clearOnStartup>-->
|
|
||||||
<!--<keycloak.model.mongo.bindIp>${keycloak.model.mongo.bindIp}</keycloak.model.mongo.bindIp>-->
|
|
||||||
<!--</systemPropertyVariables>-->
|
|
||||||
<!--</configuration>-->
|
|
||||||
<!--</execution>-->
|
|
||||||
<!--<execution>-->
|
|
||||||
<!--<id>default-test</id>-->
|
|
||||||
<!--<configuration>-->
|
|
||||||
<!--<skip>true</skip>-->
|
|
||||||
<!--</configuration>-->
|
|
||||||
<!--</execution>-->
|
|
||||||
<!--</executions>-->
|
|
||||||
<!--</plugin>-->
|
|
||||||
|
|
||||||
<!-- Embedded mongo -->
|
|
||||||
<!--<plugin>-->
|
|
||||||
<!--<groupId>com.github.joelittlejohn.embedmongo</groupId>-->
|
|
||||||
<!--<artifactId>embedmongo-maven-plugin</artifactId>-->
|
|
||||||
<!--<executions>-->
|
|
||||||
<!--<execution>-->
|
|
||||||
<!--<id>start-mongodb</id>-->
|
|
||||||
<!--<phase>pre-integration-test</phase>-->
|
|
||||||
<!--<goals>-->
|
|
||||||
<!--<goal>start</goal>-->
|
|
||||||
<!--</goals>-->
|
|
||||||
<!--<configuration>-->
|
|
||||||
<!--<port>${keycloak.model.mongo.port}</port>-->
|
|
||||||
<!--<logging>file</logging>-->
|
|
||||||
<!--<logFile>${project.build.directory}/mongodb.log</logFile>-->
|
|
||||||
<!--<bindIp>${keycloak.model.mongo.bindIp}</bindIp>-->
|
|
||||||
<!--</configuration>-->
|
|
||||||
<!--</execution>-->
|
|
||||||
<!--<execution>-->
|
|
||||||
<!--<id>stop-mongodb</id>-->
|
|
||||||
<!--<phase>post-integration-test</phase>-->
|
|
||||||
<!--<goals>-->
|
|
||||||
<!--<goal>stop</goal>-->
|
|
||||||
<!--</goals>-->
|
|
||||||
<!--</execution>-->
|
|
||||||
<!--</executions>-->
|
|
||||||
<!--</plugin>-->
|
|
||||||
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
</project>
|
|
||||||
-152
@@ -1,152 +0,0 @@
|
|||||||
package org.keycloak.exportimport;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
import org.keycloak.models.utils.reflection.Property;
|
|
||||||
import org.keycloak.models.utils.reflection.PropertyCriteria;
|
|
||||||
import org.keycloak.models.utils.reflection.PropertyQueries;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not thread safe (objectProperties). Assumption is that export/import is executed once per JVM
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
public class ExportImportPropertiesManager {
|
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(ExportImportPropertiesManager.class);
|
|
||||||
|
|
||||||
private Map<Class<?>, Map<String, Property<Object>>> objectProperties = new HashMap<Class<?>, Map<String, Property<Object>>>();
|
|
||||||
|
|
||||||
// Add properties of class to objectProperties
|
|
||||||
protected void initClassProperties(Class<?> clazz) {
|
|
||||||
Map<String, Property<Object>> classProps = PropertyQueries.createQuery(clazz).addCriteria(new NonEmptyGetterCriteria()).getWritableResultList();
|
|
||||||
this.objectProperties.put(clazz, classProps);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBasicPropertiesFromModel(Object model, Object entity) {
|
|
||||||
Class<?> modelClass = getModelClass(model);
|
|
||||||
|
|
||||||
// Lazy init of properties
|
|
||||||
checkPropertiesAvailable(modelClass, entity.getClass());
|
|
||||||
|
|
||||||
Map<String, Property<Object>> modelProps = this.objectProperties.get(modelClass);
|
|
||||||
Map<String, Property<Object>> entityProps = this.objectProperties.get(entity.getClass());
|
|
||||||
|
|
||||||
Map<String, Property<Object>> entityPropsCopy = new HashMap<String, Property<Object>>(entityProps);
|
|
||||||
|
|
||||||
logger.debugf("Properties of entity %s: %s", entity, entityProps.keySet());
|
|
||||||
for (Property<Object> modelProperty : modelProps.values()) {
|
|
||||||
Property<Object> entityProperty = entityPropsCopy.get(modelProperty.getName());
|
|
||||||
|
|
||||||
entityPropsCopy.remove(modelProperty.getName());
|
|
||||||
|
|
||||||
if (entityProperty != null) {
|
|
||||||
Object propertyValue = modelProperty.getValue(model);
|
|
||||||
|
|
||||||
// Workaround needed because model classes have many getters/setters with "Set", but for entity classes, there are usually "List"
|
|
||||||
if (propertyValue instanceof Set) {
|
|
||||||
Set propValueAsSet = (Set)propertyValue;
|
|
||||||
entityProperty.setValue(entity, new ArrayList(propValueAsSet));
|
|
||||||
} else {
|
|
||||||
entityProperty.setValue(entity, propertyValue);
|
|
||||||
}
|
|
||||||
if (logger.isTraceEnabled()) {
|
|
||||||
logger.tracef("Property %s successfully set in JSON to entity %s", modelProperty.getName(), entity);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logger.debugf("Property %s not known in JSON for entity %s", modelProperty.getName(), entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.debugf("Entity properties for manual setup: %s", entityPropsCopy.keySet());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkPropertiesAvailable(Class<?> modelClass, Class<?> entityClass) {
|
|
||||||
if (!objectProperties.containsKey(modelClass)) {
|
|
||||||
initClassProperties(modelClass);
|
|
||||||
}
|
|
||||||
if (!objectProperties.containsKey(entityClass)) {
|
|
||||||
initClassProperties(entityClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBasicPropertiesToModel(Object model, Object entity) {
|
|
||||||
Class<?> modelClass = getModelClass(model);
|
|
||||||
|
|
||||||
// Lazy init of properties
|
|
||||||
checkPropertiesAvailable(modelClass, entity.getClass());
|
|
||||||
|
|
||||||
Map<String, Property<Object>> modelProps = this.objectProperties.get(modelClass);
|
|
||||||
Map<String, Property<Object>> entityProps = this.objectProperties.get(entity.getClass());
|
|
||||||
|
|
||||||
Map<String, Property<Object>> entityPropsCopy = new HashMap<String, Property<Object>>(entityProps);
|
|
||||||
|
|
||||||
logger.debugf("Properties of exported entity %s: %s", entity, entityProps.keySet());
|
|
||||||
|
|
||||||
for (Property<Object> modelProperty : modelProps.values()) {
|
|
||||||
Property<Object> entityProperty = entityPropsCopy.get(modelProperty.getName());
|
|
||||||
|
|
||||||
entityPropsCopy.remove(modelProperty.getName());
|
|
||||||
|
|
||||||
if (entityProperty != null) {
|
|
||||||
Object propertyValue = entityProperty.getValue(entity);
|
|
||||||
|
|
||||||
// Workaround needed because model classes have many getters/setters with "Set", but for entity classes, there are usually "List"
|
|
||||||
if (propertyValue instanceof List && Set.class.isAssignableFrom(modelProperty.getJavaClass())) {
|
|
||||||
List propValueAsList = (List)propertyValue;
|
|
||||||
modelProperty.setValue(model, new HashSet(propValueAsList));
|
|
||||||
} else {
|
|
||||||
modelProperty.setValue(model, propertyValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (logger.isTraceEnabled()) {
|
|
||||||
logger.tracef("Property %s successfully set in model from entity %s", modelProperty.getName(), entity);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logger.debugf("Property %s not known for entity %s", modelProperty.getName(), entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.debugf("Entity properties for manual setup: %s", entityPropsCopy.keySet());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Class<?> getModelClass(Object model) {
|
|
||||||
Class<?> modelClass = model.getClass();
|
|
||||||
Class<?>[] interfaces = modelClass.getInterfaces();
|
|
||||||
|
|
||||||
// Bit unsafe, but looks that it works for all "model adapters" so far
|
|
||||||
if (interfaces.length == 0) {
|
|
||||||
return modelClass;
|
|
||||||
} else {
|
|
||||||
return interfaces[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class NonEmptyGetterCriteria implements PropertyCriteria {
|
|
||||||
|
|
||||||
private static final List<String> IGNORED_METHODS = Arrays.asList("getPasswordPolicy", "getAuthenticationProviders", "getAuthenticationLink");
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean methodMatches(Method m) {
|
|
||||||
// Ignore non-empty getters
|
|
||||||
if (m.getParameterTypes().length > 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignore some "known" getters (for example incompatible types between model and entity)
|
|
||||||
if (IGNORED_METHODS.contains(m.getName())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-82
@@ -1,82 +0,0 @@
|
|||||||
package org.keycloak.exportimport;
|
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
import org.keycloak.exportimport.io.ExportImportIOProvider;
|
|
||||||
import org.keycloak.exportimport.io.ExportWriter;
|
|
||||||
import org.keycloak.exportimport.io.ImportReader;
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
|
||||||
import org.keycloak.models.KeycloakTransaction;
|
|
||||||
import org.keycloak.util.ProviderLoader;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
public class ExportImportProviderImpl {
|
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(ExportImportProviderImpl.class);
|
|
||||||
|
|
||||||
public static final String ACTION_EXPORT = "export";
|
|
||||||
public static final String ACTION_IMPORT = "import";
|
|
||||||
|
|
||||||
public void checkExportImport(KeycloakSessionFactory sessionFactory) {
|
|
||||||
String exportImportAction = ExportImportConfig.getAction();
|
|
||||||
|
|
||||||
boolean export = false;
|
|
||||||
boolean importt = false;
|
|
||||||
if (ACTION_EXPORT.equals(exportImportAction)) {
|
|
||||||
logger.infof("Full model export requested");
|
|
||||||
export = true;
|
|
||||||
} else if (ACTION_IMPORT.equals(exportImportAction)) {
|
|
||||||
logger.infof("Full model import requested");
|
|
||||||
importt = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (export || importt) {
|
|
||||||
KeycloakSession session = sessionFactory.create();
|
|
||||||
KeycloakTransaction transaction = session.getTransaction();
|
|
||||||
try {
|
|
||||||
transaction.begin();
|
|
||||||
|
|
||||||
if (export) {
|
|
||||||
ExportWriter exportWriter = getProvider().getExportWriter();
|
|
||||||
new ModelExporter().exportModel(session.model(), exportWriter);
|
|
||||||
logger.infof("Export finished successfully");
|
|
||||||
} else {
|
|
||||||
ImportReader importReader = getProvider().getImportReader();
|
|
||||||
new ModelImporter().importModel(session.model(), importReader);
|
|
||||||
logger.infof("Import finished successfully");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (transaction.isActive()) {
|
|
||||||
if (transaction.getRollbackOnly()) {
|
|
||||||
transaction.rollback();
|
|
||||||
} else {
|
|
||||||
transaction.commit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
if (transaction.isActive()) {
|
|
||||||
session.getTransaction().rollback();
|
|
||||||
}
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
} finally {
|
|
||||||
session.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private ExportImportIOProvider getProvider() {
|
|
||||||
String providerId = ExportImportConfig.getProvider();
|
|
||||||
logger.infof("Requested migration provider: " + providerId);
|
|
||||||
|
|
||||||
Iterable<ExportImportIOProvider> providers = ProviderLoader.load(ExportImportIOProvider.class);
|
|
||||||
for (ExportImportIOProvider provider : providers) {
|
|
||||||
if (providerId.equals(provider.getId())) {
|
|
||||||
return provider;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalStateException("Provider " + providerId + " not found");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-335
@@ -1,335 +0,0 @@
|
|||||||
package org.keycloak.exportimport;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
import org.keycloak.exportimport.io.ExportWriter;
|
|
||||||
import org.keycloak.models.ApplicationModel;
|
|
||||||
import org.keycloak.models.AuthenticationLinkModel;
|
|
||||||
import org.keycloak.models.AuthenticationProviderModel;
|
|
||||||
import org.keycloak.models.ClientModel;
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
|
||||||
import org.keycloak.models.ModelProvider;
|
|
||||||
import org.keycloak.models.OAuthClientModel;
|
|
||||||
import org.keycloak.models.RealmModel;
|
|
||||||
import org.keycloak.models.RequiredCredentialModel;
|
|
||||||
import org.keycloak.models.RoleContainerModel;
|
|
||||||
import org.keycloak.models.RoleModel;
|
|
||||||
import org.keycloak.models.SocialLinkModel;
|
|
||||||
import org.keycloak.models.UserCredentialValueModel;
|
|
||||||
import org.keycloak.models.UserModel;
|
|
||||||
import org.keycloak.models.UsernameLoginFailureModel;
|
|
||||||
import org.keycloak.models.entities.ApplicationEntity;
|
|
||||||
import org.keycloak.models.entities.AuthenticationLinkEntity;
|
|
||||||
import org.keycloak.models.entities.AuthenticationProviderEntity;
|
|
||||||
import org.keycloak.models.entities.CredentialEntity;
|
|
||||||
import org.keycloak.models.entities.OAuthClientEntity;
|
|
||||||
import org.keycloak.models.entities.RealmEntity;
|
|
||||||
import org.keycloak.models.entities.RequiredCredentialEntity;
|
|
||||||
import org.keycloak.models.entities.RoleEntity;
|
|
||||||
import org.keycloak.models.entities.SocialLinkEntity;
|
|
||||||
import org.keycloak.models.entities.UserEntity;
|
|
||||||
import org.keycloak.models.entities.UsernameLoginFailureEntity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
public class ModelExporter {
|
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(ModelExporter.class);
|
|
||||||
|
|
||||||
private ExportWriter exportWriter;
|
|
||||||
private ExportImportPropertiesManager propertiesManager;
|
|
||||||
|
|
||||||
public void exportModel(ModelProvider model, ExportWriter exportWriter) {
|
|
||||||
// Initialize needed objects
|
|
||||||
this.exportWriter = exportWriter;
|
|
||||||
this.propertiesManager = new ExportImportPropertiesManager();
|
|
||||||
|
|
||||||
// Create separate files for "realms", "applications", "oauthClients", "roles" and finally "users". Users may be done in more files (pagination)
|
|
||||||
exportRealms(model, "realms.json");
|
|
||||||
exportApplications(model, "applications.json");
|
|
||||||
exportOAuthClients(model, "oauthClients.json");
|
|
||||||
exportRoles(model, "roles.json");
|
|
||||||
exportUsers(model, "users.json");
|
|
||||||
// exportUserFailures(model, "userFailures.json");
|
|
||||||
|
|
||||||
this.exportWriter.closeExportWriter();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void exportRealms(ModelProvider model, String fileName) {
|
|
||||||
List<RealmModel> realms = model.getRealms();
|
|
||||||
|
|
||||||
// Convert models to entities, which will be written into JSON file
|
|
||||||
List<RealmEntity> result = new LinkedList<RealmEntity>();
|
|
||||||
for (RealmModel realmModel : realms) {
|
|
||||||
RealmEntity entity = new RealmEntity();
|
|
||||||
entity.setId(realmModel.getId());
|
|
||||||
result.add(entity);
|
|
||||||
|
|
||||||
// Export all basic properties from realm
|
|
||||||
this.propertiesManager.setBasicPropertiesFromModel(realmModel, entity);
|
|
||||||
|
|
||||||
// Export 'advanced' properties
|
|
||||||
ApplicationModel realmAdminApp = realmModel.getMasterAdminApp();
|
|
||||||
if (realmAdminApp != null) {
|
|
||||||
entity.setAdminAppId(realmAdminApp.getId());
|
|
||||||
}
|
|
||||||
entity.setDefaultRoles(realmModel.getDefaultRoles());
|
|
||||||
|
|
||||||
List<RequiredCredentialEntity> reqCredEntities = new ArrayList<RequiredCredentialEntity>();
|
|
||||||
List<RequiredCredentialModel> requiredCredModels = realmModel.getRequiredCredentials();
|
|
||||||
for (RequiredCredentialModel requiredCredModel : requiredCredModels) {
|
|
||||||
RequiredCredentialEntity reqCredEntity = new RequiredCredentialEntity();
|
|
||||||
this.propertiesManager.setBasicPropertiesFromModel(requiredCredModel, reqCredEntity);
|
|
||||||
reqCredEntities.add(reqCredEntity);
|
|
||||||
}
|
|
||||||
entity.setRequiredCredentials(reqCredEntities);
|
|
||||||
|
|
||||||
// password policy
|
|
||||||
entity.setPasswordPolicy(realmModel.getPasswordPolicy().toString());
|
|
||||||
|
|
||||||
// authentication providers
|
|
||||||
List<AuthenticationProviderEntity> authProviderEntities = new ArrayList<AuthenticationProviderEntity>();
|
|
||||||
for (AuthenticationProviderModel authProvider : realmModel.getAuthenticationProviders()) {
|
|
||||||
AuthenticationProviderEntity authProviderEntity = new AuthenticationProviderEntity();
|
|
||||||
this.propertiesManager.setBasicPropertiesFromModel(authProvider, authProviderEntity);
|
|
||||||
authProviderEntities.add(authProviderEntity);
|
|
||||||
|
|
||||||
}
|
|
||||||
entity.setAuthenticationProviders(authProviderEntities);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.exportWriter.writeEntities(fileName, result);
|
|
||||||
logger.infof("Realms exported: " + result);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void exportApplications(ModelProvider model, String fileName) {
|
|
||||||
List<ApplicationModel> allApplications = getAllApplications(model);
|
|
||||||
|
|
||||||
List<ApplicationEntity> result = new LinkedList<ApplicationEntity>();
|
|
||||||
for (ApplicationModel appModel : allApplications) {
|
|
||||||
ApplicationEntity appEntity = new ApplicationEntity();
|
|
||||||
appEntity.setId(appModel.getId());
|
|
||||||
result.add(appEntity);
|
|
||||||
|
|
||||||
this.propertiesManager.setBasicPropertiesFromModel(appModel, appEntity);
|
|
||||||
|
|
||||||
// Export 'advanced' properties of application
|
|
||||||
appEntity.setRealmId(appModel.getRealm().getId());
|
|
||||||
appEntity.setDefaultRoles(appModel.getDefaultRoles());
|
|
||||||
|
|
||||||
List<String> scopeIds = getScopeIds(appModel);
|
|
||||||
appEntity.setScopeIds(scopeIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.exportWriter.writeEntities(fileName, result);
|
|
||||||
logger.infof("Applications exported: " + result);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void exportOAuthClients(ModelProvider model, String fileName) {
|
|
||||||
List<RealmModel> realms = model.getRealms();
|
|
||||||
List<OAuthClientModel> allClients = new ArrayList<OAuthClientModel>();
|
|
||||||
for (RealmModel realmModel : realms) {
|
|
||||||
allClients.addAll(realmModel.getOAuthClients());
|
|
||||||
}
|
|
||||||
|
|
||||||
List<OAuthClientEntity> result = new LinkedList<OAuthClientEntity>();
|
|
||||||
for (OAuthClientModel clientModel : allClients) {
|
|
||||||
OAuthClientEntity clientEntity = new OAuthClientEntity();
|
|
||||||
clientEntity.setId(clientModel.getId());
|
|
||||||
result.add(clientEntity);
|
|
||||||
|
|
||||||
this.propertiesManager.setBasicPropertiesFromModel(clientModel, clientEntity);
|
|
||||||
|
|
||||||
// Export 'advanced' properties of client
|
|
||||||
clientEntity.setName(clientModel.getClientId());
|
|
||||||
clientEntity.setRealmId(clientModel.getRealm().getId());
|
|
||||||
|
|
||||||
List<String> scopeIds = getScopeIds(clientModel);
|
|
||||||
clientEntity.setScopeIds(scopeIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.exportWriter.writeEntities(fileName, result);
|
|
||||||
logger.infof("OAuth clients exported: " + result);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void exportRoles(ModelProvider model, String fileName) {
|
|
||||||
List<RoleModel> allRoles = getAllRoles(model);
|
|
||||||
|
|
||||||
List<RoleEntity> result = new LinkedList<RoleEntity>();
|
|
||||||
for (RoleModel roleModel : allRoles) {
|
|
||||||
RoleEntity roleEntity = new RoleEntity();
|
|
||||||
roleEntity.setId(roleModel.getId());
|
|
||||||
result.add(roleEntity);
|
|
||||||
|
|
||||||
roleEntity.setName(roleModel.getName());
|
|
||||||
roleEntity.setDescription(roleModel.getDescription());
|
|
||||||
|
|
||||||
RoleContainerModel roleContainer = roleModel.getContainer();
|
|
||||||
if (roleContainer instanceof RealmModel) {
|
|
||||||
RealmModel realm = (RealmModel)roleContainer;
|
|
||||||
roleEntity.setRealmId(realm.getId());
|
|
||||||
} else {
|
|
||||||
ApplicationModel appModel = (ApplicationModel)roleContainer;
|
|
||||||
roleEntity.setApplicationId(appModel.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> compositeRolesIds = null;
|
|
||||||
for (RoleModel composite : roleModel.getComposites()) {
|
|
||||||
|
|
||||||
// Lazy init
|
|
||||||
if (compositeRolesIds == null) {
|
|
||||||
compositeRolesIds = new ArrayList<String>();
|
|
||||||
}
|
|
||||||
|
|
||||||
compositeRolesIds.add(composite.getId());
|
|
||||||
}
|
|
||||||
roleEntity.setCompositeRoleIds(compositeRolesIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.exportWriter.writeEntities(fileName, result);
|
|
||||||
|
|
||||||
logger.infof("%d roles exported: ", result.size());
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("Exported roles: " + result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void exportUsers(ModelProvider model, String fileName) {
|
|
||||||
List<RealmModel> realms = model.getRealms();
|
|
||||||
List<UserEntity> result = new LinkedList<UserEntity>();
|
|
||||||
|
|
||||||
for (RealmModel realm : realms) {
|
|
||||||
List<UserModel> userModels = realm.getUsers();
|
|
||||||
for (UserModel userModel : userModels) {
|
|
||||||
UserEntity userEntity = new UserEntity();
|
|
||||||
userEntity.setId(userModel.getId());
|
|
||||||
result.add(userEntity);
|
|
||||||
|
|
||||||
this.propertiesManager.setBasicPropertiesFromModel(userModel, userEntity);
|
|
||||||
|
|
||||||
userEntity.setUsername(userModel.getUsername());
|
|
||||||
userEntity.setRealmId(realm.getId());
|
|
||||||
|
|
||||||
// authentication links
|
|
||||||
AuthenticationLinkModel authLink = userModel.getAuthenticationLink();
|
|
||||||
if (authLink != null) {
|
|
||||||
AuthenticationLinkEntity authLinkEntity = new AuthenticationLinkEntity();
|
|
||||||
this.propertiesManager.setBasicPropertiesFromModel(authLink, authLinkEntity);
|
|
||||||
|
|
||||||
userEntity.setAuthenticationLink(authLinkEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
// social links
|
|
||||||
Set<SocialLinkModel> socialLinks = realm.getSocialLinks(userModel);
|
|
||||||
if (socialLinks != null && !socialLinks.isEmpty()) {
|
|
||||||
List<SocialLinkEntity> socialLinkEntities = new ArrayList<SocialLinkEntity>();
|
|
||||||
for (SocialLinkModel socialLink : socialLinks) {
|
|
||||||
SocialLinkEntity socialLinkEntity = new SocialLinkEntity();
|
|
||||||
this.propertiesManager.setBasicPropertiesFromModel(socialLink, socialLinkEntity);
|
|
||||||
|
|
||||||
socialLinkEntities.add(socialLinkEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
userEntity.setSocialLinks(socialLinkEntities);
|
|
||||||
}
|
|
||||||
|
|
||||||
// required actions
|
|
||||||
Set<UserModel.RequiredAction> requiredActions = userModel.getRequiredActions();
|
|
||||||
if (requiredActions != null && !requiredActions.isEmpty()) {
|
|
||||||
userEntity.setRequiredActions(new ArrayList<UserModel.RequiredAction>(requiredActions));
|
|
||||||
}
|
|
||||||
|
|
||||||
// attributes
|
|
||||||
userEntity.setAttributes(userModel.getAttributes());
|
|
||||||
|
|
||||||
// roleIds
|
|
||||||
Set<RoleModel> roles = userModel.getRoleMappings();
|
|
||||||
List<String> roleIds = new ArrayList<String>();
|
|
||||||
for (RoleModel role : roles) {
|
|
||||||
roleIds.add(role.getId());
|
|
||||||
}
|
|
||||||
userEntity.setRoleIds(roleIds);
|
|
||||||
|
|
||||||
// credentials
|
|
||||||
List<UserCredentialValueModel> credentials = userModel.getCredentialsDirectly();
|
|
||||||
List<CredentialEntity> credEntities = new ArrayList<CredentialEntity>();
|
|
||||||
for (UserCredentialValueModel credModel : credentials) {
|
|
||||||
CredentialEntity credEntity = new CredentialEntity();
|
|
||||||
this.propertiesManager.setBasicPropertiesFromModel(credModel, credEntity);
|
|
||||||
credEntities.add(credEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
userEntity.setCredentials(credEntities);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.exportWriter.writeEntities(fileName, result);
|
|
||||||
|
|
||||||
logger.infof("%d users exported: ", result.size());
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("Exported users: " + result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Does it makes sense to export user failures ?
|
|
||||||
// protected void exportUserFailures(ModelProvider model, String fileName) {
|
|
||||||
// List<RealmModel> realms = model.getRealms();
|
|
||||||
// List<UsernameLoginFailureModel> allFailures = new ArrayList<UsernameLoginFailureModel>();
|
|
||||||
// for (RealmModel realmModel : realms) {
|
|
||||||
// allFailures.addAll(realmModel.getAllUserLoginFailures());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// List<UsernameLoginFailureEntity> result = new LinkedList<UsernameLoginFailureEntity>();
|
|
||||||
// for (UsernameLoginFailureModel failureModel : allFailures) {
|
|
||||||
// UsernameLoginFailureEntity failureEntity = new UsernameLoginFailureEntity();
|
|
||||||
// this.propertiesManager.setBasicPropertiesFromModel(failureModel, failureEntity);
|
|
||||||
// result.add(failureEntity);
|
|
||||||
//
|
|
||||||
// failureEntity.setUsername(failureModel.getUsername());
|
|
||||||
// failureEntity.setNumFailures(failureModel.getNumFailures());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// this.exportWriter.writeEntities(fileName, result);
|
|
||||||
// }
|
|
||||||
|
|
||||||
private List<String> getScopeIds(ClientModel clientModel) {
|
|
||||||
Set<RoleModel> allScopes = clientModel.getScopeMappings();
|
|
||||||
List<String> scopeIds = new ArrayList<String>();
|
|
||||||
for (RoleModel role : allScopes) {
|
|
||||||
scopeIds.add(role.getId());
|
|
||||||
}
|
|
||||||
return scopeIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<ApplicationModel> getAllApplications(ModelProvider model) {
|
|
||||||
List<RealmModel> realms = model.getRealms();
|
|
||||||
List<ApplicationModel> allApplications = new ArrayList<ApplicationModel>();
|
|
||||||
for (RealmModel realmModel : realms) {
|
|
||||||
allApplications.addAll(realmModel.getApplications());
|
|
||||||
}
|
|
||||||
return allApplications;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<RoleModel> getAllRoles(ModelProvider model) {
|
|
||||||
List<RoleModel> allRoles = new ArrayList<RoleModel>();
|
|
||||||
|
|
||||||
List<RealmModel> realms = model.getRealms();
|
|
||||||
for (RealmModel realmModel : realms) {
|
|
||||||
allRoles.addAll(realmModel.getRoles());
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ApplicationModel> allApplications = getAllApplications(model);
|
|
||||||
for (ApplicationModel appModel : allApplications) {
|
|
||||||
allRoles.addAll(appModel.getRoles());
|
|
||||||
}
|
|
||||||
|
|
||||||
return allRoles;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-327
@@ -1,327 +0,0 @@
|
|||||||
package org.keycloak.exportimport;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
import org.keycloak.exportimport.io.ImportReader;
|
|
||||||
import org.keycloak.models.ApplicationModel;
|
|
||||||
import org.keycloak.models.AuthenticationLinkModel;
|
|
||||||
import org.keycloak.models.AuthenticationProviderModel;
|
|
||||||
import org.keycloak.models.ClientModel;
|
|
||||||
import org.keycloak.Config;
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
|
||||||
import org.keycloak.models.ModelProvider;
|
|
||||||
import org.keycloak.models.OAuthClientModel;
|
|
||||||
import org.keycloak.models.PasswordPolicy;
|
|
||||||
import org.keycloak.models.RealmModel;
|
|
||||||
import org.keycloak.models.RoleContainerModel;
|
|
||||||
import org.keycloak.models.RoleModel;
|
|
||||||
import org.keycloak.models.SocialLinkModel;
|
|
||||||
import org.keycloak.models.UserCredentialValueModel;
|
|
||||||
import org.keycloak.models.UserModel;
|
|
||||||
import org.keycloak.models.UsernameLoginFailureModel;
|
|
||||||
import org.keycloak.models.entities.ApplicationEntity;
|
|
||||||
import org.keycloak.models.entities.AuthenticationLinkEntity;
|
|
||||||
import org.keycloak.models.entities.AuthenticationProviderEntity;
|
|
||||||
import org.keycloak.models.entities.ClientEntity;
|
|
||||||
import org.keycloak.models.entities.CredentialEntity;
|
|
||||||
import org.keycloak.models.entities.OAuthClientEntity;
|
|
||||||
import org.keycloak.models.entities.RealmEntity;
|
|
||||||
import org.keycloak.models.entities.RequiredCredentialEntity;
|
|
||||||
import org.keycloak.models.entities.RoleEntity;
|
|
||||||
import org.keycloak.models.entities.SocialLinkEntity;
|
|
||||||
import org.keycloak.models.entities.UserEntity;
|
|
||||||
import org.keycloak.models.entities.UsernameLoginFailureEntity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
public class ModelImporter {
|
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(ModelImporter.class);
|
|
||||||
|
|
||||||
private ImportReader importReader;
|
|
||||||
private ExportImportPropertiesManager propertiesManager;
|
|
||||||
|
|
||||||
public void importModel(ModelProvider model, ImportReader importReader) {
|
|
||||||
// Initialize needed objects
|
|
||||||
this.importReader = importReader;
|
|
||||||
this.propertiesManager = new ExportImportPropertiesManager();
|
|
||||||
|
|
||||||
importRealms(model, "realms.json");
|
|
||||||
importApplications(model, "applications.json");
|
|
||||||
importRoles(model, "roles.json");
|
|
||||||
|
|
||||||
// Now we have all realms,applications and roles filled. So fill other objects (default roles, scopes etc)
|
|
||||||
importRealmsStep2(model, "realms.json");
|
|
||||||
importApplicationsStep2(model, "applications.json");
|
|
||||||
|
|
||||||
importOAuthClients(model, "oauthClients.json");
|
|
||||||
importUsers(model, "users.json");
|
|
||||||
// importUserFailures(model, "userFailures.json");
|
|
||||||
|
|
||||||
this.importReader.closeImportReader();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void importRealms(ModelProvider model, String fileName) {
|
|
||||||
List<RealmEntity> realms = this.importReader.readEntities(fileName, RealmEntity.class);
|
|
||||||
|
|
||||||
for (RealmEntity realmEntity : realms) {
|
|
||||||
RealmModel realm = model.createRealm(realmEntity.getId(), realmEntity.getName());
|
|
||||||
|
|
||||||
this.propertiesManager.setBasicPropertiesToModel(realm, realmEntity);
|
|
||||||
|
|
||||||
Set<String> reqCredModels = new HashSet<String>();
|
|
||||||
for (RequiredCredentialEntity requiredCredEntity : realmEntity.getRequiredCredentials()) {
|
|
||||||
reqCredModels.add(requiredCredEntity.getType());
|
|
||||||
}
|
|
||||||
realm.updateRequiredCredentials(reqCredModels);
|
|
||||||
|
|
||||||
// AdminApp and defaultRoles are set in step2
|
|
||||||
|
|
||||||
// password policy
|
|
||||||
realm.setPasswordPolicy(new PasswordPolicy(realmEntity.getPasswordPolicy()));
|
|
||||||
|
|
||||||
// authentication providers
|
|
||||||
List<AuthenticationProviderModel> authProviderModels = new ArrayList<AuthenticationProviderModel>();
|
|
||||||
for (AuthenticationProviderEntity authProviderEntity : realmEntity.getAuthenticationProviders()) {
|
|
||||||
AuthenticationProviderModel authProvider = new AuthenticationProviderModel();
|
|
||||||
this.propertiesManager.setBasicPropertiesToModel(authProvider, authProviderEntity);
|
|
||||||
authProviderModels.add(authProvider);
|
|
||||||
|
|
||||||
}
|
|
||||||
realm.setAuthenticationProviders(authProviderModels);
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.infof("Realms imported: " + realms);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void importApplications(ModelProvider model, String fileName) {
|
|
||||||
List<ApplicationEntity> apps = this.importReader.readEntities(fileName, ApplicationEntity.class);
|
|
||||||
for (ApplicationEntity appEntity : apps) {
|
|
||||||
RealmModel realm = model.getRealm(appEntity.getRealmId());
|
|
||||||
ApplicationModel app = realm.addApplication(appEntity.getId(), appEntity.getName());
|
|
||||||
|
|
||||||
this.propertiesManager.setBasicPropertiesToModel(app , appEntity);
|
|
||||||
|
|
||||||
// scopeIds and default roles will be done in step2
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.infof("Applications imported: " + apps);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void importRoles(ModelProvider model, String fileName) {
|
|
||||||
// helper map for composite roles
|
|
||||||
Map<String, RoleEntity> rolesMap = new HashMap<String, RoleEntity>();
|
|
||||||
|
|
||||||
List<RoleEntity> roles = this.importReader.readEntities(fileName, RoleEntity.class);
|
|
||||||
for (RoleEntity roleEntity : roles) {
|
|
||||||
RoleModel role = null;
|
|
||||||
if (roleEntity.getRealmId() != null) {
|
|
||||||
RealmModel realm = model.getRealm(roleEntity.getRealmId());
|
|
||||||
role = realm.addRole(roleEntity.getId(), roleEntity.getName());
|
|
||||||
} else if (roleEntity.getApplicationId() != null) {
|
|
||||||
ApplicationModel app = findApplicationById(model, roleEntity.getApplicationId());
|
|
||||||
role = app.addRole(roleEntity.getId(), roleEntity.getName());
|
|
||||||
} else {
|
|
||||||
throw new IllegalStateException("Role " + roleEntity.getId() + " doesn't have realmId nor applicationId");
|
|
||||||
}
|
|
||||||
|
|
||||||
role.setDescription(roleEntity.getDescription());
|
|
||||||
|
|
||||||
rolesMap.put(roleEntity.getId(), roleEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
// All roles were added. Fill composite roles now
|
|
||||||
for (RealmModel realm : model.getRealms()) {
|
|
||||||
|
|
||||||
// realm roles
|
|
||||||
fillCompositeRoles(rolesMap, realm, realm);
|
|
||||||
|
|
||||||
// app roles
|
|
||||||
for (ApplicationModel app : realm.getApplications()) {
|
|
||||||
fillCompositeRoles(rolesMap, app, realm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.infof("%d roles imported: ", roles.size());
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("Imported roles: " + roles);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fillCompositeRoles(Map<String, RoleEntity> rolesMap, RoleContainerModel roleContainer, RealmModel realm) {
|
|
||||||
for (RoleModel role : roleContainer.getRoles()) {
|
|
||||||
RoleEntity roleEntity = rolesMap.get(role.getId());
|
|
||||||
|
|
||||||
if (roleEntity.getCompositeRoleIds() == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String compositeRoleId : roleEntity.getCompositeRoleIds()) {
|
|
||||||
RoleModel compositeRole = realm.getRoleById(compositeRoleId);
|
|
||||||
role.addCompositeRole(compositeRole);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void importRealmsStep2(ModelProvider model, String fileName) {
|
|
||||||
List<RealmEntity> realms = this.importReader.readEntities(fileName, RealmEntity.class);
|
|
||||||
RealmModel adminRealm = model.getRealm(Config.getAdminRealm());
|
|
||||||
|
|
||||||
for (RealmEntity realmEntity : realms) {
|
|
||||||
RealmModel realm = model.getRealm(realmEntity.getId());
|
|
||||||
|
|
||||||
// admin app
|
|
||||||
String adminAppId = realmEntity.getAdminAppId();
|
|
||||||
if (adminAppId != null) {
|
|
||||||
realm.setMasterAdminApp(adminRealm.getApplicationById(adminAppId));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default roles
|
|
||||||
realm.updateDefaultRoles(realmEntity.getDefaultRoles().toArray(new String[] {}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void importApplicationsStep2(ModelProvider model, String fileName) {
|
|
||||||
List<ApplicationEntity> apps = this.importReader.readEntities(fileName, ApplicationEntity.class);
|
|
||||||
for (ApplicationEntity appEntity : apps) {
|
|
||||||
RealmModel realm = model.getRealm(appEntity.getRealmId());
|
|
||||||
ApplicationModel application = realm.getApplicationById(appEntity.getId());
|
|
||||||
|
|
||||||
// Default roles
|
|
||||||
application.updateDefaultRoles(appEntity.getDefaultRoles().toArray(new String[] {}));
|
|
||||||
|
|
||||||
// Scopes
|
|
||||||
addScopes(realm, application, appEntity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addScopes(RealmModel realm, ClientModel client, ClientEntity clientEntity) {
|
|
||||||
for (String scopeId : clientEntity.getScopeIds()) {
|
|
||||||
RoleModel scope = realm.getRoleById(scopeId);
|
|
||||||
client.addScopeMapping(scope);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void importOAuthClients(ModelProvider model, String fileName) {
|
|
||||||
List<OAuthClientEntity> clients = this.importReader.readEntities(fileName, OAuthClientEntity.class);
|
|
||||||
for (OAuthClientEntity clientEntity : clients) {
|
|
||||||
RealmModel realm = model.getRealm(clientEntity.getRealmId());
|
|
||||||
OAuthClientModel client = realm.addOAuthClient(clientEntity.getId(), clientEntity.getName());
|
|
||||||
|
|
||||||
this.propertiesManager.setBasicPropertiesToModel(client, clientEntity);
|
|
||||||
|
|
||||||
client.setClientId(clientEntity.getName());
|
|
||||||
|
|
||||||
// Scopes. All roles are already added at this point
|
|
||||||
addScopes(realm, client, clientEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info("OAuth clients imported: " + clients);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ApplicationModel findApplicationById(ModelProvider model, String applicationId) {
|
|
||||||
for (RealmModel realm : model.getRealms()) {
|
|
||||||
ApplicationModel appModel = realm.getApplicationById(applicationId);
|
|
||||||
if (appModel != null) {
|
|
||||||
return appModel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void importUsers(ModelProvider model, String fileName) {
|
|
||||||
List<UserEntity> users = this.importReader.readEntities(fileName, UserEntity.class);
|
|
||||||
for (UserEntity userEntity : users) {
|
|
||||||
RealmModel realm = model.getRealm(userEntity.getRealmId());
|
|
||||||
UserModel user = realm.addUser(userEntity.getId(), userEntity.getUsername(), false);
|
|
||||||
|
|
||||||
// We need to remove defaultRoles here as realm.addUser is automatically adding them. We may add them later during roles mapping processing
|
|
||||||
for (RoleModel role : user.getRoleMappings()) {
|
|
||||||
user.deleteRoleMapping(role);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.propertiesManager.setBasicPropertiesToModel(user, userEntity);
|
|
||||||
|
|
||||||
// authentication links
|
|
||||||
AuthenticationLinkEntity authLinkEntity = userEntity.getAuthenticationLink();
|
|
||||||
if (authLinkEntity != null) {
|
|
||||||
AuthenticationLinkModel authLinkModel = new AuthenticationLinkModel();
|
|
||||||
this.propertiesManager.setBasicPropertiesToModel(authLinkModel, authLinkEntity);
|
|
||||||
|
|
||||||
user.setAuthenticationLink(authLinkModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
// social links
|
|
||||||
List<SocialLinkEntity> socialLinks = userEntity.getSocialLinks();
|
|
||||||
if (socialLinks != null && !socialLinks.isEmpty()) {
|
|
||||||
for (SocialLinkEntity socialLinkEntity : socialLinks) {
|
|
||||||
SocialLinkModel socialLink = new SocialLinkModel();
|
|
||||||
this.propertiesManager.setBasicPropertiesToModel(socialLink, socialLinkEntity);
|
|
||||||
|
|
||||||
realm.addSocialLink(user, socialLink);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// required actions
|
|
||||||
List<UserModel.RequiredAction> requiredActions = userEntity.getRequiredActions();
|
|
||||||
if (requiredActions != null && !requiredActions.isEmpty()) {
|
|
||||||
for (UserModel.RequiredAction reqAction : requiredActions) {
|
|
||||||
user.addRequiredAction(reqAction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// attributes
|
|
||||||
if (userEntity.getAttributes() != null) {
|
|
||||||
for (Map.Entry<String, String> attr : userEntity.getAttributes().entrySet()) {
|
|
||||||
user.setAttribute(attr.getKey(), attr.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// roles
|
|
||||||
if (userEntity.getRoleIds() != null) {
|
|
||||||
for (String roleId : userEntity.getRoleIds()) {
|
|
||||||
RoleModel role = realm.getRoleById(roleId);
|
|
||||||
user.grantRole(role);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// credentials
|
|
||||||
List<CredentialEntity> credentials = userEntity.getCredentials();
|
|
||||||
if (credentials != null) {
|
|
||||||
for (CredentialEntity credEntity : credentials) {
|
|
||||||
UserCredentialValueModel credModel = new UserCredentialValueModel();
|
|
||||||
this.propertiesManager.setBasicPropertiesToModel(credModel, credEntity);
|
|
||||||
|
|
||||||
user.updateCredentialDirectly(credModel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.infof("%d users imported: ", users.size());
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("Imported users: " + users);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// public void importUserFailures(ModelProvider model, String fileName) {
|
|
||||||
// List<UsernameLoginFailureEntity> userFailures = this.importReader.readEntities(fileName, UsernameLoginFailureEntity.class);
|
|
||||||
// for (UsernameLoginFailureEntity entity : userFailures) {
|
|
||||||
// RealmModel realm = model.getRealm(entity.getRealmId());
|
|
||||||
// UsernameLoginFailureModel loginFailureModel = realm.addUserLoginFailure(entity.getUsername());
|
|
||||||
//
|
|
||||||
// this.propertiesManager.setBasicPropertiesToModel(loginFailureModel , entity);
|
|
||||||
//
|
|
||||||
// for (int i=0 ; i<entity.getNumFailures() ; i++) {
|
|
||||||
// loginFailureModel.incrementFailures();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
-14
@@ -1,14 +0,0 @@
|
|||||||
package org.keycloak.exportimport.io;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
public interface ExportImportIOProvider {
|
|
||||||
|
|
||||||
String getId();
|
|
||||||
|
|
||||||
ExportWriter getExportWriter();
|
|
||||||
|
|
||||||
ImportReader getImportReader();
|
|
||||||
|
|
||||||
}
|
|
||||||
-13
@@ -1,13 +0,0 @@
|
|||||||
package org.keycloak.exportimport.io;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
public interface ExportWriter {
|
|
||||||
|
|
||||||
<T> void writeEntities(String fileName, List<T> entities);
|
|
||||||
|
|
||||||
void closeExportWriter();
|
|
||||||
}
|
|
||||||
-13
@@ -1,13 +0,0 @@
|
|||||||
package org.keycloak.exportimport.io;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
public interface ImportReader {
|
|
||||||
|
|
||||||
<T> List<T> readEntities(String fileName, Class<T> entityClass);
|
|
||||||
|
|
||||||
void closeImportReader();
|
|
||||||
}
|
|
||||||
-36
@@ -1,36 +0,0 @@
|
|||||||
package org.keycloak.exportimport.io.directory;
|
|
||||||
|
|
||||||
import org.keycloak.exportimport.ExportImportConfig;
|
|
||||||
import org.keycloak.exportimport.io.ExportImportIOProvider;
|
|
||||||
import org.keycloak.exportimport.io.ExportWriter;
|
|
||||||
import org.keycloak.exportimport.io.ImportReader;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Export/import into JSON files inside "tmp" directory. This implementation is used mainly for testing
|
|
||||||
* (shouldn't be used in production due to passwords in JSON files)
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
public class TmpDirExportImportIOProvider implements ExportImportIOProvider {
|
|
||||||
|
|
||||||
public static final String PROVIDER_ID = "dir";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ExportWriter getExportWriter() {
|
|
||||||
String dir = ExportImportConfig.getDir();
|
|
||||||
return dir!=null ? new TmpDirExportWriter(new File(dir)) : new TmpDirExportWriter();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ImportReader getImportReader() {
|
|
||||||
String dir = ExportImportConfig.getDir();
|
|
||||||
return dir!=null ? new TmpDirImportReader(new File(dir)) : new TmpDirImportReader();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return PROVIDER_ID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-82
@@ -1,82 +0,0 @@
|
|||||||
package org.keycloak.exportimport.io.directory;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.codehaus.jackson.map.ObjectMapper;
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
import org.keycloak.exportimport.io.ExportWriter;
|
|
||||||
import org.keycloak.util.JsonSerialization;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
public class TmpDirExportWriter implements ExportWriter {
|
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(TmpDirExportWriter.class);
|
|
||||||
|
|
||||||
private final ObjectMapper objectMapper;
|
|
||||||
private final File rootDirectory;
|
|
||||||
|
|
||||||
public TmpDirExportWriter() {
|
|
||||||
// Determine system tmp directory
|
|
||||||
String tempDir = System.getProperty("java.io.tmpdir");
|
|
||||||
|
|
||||||
// Delete and recreate directory inside tmp
|
|
||||||
this.rootDirectory = new File(tempDir + "/keycloak-export");
|
|
||||||
if (this.rootDirectory .exists()) {
|
|
||||||
recursiveDeleteDir(this.rootDirectory );
|
|
||||||
}
|
|
||||||
this.rootDirectory.mkdirs();
|
|
||||||
|
|
||||||
logger.infof("Exporting into directory %s", this.rootDirectory.getAbsolutePath());
|
|
||||||
this.objectMapper = getObjectMapper();
|
|
||||||
}
|
|
||||||
|
|
||||||
public TmpDirExportWriter(File rootDirectory) {
|
|
||||||
this.rootDirectory = rootDirectory;
|
|
||||||
this.rootDirectory.mkdirs();
|
|
||||||
this.objectMapper = getObjectMapper();
|
|
||||||
|
|
||||||
logger.infof("Exporting into directory %s", this.rootDirectory.getAbsolutePath());
|
|
||||||
}
|
|
||||||
|
|
||||||
private ObjectMapper getObjectMapper() {
|
|
||||||
return JsonSerialization.prettyMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean recursiveDeleteDir(File dirPath) {
|
|
||||||
if (dirPath.exists()) {
|
|
||||||
File[] files = dirPath.listFiles();
|
|
||||||
for (int i = 0; i < files.length; i++) {
|
|
||||||
if (files[i].isDirectory()) {
|
|
||||||
recursiveDeleteDir(files[i]);
|
|
||||||
} else {
|
|
||||||
files[i].delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (dirPath.exists())
|
|
||||||
return dirPath.delete();
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> void writeEntities(String fileName, List<T> entities) {
|
|
||||||
try {
|
|
||||||
File file = new File(this.rootDirectory, fileName);
|
|
||||||
FileOutputStream stream = new FileOutputStream(file);
|
|
||||||
this.objectMapper.writeValue(stream, entities);
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
throw new RuntimeException(ioe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void closeExportWriter() {
|
|
||||||
//To change body of implemented methods use File | Settings | File Templates.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-67
@@ -1,67 +0,0 @@
|
|||||||
package org.keycloak.exportimport.io.directory;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.reflect.Array;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.codehaus.jackson.map.ObjectMapper;
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
import org.keycloak.exportimport.io.ImportReader;
|
|
||||||
import org.keycloak.util.JsonSerialization;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
public class TmpDirImportReader implements ImportReader {
|
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(TmpDirImportReader.class);
|
|
||||||
|
|
||||||
private final ObjectMapper objectMapper;
|
|
||||||
private final File rootDirectory;
|
|
||||||
|
|
||||||
public TmpDirImportReader() {
|
|
||||||
// Determine system tmp directory
|
|
||||||
String tempDir = System.getProperty("java.io.tmpdir");
|
|
||||||
|
|
||||||
// Delete and recreate directory inside tmp
|
|
||||||
this.rootDirectory = new File(tempDir + "/keycloak-export");
|
|
||||||
if (!this.rootDirectory .exists()) {
|
|
||||||
throw new IllegalStateException("Directory " + this.rootDirectory + " doesn't exists");
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.infof("Importing from directory %s", this.rootDirectory.getAbsolutePath());
|
|
||||||
this.objectMapper = getObjectMapper();
|
|
||||||
}
|
|
||||||
|
|
||||||
public TmpDirImportReader(File rootDirectory) {
|
|
||||||
this.rootDirectory = rootDirectory;
|
|
||||||
this.objectMapper = getObjectMapper();
|
|
||||||
|
|
||||||
logger.infof("Importing from directory %s", this.rootDirectory.getAbsolutePath());
|
|
||||||
}
|
|
||||||
|
|
||||||
private ObjectMapper getObjectMapper() {
|
|
||||||
return JsonSerialization.prettyMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> List<T> readEntities(String fileName, Class<T> entityClass) {
|
|
||||||
try {
|
|
||||||
File file = new File(this.rootDirectory, fileName);
|
|
||||||
FileInputStream stream = new FileInputStream(file);
|
|
||||||
T[] template = (T[]) Array.newInstance(entityClass, 0);
|
|
||||||
T[] result = (T[])this.objectMapper.readValue(stream, template.getClass());
|
|
||||||
return Arrays.asList(result);
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
throw new RuntimeException(ioe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void closeImportReader() {
|
|
||||||
//TODO: Should directory be deleted after import?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-66
@@ -1,66 +0,0 @@
|
|||||||
package org.keycloak.exportimport.io.zip;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import de.idyl.winzipaes.AesZipFileEncrypter;
|
|
||||||
import de.idyl.winzipaes.impl.AESEncrypter;
|
|
||||||
import de.idyl.winzipaes.impl.AESEncrypterBC;
|
|
||||||
import org.codehaus.jackson.map.ObjectMapper;
|
|
||||||
import org.keycloak.exportimport.io.ExportWriter;
|
|
||||||
import org.keycloak.util.JsonSerialization;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
public class EncryptedZIPExportWriter implements ExportWriter {
|
|
||||||
|
|
||||||
private final File zipFile;
|
|
||||||
private final ObjectMapper objectMapper;
|
|
||||||
private final String password;
|
|
||||||
|
|
||||||
private final AesZipFileEncrypter encrypter;
|
|
||||||
|
|
||||||
|
|
||||||
public EncryptedZIPExportWriter(String zipFileName, String password) {
|
|
||||||
try {
|
|
||||||
this.zipFile = new File(zipFileName);
|
|
||||||
if (zipFile.exists()) {
|
|
||||||
throw new IllegalStateException("File " + zipFileName + " already exists");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.objectMapper = JsonSerialization.mapper;
|
|
||||||
|
|
||||||
AESEncrypter encrypter = new AESEncrypterBC();
|
|
||||||
this.encrypter = new AesZipFileEncrypter(this.zipFile, encrypter);
|
|
||||||
this.password = password;
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
throw new RuntimeException(ioe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> void writeEntities(String fileName, List<T> entities) {
|
|
||||||
try {
|
|
||||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
|
||||||
this.objectMapper.writeValue(stream, entities);
|
|
||||||
|
|
||||||
byte[] byteArray = stream.toByteArray();
|
|
||||||
this.encrypter.add(fileName, new ByteArrayInputStream(byteArray), this.password);
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
throw new RuntimeException(ioe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void closeExportWriter() {
|
|
||||||
try {
|
|
||||||
this.encrypter.close();
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
throw new RuntimeException(ioe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-48
@@ -1,48 +0,0 @@
|
|||||||
package org.keycloak.exportimport.io.zip;
|
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
import org.keycloak.exportimport.ExportImportConfig;
|
|
||||||
import org.keycloak.exportimport.io.ExportImportIOProvider;
|
|
||||||
import org.keycloak.exportimport.io.ExportWriter;
|
|
||||||
import org.keycloak.exportimport.io.ImportReader;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
public class EncryptedZIPIOProvider implements ExportImportIOProvider {
|
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(EncryptedZIPIOProvider.class);
|
|
||||||
|
|
||||||
public static final String PROVIDER_ID = "zip";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return PROVIDER_ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ExportWriter getExportWriter() {
|
|
||||||
String zipFile = ExportImportConfig.getZipFile();
|
|
||||||
String zipPassword = ExportImportConfig.getZipPassword();
|
|
||||||
logger.infof("Using zip for export: " + zipFile);
|
|
||||||
|
|
||||||
if (zipFile==null || zipPassword==null) {
|
|
||||||
throw new IllegalArgumentException("zipFile or zipPassword are null");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new EncryptedZIPExportWriter(zipFile, zipPassword);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ImportReader getImportReader() {
|
|
||||||
String zipFile = ExportImportConfig.getZipFile();
|
|
||||||
String zipPassword = ExportImportConfig.getZipPassword();
|
|
||||||
logger.infof("Using zip for import: " + zipFile);
|
|
||||||
|
|
||||||
if (zipFile==null || zipPassword==null) {
|
|
||||||
throw new IllegalArgumentException("zipFile or zipPassword are null");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new EncryptedZIPImportReader(zipFile, zipPassword);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-70
@@ -1,70 +0,0 @@
|
|||||||
package org.keycloak.exportimport.io.zip;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.reflect.Array;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import de.idyl.winzipaes.AesZipFileDecrypter;
|
|
||||||
import de.idyl.winzipaes.impl.AESDecrypter;
|
|
||||||
import de.idyl.winzipaes.impl.AESDecrypterBC;
|
|
||||||
import org.codehaus.jackson.map.ObjectMapper;
|
|
||||||
import org.keycloak.exportimport.io.ImportReader;
|
|
||||||
import org.keycloak.util.JsonSerialization;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
public class EncryptedZIPImportReader implements ImportReader {
|
|
||||||
|
|
||||||
private final File zipFile;
|
|
||||||
private final ObjectMapper objectMapper;
|
|
||||||
private final String password;
|
|
||||||
|
|
||||||
private final AesZipFileDecrypter decrypter;
|
|
||||||
|
|
||||||
|
|
||||||
public EncryptedZIPImportReader(String zipFileName, String password) {
|
|
||||||
try {
|
|
||||||
this.zipFile = new File(zipFileName);
|
|
||||||
if (!zipFile.exists()) {
|
|
||||||
throw new IllegalStateException("File " + zipFileName + " doesn't exists");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.objectMapper = JsonSerialization.mapper;
|
|
||||||
|
|
||||||
AESDecrypter decrypter = new AESDecrypterBC();
|
|
||||||
this.decrypter = new AesZipFileDecrypter(this.zipFile, decrypter);
|
|
||||||
this.password = password;
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
throw new RuntimeException(ioe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> List<T> readEntities(String fileName, Class<T> entityClass) {
|
|
||||||
try {
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
||||||
this.decrypter.extractEntry(this.decrypter.getEntry(fileName), bos, this.password);
|
|
||||||
|
|
||||||
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
|
|
||||||
T[] template = (T[]) Array.newInstance(entityClass, 0);
|
|
||||||
T[] result = (T[])this.objectMapper.readValue(bis, template.getClass());
|
|
||||||
return Arrays.asList(result);
|
|
||||||
} catch (Exception ioe) {
|
|
||||||
throw new RuntimeException(ioe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void closeImportReader() {
|
|
||||||
try {
|
|
||||||
this.decrypter.close();
|
|
||||||
} catch (Exception ioe) {
|
|
||||||
throw new RuntimeException(ioe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
org.keycloak.exportimport.ExportImportProviderImpl
|
|
||||||
-2
@@ -1,2 +0,0 @@
|
|||||||
org.keycloak.exportimport.io.directory.TmpDirExportImportIOProvider
|
|
||||||
org.keycloak.exportimport.io.zip.EncryptedZIPIOProvider
|
|
||||||
-14
@@ -1,14 +0,0 @@
|
|||||||
package org.keycloak.exportimport;
|
|
||||||
|
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.keycloak.exportimport.io.directory.TmpDirExportImportIOProvider;
|
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test for full export of data from JPA and import them to Mongo. Using "directory" provider
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
@Ignore
|
|
||||||
public class JPAToMongoExportImportTest {
|
|
||||||
}
|
|
||||||
-17
@@ -1,17 +0,0 @@
|
|||||||
package org.keycloak.exportimport;
|
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.keycloak.exportimport.io.zip.EncryptedZIPIOProvider;
|
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test for full export of data from Mongo and import them to JPA. Using export into encrypted ZIP and import from it
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
@Ignore
|
|
||||||
public class MongoToJPAExportImportTest {
|
|
||||||
}
|
|
||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
<module>export-import-api</module>
|
<module>export-import-api</module>
|
||||||
<module>export-import-impl</module>
|
|
||||||
<module>export-import-dir</module>
|
<module>export-import-dir</module>
|
||||||
<module>export-import-single-file</module>
|
<module>export-import-single-file</module>
|
||||||
<module>export-import-zip</module>
|
<module>export-import-zip</module>
|
||||||
|
|||||||
+14
@@ -266,9 +266,23 @@ public class DefaultCacheModelProvider implements CacheModelProvider {
|
|||||||
@Override
|
@Override
|
||||||
public boolean removeRealm(String id) {
|
public boolean removeRealm(String id) {
|
||||||
cache.invalidateCachedRealmById(id);
|
cache.invalidateCachedRealmById(id);
|
||||||
|
|
||||||
|
RealmModel realm = getDelegate().getRealm(id);
|
||||||
|
Set<RoleModel> realmRoles = null;
|
||||||
|
if (realm != null) {
|
||||||
|
realmRoles = realm.getRoles();
|
||||||
|
}
|
||||||
|
|
||||||
boolean didIt = getDelegate().removeRealm(id);
|
boolean didIt = getDelegate().removeRealm(id);
|
||||||
realmInvalidations.add(id);
|
realmInvalidations.add(id);
|
||||||
|
|
||||||
|
// TODO: Temporary workaround to invalidate cached realm roles
|
||||||
|
if (didIt && realmRoles != null) {
|
||||||
|
for (RoleModel role : realmRoles) {
|
||||||
|
roleInvalidations.add(role.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return didIt;
|
return didIt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -167,7 +167,12 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-export-import-impl</artifactId>
|
<artifactId>keycloak-export-import-dir</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-export-import-single-file</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|||||||
+11
-1
@@ -284,7 +284,17 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-export-import-impl</artifactId>
|
<artifactId>keycloak-export-import-dir</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-export-import-zip</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-export-import-single-file</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
+30
-9
@@ -5,8 +5,6 @@ import java.util.Properties;
|
|||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.ClassRule;
|
import org.junit.ClassRule;
|
||||||
import org.junit.FixMethodOrder;
|
|
||||||
import org.junit.Rule;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.rules.ExternalResource;
|
import org.junit.rules.ExternalResource;
|
||||||
import org.junit.rules.RuleChain;
|
import org.junit.rules.RuleChain;
|
||||||
@@ -25,7 +23,6 @@ import org.keycloak.models.UserModel;
|
|||||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||||
import org.keycloak.services.managers.RealmManager;
|
import org.keycloak.services.managers.RealmManager;
|
||||||
import org.keycloak.testsuite.rule.KeycloakRule;
|
import org.keycloak.testsuite.rule.KeycloakRule;
|
||||||
import org.keycloak.testutils.KeycloakServer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
@@ -39,7 +36,7 @@ public class ExportImportTest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void before() throws Throwable {
|
protected void before() throws Throwable {
|
||||||
if (System.getProperty("hibernate.connection.url") == null) {
|
if (System.getProperty("hibernate.connection.url") == null) {
|
||||||
String baseExportImportDir = getExportImportTestDirectory();
|
String baseExportImportDir = getExportImportTestDirectory();
|
||||||
|
|
||||||
File oldDBFile = new File(baseExportImportDir, "keycloakDB.h2.db");
|
File oldDBFile = new File(baseExportImportDir, "keycloakDB.h2.db");
|
||||||
@@ -64,6 +61,29 @@ public class ExportImportTest {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// We want data to be persisted among server restarts
|
||||||
|
private static ExternalResource mongoRule = new ExternalResource() {
|
||||||
|
|
||||||
|
private static final String MONGO_CLEAR_ON_STARTUP_PROP_NAME = "keycloak.model.mongo.clearOnStartup";
|
||||||
|
private String previousMongoClearOnStartup;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void before() throws Throwable {
|
||||||
|
previousMongoClearOnStartup = System.getProperty(MONGO_CLEAR_ON_STARTUP_PROP_NAME);
|
||||||
|
System.setProperty(MONGO_CLEAR_ON_STARTUP_PROP_NAME, "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void after() {
|
||||||
|
if (previousMongoClearOnStartup != null) {
|
||||||
|
System.setProperty(MONGO_CLEAR_ON_STARTUP_PROP_NAME, "false");
|
||||||
|
} else {
|
||||||
|
System.getProperties().remove(MONGO_CLEAR_ON_STARTUP_PROP_NAME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
private static KeycloakRule keycloakRule = new KeycloakRule( new KeycloakRule.KeycloakSetup() {
|
private static KeycloakRule keycloakRule = new KeycloakRule( new KeycloakRule.KeycloakSetup() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -79,9 +99,10 @@ public class ExportImportTest {
|
|||||||
@ClassRule
|
@ClassRule
|
||||||
public static TestRule chain = RuleChain
|
public static TestRule chain = RuleChain
|
||||||
.outerRule(hibernateSetupRule)
|
.outerRule(hibernateSetupRule)
|
||||||
|
.around(mongoRule)
|
||||||
.around(keycloakRule);
|
.around(keycloakRule);
|
||||||
|
|
||||||
//@Test
|
@Test
|
||||||
public void testDirFullExportImport() throws Throwable {
|
public void testDirFullExportImport() throws Throwable {
|
||||||
ExportImportConfig.setProvider(DirExportProviderFactory.PROVIDER_ID);
|
ExportImportConfig.setProvider(DirExportProviderFactory.PROVIDER_ID);
|
||||||
String targetDirPath = getExportImportTestDirectory() + File.separator + "dirExport";
|
String targetDirPath = getExportImportTestDirectory() + File.separator + "dirExport";
|
||||||
@@ -95,7 +116,7 @@ public class ExportImportTest {
|
|||||||
Assert.assertEquals(4, new File(targetDirPath).listFiles().length);
|
Assert.assertEquals(4, new File(targetDirPath).listFiles().length);
|
||||||
}
|
}
|
||||||
|
|
||||||
//@Test
|
@Test
|
||||||
public void testDirRealmExportImport() throws Throwable {
|
public void testDirRealmExportImport() throws Throwable {
|
||||||
ExportImportConfig.setProvider(DirExportProviderFactory.PROVIDER_ID);
|
ExportImportConfig.setProvider(DirExportProviderFactory.PROVIDER_ID);
|
||||||
String targetDirPath = getExportImportTestDirectory() + File.separator + "dirRealmExport";
|
String targetDirPath = getExportImportTestDirectory() + File.separator + "dirRealmExport";
|
||||||
@@ -118,7 +139,7 @@ public class ExportImportTest {
|
|||||||
testFullExportImport();
|
testFullExportImport();
|
||||||
}
|
}
|
||||||
|
|
||||||
//@Test
|
@Test
|
||||||
public void testSingleFileRealmExportImport() throws Throwable {
|
public void testSingleFileRealmExportImport() throws Throwable {
|
||||||
ExportImportConfig.setProvider(SingleFileExportProviderFactory.PROVIDER_ID);
|
ExportImportConfig.setProvider(SingleFileExportProviderFactory.PROVIDER_ID);
|
||||||
String targetFilePath = getExportImportTestDirectory() + File.separator + "singleFile-realm.json";
|
String targetFilePath = getExportImportTestDirectory() + File.separator + "singleFile-realm.json";
|
||||||
@@ -127,7 +148,7 @@ public class ExportImportTest {
|
|||||||
testRealmExportImport();
|
testRealmExportImport();
|
||||||
}
|
}
|
||||||
|
|
||||||
//@Test
|
@Test
|
||||||
public void testZipFullExportImport() throws Throwable {
|
public void testZipFullExportImport() throws Throwable {
|
||||||
ExportImportConfig.setProvider(ZipExportProviderFactory.PROVIDER_ID);
|
ExportImportConfig.setProvider(ZipExportProviderFactory.PROVIDER_ID);
|
||||||
String zipFilePath = getExportImportTestDirectory() + File.separator + "export-full.zip";
|
String zipFilePath = getExportImportTestDirectory() + File.separator + "export-full.zip";
|
||||||
@@ -139,7 +160,7 @@ public class ExportImportTest {
|
|||||||
testFullExportImport();
|
testFullExportImport();
|
||||||
}
|
}
|
||||||
|
|
||||||
//@Test
|
@Test
|
||||||
public void testZipRealmExportImport() throws Throwable {
|
public void testZipRealmExportImport() throws Throwable {
|
||||||
ExportImportConfig.setProvider(ZipExportProviderFactory.PROVIDER_ID);
|
ExportImportConfig.setProvider(ZipExportProviderFactory.PROVIDER_ID);
|
||||||
String zipFilePath = getExportImportTestDirectory() + File.separator + "export-realm.zip";
|
String zipFilePath = getExportImportTestDirectory() + File.separator + "export-realm.zip";
|
||||||
|
|||||||
+4
-3
@@ -6,6 +6,7 @@ import org.apache.log.Logger;
|
|||||||
import org.keycloak.models.ApplicationModel;
|
import org.keycloak.models.ApplicationModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.utils.RepresentationToModel;
|
||||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||||
import org.keycloak.services.managers.RealmManager;
|
import org.keycloak.services.managers.RealmManager;
|
||||||
|
|
||||||
@@ -77,9 +78,9 @@ public class CreateRealmsWorker implements Worker {
|
|||||||
|
|
||||||
// Add required credentials
|
// Add required credentials
|
||||||
if (createRequiredCredentials) {
|
if (createRequiredCredentials) {
|
||||||
realmManager.addRequiredCredential(realm, CredentialRepresentation.PASSWORD);
|
RepresentationToModel.addRequiredCredential(realm, CredentialRepresentation.PASSWORD);
|
||||||
realmManager.addRequiredCredential(realm, CredentialRepresentation.TOTP);
|
RepresentationToModel.addRequiredCredential(realm, CredentialRepresentation.TOTP);
|
||||||
realmManager.addRequiredCredential(realm, CredentialRepresentation.CLIENT_CERT);
|
RepresentationToModel.addRequiredCredential(realm, CredentialRepresentation.CLIENT_CERT);
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info("Finished creation of realm " + realmName);
|
log.info("Finished creation of realm " + realmName);
|
||||||
|
|||||||
+11
-1
@@ -283,7 +283,17 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-export-import-impl</artifactId>
|
<artifactId>keycloak-export-import-dir</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-export-import-zip</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-export-import-single-file</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.keycloak.test.tools;
|
package org.keycloak.test.tools;
|
||||||
|
|
||||||
import org.keycloak.exportimport.ExportImportConfig;
|
import org.keycloak.exportimport.ExportImportConfig;
|
||||||
|
import org.keycloak.exportimport.ExportImportManager;
|
||||||
import org.keycloak.exportimport.ExportProvider;
|
import org.keycloak.exportimport.ExportProvider;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
@@ -231,14 +232,7 @@ public class PerfTools {
|
|||||||
ExportImportConfig.setProvider("dir");
|
ExportImportConfig.setProvider("dir");
|
||||||
ExportImportConfig.setDir(dir);
|
ExportImportConfig.setDir(dir);
|
||||||
|
|
||||||
Iterator<ExportProvider> providers = ProviderLoader.load(ExportProvider.class).iterator();
|
new ExportImportManager().checkExportImport(sessionFactory);
|
||||||
|
|
||||||
if (providers.hasNext()) {
|
|
||||||
ExportProvider exportImport = providers.next();
|
|
||||||
exportImport.checkExportImport(sessionFactory);
|
|
||||||
} else {
|
|
||||||
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class JobRepresentation {
|
public static class JobRepresentation {
|
||||||
|
|||||||
Reference in new issue
Block a user