Moved model unit tests from services to model/tests . Mongo profile in testsuite
This commit is contained in:
parent
b3f1032f96
commit
b9ff73d61c
65 changed files with 994 additions and 962 deletions
|
@ -1,4 +1,4 @@
|
|||
package org.keycloak.services.utils;
|
||||
package org.keycloak.models.utils;
|
||||
|
||||
import java.util.ServiceLoader;
|
||||
|
|
@ -59,6 +59,20 @@
|
|||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-model-tests</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>tests</classifier>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
|
@ -70,6 +84,22 @@
|
|||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-test</id>
|
||||
<configuration>
|
||||
<dependenciesToScan>
|
||||
<dependency>org.keycloak:keycloak-model-tests</dependency>
|
||||
</dependenciesToScan>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
|
|
@ -46,17 +46,23 @@
|
|||
<artifactId>mongo-java-driver</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>de.flapdoodle.embed</groupId>
|
||||
<artifactId>de.flapdoodle.embed.mongo</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-model-tests</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>tests</classifier>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<keycloak.mongo.host>localhost</keycloak.mongo.host>
|
||||
<keycloak.mongo.port>27018</keycloak.mongo.port>
|
||||
<keycloak.mongo.db>keycloak</keycloak.mongo.db>
|
||||
<keycloak.mongo.clearOnStartup>true</keycloak.mongo.clearOnStartup>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
@ -67,6 +73,66 @@
|
|||
<target>1.6</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.mongo.host>${keycloak.mongo.host}</keycloak.mongo.host>
|
||||
<keycloak.mongo.port>${keycloak.mongo.port}</keycloak.mongo.port>
|
||||
<keycloak.mongo.db>${keycloak.mongo.db}</keycloak.mongo.db>
|
||||
<keycloak.mongo.clearOnStartup>${keycloak.mongo.clearOnStartup}</keycloak.mongo.clearOnStartup>
|
||||
</systemPropertyVariables>
|
||||
<dependenciesToScan>
|
||||
<dependency>org.keycloak:keycloak-model-tests</dependency>
|
||||
</dependenciesToScan>
|
||||
</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.mongo.port}</port>
|
||||
<logging>file</logging>
|
||||
<logFile>${project.build.directory}/mongodb.log</logFile>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>stop-mongodb</id>
|
||||
<phase>post-integration-test</phase>
|
||||
<goals>
|
||||
<goal>stop</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -18,7 +18,7 @@ public class AbstractMongoIdentifiableEntity implements MongoIdentifiableEntity
|
|||
}
|
||||
|
||||
@Override
|
||||
public void afterRemove(MongoStore mongoStore, MongoStoreInvocationContext invocationContext) {
|
||||
public void afterRemove(MongoStoreInvocationContext invocationContext) {
|
||||
// Empty by default
|
||||
}
|
||||
|
||||
|
|
|
@ -17,5 +17,5 @@ public interface MongoIdentifiableEntity extends MongoEntity {
|
|||
* Lifecycle callback, which is called after removal of this object from Mongo.
|
||||
* It may be useful for triggering removal of wired objects.
|
||||
*/
|
||||
void afterRemove(MongoStore mongoStore, MongoStoreInvocationContext invocationContext);
|
||||
void afterRemove(MongoStoreInvocationContext invocationContext);
|
||||
}
|
||||
|
|
|
@ -11,33 +11,33 @@ import java.util.List;
|
|||
public interface MongoStore {
|
||||
|
||||
/**
|
||||
* Insert new object
|
||||
* Insert new entity
|
||||
*
|
||||
* @param object to update
|
||||
* @param entity to insert
|
||||
*/
|
||||
void insertObject(MongoIdentifiableEntity object, MongoStoreInvocationContext context);
|
||||
void insertEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context);
|
||||
|
||||
/**
|
||||
* Update existing object
|
||||
* Update existing entity
|
||||
*
|
||||
* @param object to update
|
||||
* @param entity to update
|
||||
*/
|
||||
void updateObject(MongoIdentifiableEntity object, MongoStoreInvocationContext context);
|
||||
void updateEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context);
|
||||
|
||||
|
||||
<T extends MongoIdentifiableEntity> T loadObject(Class<T> type, String oid, MongoStoreInvocationContext context);
|
||||
<T extends MongoIdentifiableEntity> T loadEntity(Class<T> type, String id, MongoStoreInvocationContext context);
|
||||
|
||||
<T extends MongoIdentifiableEntity> T loadSingleObject(Class<T> type, DBObject query, MongoStoreInvocationContext context);
|
||||
<T extends MongoIdentifiableEntity> T loadSingleEntity(Class<T> type, DBObject query, MongoStoreInvocationContext context);
|
||||
|
||||
<T extends MongoIdentifiableEntity> List<T> loadObjects(Class<T> type, DBObject query, MongoStoreInvocationContext context);
|
||||
<T extends MongoIdentifiableEntity> List<T> loadEntities(Class<T> type, DBObject query, MongoStoreInvocationContext context);
|
||||
|
||||
boolean removeObject(MongoIdentifiableEntity object, MongoStoreInvocationContext context);
|
||||
boolean removeEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context);
|
||||
|
||||
boolean removeObject(Class<? extends MongoIdentifiableEntity> type, String id, MongoStoreInvocationContext context);
|
||||
boolean removeEntity(Class<? extends MongoIdentifiableEntity> type, String id, MongoStoreInvocationContext context);
|
||||
|
||||
boolean removeObjects(Class<? extends MongoIdentifiableEntity> type, DBObject query, MongoStoreInvocationContext context);
|
||||
boolean removeEntities(Class<? extends MongoIdentifiableEntity> type, DBObject query, MongoStoreInvocationContext context);
|
||||
|
||||
<S> boolean pushItemToList(MongoIdentifiableEntity object, String listPropertyName, S itemToPush, boolean skipIfAlreadyPresent, MongoStoreInvocationContext context);
|
||||
<S> boolean pushItemToList(MongoIdentifiableEntity entity, String listPropertyName, S itemToPush, boolean skipIfAlreadyPresent, MongoStoreInvocationContext context);
|
||||
|
||||
<S> boolean pullItemFromList(MongoIdentifiableEntity object, String listPropertyName, S itemToPull, MongoStoreInvocationContext context);
|
||||
<S> boolean pullItemFromList(MongoIdentifiableEntity entity, String listPropertyName, S itemToPull, MongoStoreInvocationContext context);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
package org.keycloak.models.mongo.api.context;
|
||||
|
||||
import org.keycloak.models.mongo.api.MongoIdentifiableEntity;
|
||||
import org.keycloak.models.mongo.api.MongoStore;
|
||||
|
||||
/**
|
||||
* Context, which provides callback methods to be invoked by MongoStore
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public interface MongoStoreInvocationContext {
|
||||
|
||||
void addCreatedObject(MongoIdentifiableEntity entity);
|
||||
|
||||
void addLoadedObject(MongoIdentifiableEntity entity);
|
||||
|
||||
<T extends MongoIdentifiableEntity> T getLoadedObject(Class<T> type, String id);
|
||||
|
@ -22,4 +27,6 @@ public interface MongoStoreInvocationContext {
|
|||
void commit();
|
||||
|
||||
void rollback();
|
||||
|
||||
MongoStore getMongoStore();
|
||||
}
|
||||
|
|
|
@ -2,21 +2,21 @@ package org.keycloak.models.mongo.api.types;
|
|||
|
||||
/**
|
||||
* SPI object to convert object from application type to database type and vice versa. Shouldn't be directly used by application.
|
||||
* Various converters should be registered in TypeConverter, which is main entry point to be used by application
|
||||
* Various mappers should be registered in TypeMapper, which is main entry point to be used by application
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public interface Converter<T, S> {
|
||||
public interface Mapper<T, S> {
|
||||
|
||||
/**
|
||||
* Convert object from one type to expected type
|
||||
*
|
||||
* @param converterContext Encapsulates reference to converted object and other things, which might be helpful in conversion
|
||||
* @param mapperContext Encapsulates reference to converted object and other things, which might be helpful in conversion
|
||||
* @return converted object
|
||||
*/
|
||||
S convertObject(ConverterContext<T> converterContext);
|
||||
S convertObject(MapperContext<T, S> mapperContext);
|
||||
|
||||
Class<? extends T> getConverterObjectType();
|
||||
Class<? extends T> getTypeOfObjectToConvert();
|
||||
|
||||
Class<S> getExpectedReturnType();
|
||||
}
|
|
@ -5,18 +5,18 @@ import java.util.List;
|
|||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class ConverterContext<T> {
|
||||
public class MapperContext<T, S> {
|
||||
|
||||
// object to convert
|
||||
private final T objectToConvert;
|
||||
|
||||
// expected return type, which could be useful information in some converters, so they are able to dynamically instantiate types
|
||||
private final Class<?> expectedReturnType;
|
||||
private final Class<? extends S> expectedReturnType;
|
||||
|
||||
// in case that expected return type is generic type (like "List<String>"), then genericTypes could contain list of expected generic arguments
|
||||
private final List<Class<?>> genericTypes;
|
||||
|
||||
public ConverterContext(T objectToConvert, Class<?> expectedReturnType, List<Class<?>> genericTypes) {
|
||||
public MapperContext(T objectToConvert, Class<? extends S> expectedReturnType, List<Class<?>> genericTypes) {
|
||||
this.objectToConvert = objectToConvert;
|
||||
this.expectedReturnType = expectedReturnType;
|
||||
this.genericTypes = genericTypes;
|
||||
|
@ -26,7 +26,7 @@ public class ConverterContext<T> {
|
|||
return objectToConvert;
|
||||
}
|
||||
|
||||
public Class<?> getExpectedReturnType() {
|
||||
public Class<? extends S> getExpectedReturnType() {
|
||||
return expectedReturnType;
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
package org.keycloak.models.mongo.api.types;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Registry of mappers, which allow to convert application object to database objects. MapperRegistry is main entry point to be used by application.
|
||||
* Application can create instance of MapperRegistry and then register required Mapper objects.
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class MapperRegistry {
|
||||
|
||||
// TODO: Thread-safety support (maybe...)
|
||||
// Mappers of Application objects to DB objects
|
||||
private Map<Class<?>, Mapper<?, ?>> appObjectMappers = new HashMap<Class<?>, Mapper<?, ?>>();
|
||||
|
||||
// Mappers of DB objects to Application objects
|
||||
private Map<Class<?>, Map<Class<?>, Mapper<?, ?>>> dbObjectMappers = new HashMap<Class<?>, Map<Class<?>, Mapper<?,?>>>();
|
||||
|
||||
|
||||
/**
|
||||
* Add mapper for converting application objects to DB objects
|
||||
*
|
||||
* @param mapper
|
||||
*/
|
||||
public void addAppObjectMapper(Mapper<?, ?> mapper) {
|
||||
appObjectMappers.put(mapper.getTypeOfObjectToConvert(), mapper);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add mapper for converting DB objects to application objects
|
||||
*
|
||||
* @param mapper
|
||||
*/
|
||||
public void addDBObjectMapper(Mapper<?, ?> mapper) {
|
||||
Class<?> dbObjectType = mapper.getTypeOfObjectToConvert();
|
||||
Class<?> appObjectType = mapper.getExpectedReturnType();
|
||||
Map<Class<?>, Mapper<?, ?>> appObjects = dbObjectMappers.get(dbObjectType);
|
||||
if (appObjects == null) {
|
||||
appObjects = new HashMap<Class<?>, Mapper<?, ?>>();
|
||||
dbObjectMappers.put(dbObjectType, appObjects);
|
||||
}
|
||||
appObjects.put(appObjectType, mapper);
|
||||
}
|
||||
|
||||
|
||||
public <S> S convertDBObjectToApplicationObject(MapperContext<Object, S> context) {
|
||||
Object dbObject = context.getObjectToConvert();
|
||||
Class<?> expectedApplicationObjectType = context.getExpectedReturnType();
|
||||
|
||||
Class<?> dbObjectType = dbObject.getClass();
|
||||
Mapper<Object, S> mapper;
|
||||
|
||||
Map<Class<?>, Mapper<?, ?>> appObjects = dbObjectMappers.get(dbObjectType);
|
||||
if (appObjects == null) {
|
||||
throw new IllegalArgumentException("Not found any mappers for type " + dbObjectType);
|
||||
} else {
|
||||
if (appObjects.size() == 1) {
|
||||
mapper = (Mapper<Object, S>)appObjects.values().iterator().next();
|
||||
} else {
|
||||
// Try to find converter for requested application type
|
||||
mapper = (Mapper<Object, S>)getAppConverterForType(context.getExpectedReturnType(), appObjects);
|
||||
}
|
||||
}
|
||||
|
||||
if (mapper == null) {
|
||||
throw new IllegalArgumentException("Can't found mapper for type " + dbObjectType + " and expectedApplicationType " + expectedApplicationObjectType);
|
||||
}
|
||||
|
||||
return mapper.convertObject(context);
|
||||
}
|
||||
|
||||
|
||||
public <S> S convertApplicationObjectToDBObject(Object applicationObject, Class<S> expectedDBObjectType) {
|
||||
Class<?> appObjectType = applicationObject.getClass();
|
||||
Mapper<Object, S> mapper = (Mapper<Object, S>)getAppConverterForType(appObjectType, appObjectMappers);
|
||||
if (mapper == null) {
|
||||
throw new IllegalArgumentException("Can't found converter for type " + appObjectType + " in registered appObjectMappers");
|
||||
}
|
||||
if (!expectedDBObjectType.isAssignableFrom(mapper.getExpectedReturnType())) {
|
||||
throw new IllegalArgumentException("Converter " + mapper + " has return type " + mapper.getExpectedReturnType() +
|
||||
" but we need type " + expectedDBObjectType);
|
||||
}
|
||||
return mapper.convertObject(new MapperContext(applicationObject, expectedDBObjectType, null));
|
||||
}
|
||||
|
||||
// Try to find converter for given type or all it's supertypes
|
||||
private static Mapper<Object, ?> getAppConverterForType(Class<?> appObjectType, Map<Class<?>, Mapper<?, ?>> appObjectConverters) {
|
||||
Mapper<Object, ?> mapper = (Mapper<Object, ?>)appObjectConverters.get(appObjectType);
|
||||
if (mapper != null) {
|
||||
return mapper;
|
||||
} else {
|
||||
Class<?>[] interfaces = appObjectType.getInterfaces();
|
||||
for (Class<?> interface1 : interfaces) {
|
||||
mapper = getAppConverterForType(interface1, appObjectConverters);
|
||||
if (mapper != null) {
|
||||
return mapper;
|
||||
}
|
||||
}
|
||||
|
||||
Class<?> superType = appObjectType.getSuperclass();
|
||||
if (superType != null) {
|
||||
return getAppConverterForType(superType, appObjectConverters);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,115 +0,0 @@
|
|||
package org.keycloak.models.mongo.api.types;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Registry of converters, which allow to convert application object to database objects. TypeConverter is main entry point to be used by application.
|
||||
* Application can create instance of TypeConverter and then register required Converter objects.
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class TypeConverter {
|
||||
|
||||
// TODO: Thread-safety support (maybe...)
|
||||
// Converters of Application objects to DB objects
|
||||
private Map<Class<?>, Converter<?, ?>> appObjectConverters = new HashMap<Class<?>, Converter<?, ?>>();
|
||||
|
||||
// Converters of DB objects to Application objects
|
||||
private Map<Class<?>, Map<Class<?>, Converter<?, ?>>> dbObjectConverters = new HashMap<Class<?>, Map<Class<?>, Converter<?,?>>>();
|
||||
|
||||
|
||||
/**
|
||||
* Add converter for converting application objects to DB objects
|
||||
*
|
||||
* @param converter
|
||||
*/
|
||||
public void addAppObjectConverter(Converter<?, ?> converter) {
|
||||
appObjectConverters.put(converter.getConverterObjectType(), converter);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add converter for converting DB objects to application objects
|
||||
*
|
||||
* @param converter
|
||||
*/
|
||||
public void addDBObjectConverter(Converter<?, ?> converter) {
|
||||
Class<?> dbObjectType = converter.getConverterObjectType();
|
||||
Class<?> appObjectType = converter.getExpectedReturnType();
|
||||
Map<Class<?>, Converter<?, ?>> appObjects = dbObjectConverters.get(dbObjectType);
|
||||
if (appObjects == null) {
|
||||
appObjects = new HashMap<Class<?>, Converter<?, ?>>();
|
||||
dbObjectConverters.put(dbObjectType, appObjects);
|
||||
}
|
||||
appObjects.put(appObjectType, converter);
|
||||
}
|
||||
|
||||
|
||||
public Object convertDBObjectToApplicationObject(ConverterContext<Object> context) {
|
||||
Object dbObject = context.getObjectToConvert();
|
||||
Class<?> expectedApplicationObjectType = context.getExpectedReturnType();
|
||||
|
||||
Class<?> dbObjectType = dbObject.getClass();
|
||||
Converter<Object, Object> converter;
|
||||
|
||||
Map<Class<?>, Converter<?, ?>> appObjects = dbObjectConverters.get(dbObjectType);
|
||||
if (appObjects == null) {
|
||||
throw new IllegalArgumentException("Not found any converters for type " + dbObjectType);
|
||||
} else {
|
||||
if (appObjects.size() == 1) {
|
||||
converter = (Converter<Object, Object>)appObjects.values().iterator().next();
|
||||
} else {
|
||||
// Try to find converter for requested application type
|
||||
converter = (Converter<Object, Object>)getAppConverterForType(context.getExpectedReturnType(), appObjects);
|
||||
}
|
||||
}
|
||||
|
||||
if (converter == null) {
|
||||
throw new IllegalArgumentException("Can't found converter for type " + dbObjectType + " and expectedApplicationType " + expectedApplicationObjectType);
|
||||
}
|
||||
/*if (!expectedApplicationObjectType.isAssignableFrom(converter.getExpectedReturnType())) {
|
||||
throw new IllegalArgumentException("Converter " + converter + " has return type " + converter.getExpectedReturnType() +
|
||||
" but we need type " + expectedApplicationObjectType);
|
||||
} */
|
||||
|
||||
return converter.convertObject(context);
|
||||
}
|
||||
|
||||
|
||||
public <S> S convertApplicationObjectToDBObject(Object applicationObject, Class<S> expectedDBObjectType) {
|
||||
Class<?> appObjectType = applicationObject.getClass();
|
||||
Converter<Object, S> converter = (Converter<Object, S>)getAppConverterForType(appObjectType, appObjectConverters);
|
||||
if (converter == null) {
|
||||
throw new IllegalArgumentException("Can't found converter for type " + appObjectType + " in registered appObjectConverters");
|
||||
}
|
||||
if (!expectedDBObjectType.isAssignableFrom(converter.getExpectedReturnType())) {
|
||||
throw new IllegalArgumentException("Converter " + converter + " has return type " + converter.getExpectedReturnType() +
|
||||
" but we need type " + expectedDBObjectType);
|
||||
}
|
||||
return converter.convertObject(new ConverterContext(applicationObject, expectedDBObjectType, null));
|
||||
}
|
||||
|
||||
// Try to find converter for given type or all it's supertypes
|
||||
private static Converter<Object, ?> getAppConverterForType(Class<?> appObjectType, Map<Class<?>, Converter<?, ?>> appObjectConverters) {
|
||||
Converter<Object, ?> converter = (Converter<Object, ?>)appObjectConverters.get(appObjectType);
|
||||
if (converter != null) {
|
||||
return converter;
|
||||
} else {
|
||||
Class<?>[] interfaces = appObjectType.getInterfaces();
|
||||
for (Class<?> interface1 : interfaces) {
|
||||
converter = getAppConverterForType(interface1, appObjectConverters);
|
||||
if (converter != null) {
|
||||
return converter;
|
||||
}
|
||||
}
|
||||
|
||||
Class<?> superType = appObjectType.getSuperclass();
|
||||
if (superType != null) {
|
||||
return getAppConverterForType(superType, appObjectConverters);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ import java.util.Map;
|
|||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class ObjectInfo {
|
||||
public class EntityInfo {
|
||||
|
||||
private final Class<? extends MongoEntity> objectClass;
|
||||
|
||||
|
@ -20,7 +20,7 @@ public class ObjectInfo {
|
|||
|
||||
private final Map<String, Property<Object>> properties;
|
||||
|
||||
public ObjectInfo(Class<? extends MongoEntity> objectClass, String dbCollectionName, List<Property<Object>> properties) {
|
||||
public EntityInfo(Class<? extends MongoEntity> objectClass, String dbCollectionName, List<Property<Object>> properties) {
|
||||
this.objectClass = objectClass;
|
||||
this.dbCollectionName = dbCollectionName;
|
||||
|
|
@ -15,18 +15,18 @@ import org.keycloak.models.mongo.api.MongoIdentifiableEntity;
|
|||
import org.keycloak.models.mongo.api.MongoStore;
|
||||
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
|
||||
import org.keycloak.models.mongo.api.context.MongoTask;
|
||||
import org.keycloak.models.mongo.api.types.Converter;
|
||||
import org.keycloak.models.mongo.api.types.ConverterContext;
|
||||
import org.keycloak.models.mongo.api.types.TypeConverter;
|
||||
import org.keycloak.models.mongo.impl.types.BasicDBListConverter;
|
||||
import org.keycloak.models.mongo.impl.types.BasicDBObjectConverter;
|
||||
import org.keycloak.models.mongo.impl.types.BasicDBObjectToMapConverter;
|
||||
import org.keycloak.models.mongo.impl.types.EnumToStringConverter;
|
||||
import org.keycloak.models.mongo.impl.types.ListConverter;
|
||||
import org.keycloak.models.mongo.impl.types.MapConverter;
|
||||
import org.keycloak.models.mongo.impl.types.MongoEntityConverter;
|
||||
import org.keycloak.models.mongo.impl.types.SimpleConverter;
|
||||
import org.keycloak.models.mongo.impl.types.StringToEnumConverter;
|
||||
import org.keycloak.models.mongo.api.types.Mapper;
|
||||
import org.keycloak.models.mongo.api.types.MapperContext;
|
||||
import org.keycloak.models.mongo.api.types.MapperRegistry;
|
||||
import org.keycloak.models.mongo.impl.types.BasicDBListMapper;
|
||||
import org.keycloak.models.mongo.impl.types.BasicDBObjectMapper;
|
||||
import org.keycloak.models.mongo.impl.types.BasicDBObjectToMapMapper;
|
||||
import org.keycloak.models.mongo.impl.types.EnumToStringMapper;
|
||||
import org.keycloak.models.mongo.impl.types.ListMapper;
|
||||
import org.keycloak.models.mongo.impl.types.MapMapper;
|
||||
import org.keycloak.models.mongo.impl.types.MongoEntityMapper;
|
||||
import org.keycloak.models.mongo.impl.types.SimpleMapper;
|
||||
import org.keycloak.models.mongo.impl.types.StringToEnumMapper;
|
||||
import org.picketlink.common.properties.Property;
|
||||
import org.picketlink.common.properties.query.AnnotatedPropertyCriteria;
|
||||
import org.picketlink.common.properties.query.PropertyQueries;
|
||||
|
@ -49,39 +49,39 @@ public class MongoStoreImpl implements MongoStore {
|
|||
private final DB database;
|
||||
private static final Logger logger = Logger.getLogger(MongoStoreImpl.class);
|
||||
|
||||
private final TypeConverter typeConverter;
|
||||
private ConcurrentMap<Class<? extends MongoEntity>, ObjectInfo> objectInfoCache =
|
||||
new ConcurrentHashMap<Class<? extends MongoEntity>, ObjectInfo>();
|
||||
private final MapperRegistry mapperRegistry;
|
||||
private ConcurrentMap<Class<? extends MongoEntity>, EntityInfo> entityInfoCache =
|
||||
new ConcurrentHashMap<Class<? extends MongoEntity>, EntityInfo>();
|
||||
|
||||
|
||||
public MongoStoreImpl(DB database, boolean clearCollectionsOnStartup, Class<? extends MongoEntity>[] managedEntityTypes) {
|
||||
this.database = database;
|
||||
|
||||
typeConverter = new TypeConverter();
|
||||
mapperRegistry = new MapperRegistry();
|
||||
|
||||
for (Class<?> simpleConverterClass : SIMPLE_TYPES) {
|
||||
SimpleConverter converter = new SimpleConverter(simpleConverterClass);
|
||||
typeConverter.addAppObjectConverter(converter);
|
||||
typeConverter.addDBObjectConverter(converter);
|
||||
SimpleMapper converter = new SimpleMapper(simpleConverterClass);
|
||||
mapperRegistry.addAppObjectMapper(converter);
|
||||
mapperRegistry.addDBObjectMapper(converter);
|
||||
}
|
||||
|
||||
// Specific converter for ArrayList is added just for performance purposes to avoid recursive converter lookup (most of list impl will be ArrayList)
|
||||
typeConverter.addAppObjectConverter(new ListConverter(typeConverter, ArrayList.class));
|
||||
typeConverter.addAppObjectConverter(new ListConverter(typeConverter, List.class));
|
||||
typeConverter.addDBObjectConverter(new BasicDBListConverter(typeConverter));
|
||||
mapperRegistry.addAppObjectMapper(new ListMapper(mapperRegistry, ArrayList.class));
|
||||
mapperRegistry.addAppObjectMapper(new ListMapper(mapperRegistry, List.class));
|
||||
mapperRegistry.addDBObjectMapper(new BasicDBListMapper(mapperRegistry));
|
||||
|
||||
typeConverter.addAppObjectConverter(new MapConverter(HashMap.class));
|
||||
typeConverter.addAppObjectConverter(new MapConverter(Map.class));
|
||||
typeConverter.addDBObjectConverter(new BasicDBObjectToMapConverter());
|
||||
mapperRegistry.addAppObjectMapper(new MapMapper(HashMap.class));
|
||||
mapperRegistry.addAppObjectMapper(new MapMapper(Map.class));
|
||||
mapperRegistry.addDBObjectMapper(new BasicDBObjectToMapMapper());
|
||||
|
||||
// Enum converters
|
||||
typeConverter.addAppObjectConverter(new EnumToStringConverter());
|
||||
typeConverter.addDBObjectConverter(new StringToEnumConverter());
|
||||
mapperRegistry.addAppObjectMapper(new EnumToStringMapper());
|
||||
mapperRegistry.addDBObjectMapper(new StringToEnumMapper());
|
||||
|
||||
for (Class<? extends MongoEntity> type : managedEntityTypes) {
|
||||
getObjectInfo(type);
|
||||
typeConverter.addAppObjectConverter(new MongoEntityConverter(this, typeConverter, type));
|
||||
typeConverter.addDBObjectConverter(new BasicDBObjectConverter(this, typeConverter, type));
|
||||
getEntityInfo(type);
|
||||
mapperRegistry.addAppObjectMapper(new MongoEntityMapper(this, mapperRegistry, type));
|
||||
mapperRegistry.addDBObjectMapper(new BasicDBObjectMapper(this, mapperRegistry, type));
|
||||
}
|
||||
|
||||
if (clearCollectionsOnStartup) {
|
||||
|
@ -107,18 +107,18 @@ public class MongoStoreImpl implements MongoStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void insertObject(MongoIdentifiableEntity object, MongoStoreInvocationContext context) {
|
||||
Class<? extends MongoEntity> clazz = object.getClass();
|
||||
public void insertEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context) {
|
||||
Class<? extends MongoEntity> clazz = entity.getClass();
|
||||
|
||||
// Find annotations for ID, for all the properties and for the name of the collection.
|
||||
ObjectInfo objectInfo = getObjectInfo(clazz);
|
||||
EntityInfo entityInfo = getEntityInfo(clazz);
|
||||
|
||||
// Create instance of BasicDBObject and add all declared properties to it (properties with null value probably should be skipped)
|
||||
BasicDBObject dbObject = typeConverter.convertApplicationObjectToDBObject(object, BasicDBObject.class);
|
||||
BasicDBObject dbObject = mapperRegistry.convertApplicationObjectToDBObject(entity, BasicDBObject.class);
|
||||
|
||||
DBCollection dbCollection = database.getCollection(objectInfo.getDbCollectionName());
|
||||
DBCollection dbCollection = database.getCollection(entityInfo.getDbCollectionName());
|
||||
|
||||
String currentId = object.getId();
|
||||
String currentId = entity.getId();
|
||||
|
||||
// Inserting object, which already has oid property set. So we need to set "_id"
|
||||
if (currentId != null) {
|
||||
|
@ -129,28 +129,28 @@ public class MongoStoreImpl implements MongoStore {
|
|||
|
||||
// Add id to value of given object
|
||||
if (currentId == null) {
|
||||
object.setId(dbObject.getString("_id"));
|
||||
entity.setId(dbObject.getString("_id"));
|
||||
}
|
||||
|
||||
// Treat object as if it is read (It is already submited to transaction)
|
||||
context.addLoadedObject(object);
|
||||
context.addLoadedObject(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateObject(final MongoIdentifiableEntity object, MongoStoreInvocationContext context) {
|
||||
public void updateEntity(final MongoIdentifiableEntity entity, MongoStoreInvocationContext context) {
|
||||
MongoTask fullUpdateTask = new MongoTask() {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
Class<? extends MongoEntity> clazz = object.getClass();
|
||||
ObjectInfo objectInfo = getObjectInfo(clazz);
|
||||
BasicDBObject dbObject = typeConverter.convertApplicationObjectToDBObject(object, BasicDBObject.class);
|
||||
DBCollection dbCollection = database.getCollection(objectInfo.getDbCollectionName());
|
||||
Class<? extends MongoEntity> clazz = entity.getClass();
|
||||
EntityInfo entityInfo = getEntityInfo(clazz);
|
||||
BasicDBObject dbObject = mapperRegistry.convertApplicationObjectToDBObject(entity, BasicDBObject.class);
|
||||
DBCollection dbCollection = database.getCollection(entityInfo.getDbCollectionName());
|
||||
|
||||
String currentId = object.getId();
|
||||
String currentId = entity.getId();
|
||||
|
||||
if (currentId == null) {
|
||||
throw new IllegalStateException("Can't update object without id: " + object);
|
||||
throw new IllegalStateException("Can't update entity without id: " + entity);
|
||||
} else {
|
||||
BasicDBObject query = new BasicDBObject("_id", getObjectId(currentId));
|
||||
dbCollection.update(query, dbObject);
|
||||
|
@ -164,12 +164,12 @@ public class MongoStoreImpl implements MongoStore {
|
|||
};
|
||||
|
||||
// update is just added to context and postponed
|
||||
context.addUpdateTask(object, fullUpdateTask);
|
||||
context.addUpdateTask(entity, fullUpdateTask);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T extends MongoIdentifiableEntity> T loadObject(Class<T> type, String id, MongoStoreInvocationContext context) {
|
||||
public <T extends MongoIdentifiableEntity> T loadEntity(Class<T> type, String id, MongoStoreInvocationContext context) {
|
||||
// First look if we already read the object with this oid and type during this transaction. If yes, use it instead of DB lookup
|
||||
T cached = context.getLoadedObject(type, id);
|
||||
if (cached != null) return cached;
|
||||
|
@ -181,8 +181,8 @@ public class MongoStoreImpl implements MongoStore {
|
|||
|
||||
if (dbObject == null) return null;
|
||||
|
||||
ConverterContext<Object> converterContext = new ConverterContext<Object>(dbObject, type, null);
|
||||
T converted = (T)typeConverter.convertDBObjectToApplicationObject(converterContext);
|
||||
MapperContext<Object, T> mapperContext = new MapperContext<Object, T>(dbObject, type, null);
|
||||
T converted = mapperRegistry.convertDBObjectToApplicationObject(mapperContext);
|
||||
|
||||
// Now add it to loaded objects
|
||||
context.addLoadedObject(converted);
|
||||
|
@ -192,8 +192,8 @@ public class MongoStoreImpl implements MongoStore {
|
|||
|
||||
|
||||
@Override
|
||||
public <T extends MongoIdentifiableEntity> T loadSingleObject(Class<T> type, DBObject query, MongoStoreInvocationContext context) {
|
||||
List<T> result = loadObjects(type, query, context);
|
||||
public <T extends MongoIdentifiableEntity> T loadSingleEntity(Class<T> type, DBObject query, MongoStoreInvocationContext context) {
|
||||
List<T> result = loadEntities(type, query, context);
|
||||
if (result.size() > 1) {
|
||||
throw new IllegalStateException("There are " + result.size() + " results for type=" + type + ", query=" + query + ". We expect just one");
|
||||
} else if (result.size() == 1) {
|
||||
|
@ -206,7 +206,7 @@ public class MongoStoreImpl implements MongoStore {
|
|||
|
||||
|
||||
@Override
|
||||
public <T extends MongoIdentifiableEntity> List<T> loadObjects(Class<T> type, DBObject query, MongoStoreInvocationContext context) {
|
||||
public <T extends MongoIdentifiableEntity> List<T> loadEntities(Class<T> type, DBObject query, MongoStoreInvocationContext context) {
|
||||
// First we should execute all pending tasks before searching DB
|
||||
context.beforeDBSearch(type);
|
||||
|
||||
|
@ -218,21 +218,21 @@ public class MongoStoreImpl implements MongoStore {
|
|||
|
||||
|
||||
@Override
|
||||
public boolean removeObject(MongoIdentifiableEntity object, MongoStoreInvocationContext context) {
|
||||
return removeObject(object.getClass(), object.getId(), context);
|
||||
public boolean removeEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context) {
|
||||
return removeEntity(entity.getClass(), entity.getId(), context);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean removeObject(Class<? extends MongoIdentifiableEntity> type, String id, MongoStoreInvocationContext context) {
|
||||
MongoIdentifiableEntity found = loadObject(type, id, context);
|
||||
public boolean removeEntity(Class<? extends MongoIdentifiableEntity> type, String id, MongoStoreInvocationContext context) {
|
||||
MongoIdentifiableEntity found = loadEntity(type, id, context);
|
||||
if (found == null) {
|
||||
return false;
|
||||
} else {
|
||||
DBCollection dbCollection = getDBCollectionForType(type);
|
||||
BasicDBObject dbQuery = new BasicDBObject("_id", getObjectId(id));
|
||||
dbCollection.remove(dbQuery);
|
||||
logger.info("Object of type: " + type + ", id: " + id + " removed from MongoDB.");
|
||||
logger.info("Entity of type: " + type + ", id: " + id + " removed from MongoDB.");
|
||||
|
||||
context.addRemovedObject(found);
|
||||
return true;
|
||||
|
@ -241,14 +241,14 @@ public class MongoStoreImpl implements MongoStore {
|
|||
|
||||
|
||||
@Override
|
||||
public boolean removeObjects(Class<? extends MongoIdentifiableEntity> type, DBObject query, MongoStoreInvocationContext context) {
|
||||
List<? extends MongoIdentifiableEntity> foundObjects = loadObjects(type, query, context);
|
||||
public boolean removeEntities(Class<? extends MongoIdentifiableEntity> type, DBObject query, MongoStoreInvocationContext context) {
|
||||
List<? extends MongoIdentifiableEntity> foundObjects = loadEntities(type, query, context);
|
||||
if (foundObjects.size() == 0) {
|
||||
return false;
|
||||
} else {
|
||||
DBCollection dbCollection = getDBCollectionForType(type);
|
||||
dbCollection.remove(query);
|
||||
logger.info("Removed " + foundObjects.size() + " objects of type: " + type + ", query: " + query);
|
||||
logger.info("Removed " + foundObjects.size() + " entities of type: " + type + ", query: " + query);
|
||||
|
||||
for (MongoIdentifiableEntity found : foundObjects) {
|
||||
context.addRemovedObject(found);;
|
||||
|
@ -258,20 +258,20 @@ public class MongoStoreImpl implements MongoStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <S> boolean pushItemToList(final MongoIdentifiableEntity object, final String listPropertyName, S itemToPush, boolean skipIfAlreadyPresent, MongoStoreInvocationContext context) {
|
||||
final Class<? extends MongoEntity> type = object.getClass();
|
||||
ObjectInfo objectInfo = getObjectInfo(type);
|
||||
public <S> boolean pushItemToList(final MongoIdentifiableEntity entity, final String listPropertyName, S itemToPush, boolean skipIfAlreadyPresent, MongoStoreInvocationContext context) {
|
||||
final Class<? extends MongoEntity> type = entity.getClass();
|
||||
EntityInfo entityInfo = getEntityInfo(type);
|
||||
|
||||
// Add item to list directly in this object
|
||||
Property<Object> listProperty = objectInfo.getPropertyByName(listPropertyName);
|
||||
Property<Object> listProperty = entityInfo.getPropertyByName(listPropertyName);
|
||||
if (listProperty == null) {
|
||||
throw new IllegalArgumentException("Property " + listPropertyName + " doesn't exist on object " + object);
|
||||
throw new IllegalArgumentException("Property " + listPropertyName + " doesn't exist on object " + entity);
|
||||
}
|
||||
|
||||
List<S> list = (List<S>)listProperty.getValue(object);
|
||||
List<S> list = (List<S>)listProperty.getValue(entity);
|
||||
if (list == null) {
|
||||
list = new ArrayList<S>();
|
||||
listProperty.setValue(object, list);
|
||||
listProperty.setValue(entity, list);
|
||||
}
|
||||
|
||||
// Skip if item is already in list
|
||||
|
@ -284,14 +284,14 @@ public class MongoStoreImpl implements MongoStore {
|
|||
|
||||
// Add update of list to pending tasks
|
||||
final List<S> listt = list;
|
||||
context.addUpdateTask(object, new MongoTask() {
|
||||
context.addUpdateTask(entity, new MongoTask() {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
// Now DB update of new list with usage of $set
|
||||
BasicDBList dbList = typeConverter.convertApplicationObjectToDBObject(listt, BasicDBList.class);
|
||||
BasicDBList dbList = mapperRegistry.convertApplicationObjectToDBObject(listt, BasicDBList.class);
|
||||
|
||||
BasicDBObject query = new BasicDBObject("_id", getObjectId(object.getId()));
|
||||
BasicDBObject query = new BasicDBObject("_id", getObjectId(entity.getId()));
|
||||
BasicDBObject listObject = new BasicDBObject(listPropertyName, dbList);
|
||||
BasicDBObject setCommand = new BasicDBObject("$set", listObject);
|
||||
getDBCollectionForType(type).update(query, setCommand);
|
||||
|
@ -308,16 +308,16 @@ public class MongoStoreImpl implements MongoStore {
|
|||
|
||||
|
||||
@Override
|
||||
public <S> boolean pullItemFromList(final MongoIdentifiableEntity object, final String listPropertyName, final S itemToPull, MongoStoreInvocationContext context) {
|
||||
final Class<? extends MongoEntity> type = object.getClass();
|
||||
ObjectInfo objectInfo = getObjectInfo(type);
|
||||
public <S> boolean pullItemFromList(final MongoIdentifiableEntity entity, final String listPropertyName, final S itemToPull, MongoStoreInvocationContext context) {
|
||||
final Class<? extends MongoEntity> type = entity.getClass();
|
||||
EntityInfo entityInfo = getEntityInfo(type);
|
||||
|
||||
// Remove item from list directly in this object
|
||||
Property<Object> listProperty = objectInfo.getPropertyByName(listPropertyName);
|
||||
Property<Object> listProperty = entityInfo.getPropertyByName(listPropertyName);
|
||||
if (listProperty == null) {
|
||||
throw new IllegalArgumentException("Property " + listPropertyName + " doesn't exist on object " + object);
|
||||
throw new IllegalArgumentException("Property " + listPropertyName + " doesn't exist on object " + entity);
|
||||
}
|
||||
List<S> list = (List<S>)listProperty.getValue(object);
|
||||
List<S> list = (List<S>)listProperty.getValue(entity);
|
||||
|
||||
// If list is null, we skip both object and DB update
|
||||
if (list == null || !list.contains(itemToPull)) {
|
||||
|
@ -328,13 +328,13 @@ public class MongoStoreImpl implements MongoStore {
|
|||
list.remove(itemToPull);
|
||||
|
||||
// Add update of list to pending tasks
|
||||
context.addUpdateTask(object, new MongoTask() {
|
||||
context.addUpdateTask(entity, new MongoTask() {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
// Pull item from DB
|
||||
Object dbItemToPull = typeConverter.convertApplicationObjectToDBObject(itemToPull, Object.class);
|
||||
BasicDBObject query = new BasicDBObject("_id", getObjectId(object.getId()));
|
||||
Object dbItemToPull = mapperRegistry.convertApplicationObjectToDBObject(itemToPull, Object.class);
|
||||
BasicDBObject query = new BasicDBObject("_id", getObjectId(entity.getId()));
|
||||
BasicDBObject pullObject = new BasicDBObject(listPropertyName, dbItemToPull);
|
||||
BasicDBObject pullCommand = new BasicDBObject("$pull", pullObject);
|
||||
getDBCollectionForType(type).update(query, pullCommand);
|
||||
|
@ -351,31 +351,31 @@ public class MongoStoreImpl implements MongoStore {
|
|||
}
|
||||
|
||||
// Possibility to add user-defined converters
|
||||
public void addAppObjectConverter(Converter<?, ?> converter) {
|
||||
typeConverter.addAppObjectConverter(converter);
|
||||
public void addAppObjectConverter(Mapper<?, ?> mapper) {
|
||||
mapperRegistry.addAppObjectMapper(mapper);
|
||||
}
|
||||
|
||||
public void addDBObjectConverter(Converter<?, ?> converter) {
|
||||
typeConverter.addDBObjectConverter(converter);
|
||||
public void addDBObjectConverter(Mapper<?, ?> mapper) {
|
||||
mapperRegistry.addDBObjectMapper(mapper);
|
||||
}
|
||||
|
||||
public ObjectInfo getObjectInfo(Class<? extends MongoEntity> objectClass) {
|
||||
ObjectInfo objectInfo = objectInfoCache.get(objectClass);
|
||||
if (objectInfo == null) {
|
||||
public EntityInfo getEntityInfo(Class<? extends MongoEntity> objectClass) {
|
||||
EntityInfo entityInfo = entityInfoCache.get(objectClass);
|
||||
if (entityInfo == null) {
|
||||
List<Property<Object>> properties = PropertyQueries.createQuery(objectClass).addCriteria(new AnnotatedPropertyCriteria(MongoField.class)).getResultList();
|
||||
|
||||
MongoCollection classAnnotation = objectClass.getAnnotation(MongoCollection.class);
|
||||
|
||||
String dbCollectionName = classAnnotation==null ? null : classAnnotation.collectionName();
|
||||
objectInfo = new ObjectInfo(objectClass, dbCollectionName, properties);
|
||||
entityInfo = new EntityInfo(objectClass, dbCollectionName, properties);
|
||||
|
||||
ObjectInfo existing = objectInfoCache.putIfAbsent(objectClass, objectInfo);
|
||||
EntityInfo existing = entityInfoCache.putIfAbsent(objectClass, entityInfo);
|
||||
if (existing != null) {
|
||||
objectInfo = existing;
|
||||
entityInfo = existing;
|
||||
}
|
||||
}
|
||||
|
||||
return objectInfo;
|
||||
return entityInfo;
|
||||
}
|
||||
|
||||
protected <T extends MongoIdentifiableEntity> List<T> convertCursor(Class<T> type, DBCursor cursor, MongoStoreInvocationContext context) {
|
||||
|
@ -389,8 +389,8 @@ public class MongoStoreImpl implements MongoStore {
|
|||
|
||||
if (object == null) {
|
||||
// So convert and use fresh instance from DB
|
||||
ConverterContext<Object> converterContext = new ConverterContext<Object>(dbObject, type, null);
|
||||
object = (T)typeConverter.convertDBObjectToApplicationObject(converterContext);
|
||||
MapperContext<Object, T> mapperContext = new MapperContext<Object, T>(dbObject, type, null);
|
||||
object = mapperRegistry.convertDBObjectToApplicationObject(mapperContext);
|
||||
context.addLoadedObject(object);
|
||||
}
|
||||
|
||||
|
@ -404,9 +404,9 @@ public class MongoStoreImpl implements MongoStore {
|
|||
}
|
||||
|
||||
protected DBCollection getDBCollectionForType(Class<? extends MongoEntity> type) {
|
||||
ObjectInfo objectInfo = getObjectInfo(type);
|
||||
String dbCollectionName = objectInfo.getDbCollectionName();
|
||||
return dbCollectionName==null ? null : database.getCollection(objectInfo.getDbCollectionName());
|
||||
EntityInfo entityInfo = getEntityInfo(type);
|
||||
String dbCollectionName = entityInfo.getDbCollectionName();
|
||||
return dbCollectionName==null ? null : database.getCollection(entityInfo.getDbCollectionName());
|
||||
}
|
||||
|
||||
// We allow ObjectId to be both "ObjectId" or "String".
|
||||
|
|
|
@ -13,10 +13,14 @@ import org.keycloak.models.mongo.api.context.MongoTask;
|
|||
*/
|
||||
public class SimpleMongoStoreInvocationContext implements MongoStoreInvocationContext {
|
||||
|
||||
private final MongoStore store;
|
||||
private final MongoStore mongoStore;
|
||||
|
||||
public SimpleMongoStoreInvocationContext(MongoStore store) {
|
||||
this.store = store;
|
||||
public SimpleMongoStoreInvocationContext(MongoStore mongoStore) {
|
||||
this.mongoStore = mongoStore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCreatedObject(MongoIdentifiableEntity entity) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -35,7 +39,7 @@ public class SimpleMongoStoreInvocationContext implements MongoStoreInvocationCo
|
|||
|
||||
@Override
|
||||
public void addRemovedObject(MongoIdentifiableEntity entityToRemove) {
|
||||
entityToRemove.afterRemove(store, this);
|
||||
entityToRemove.afterRemove(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -53,4 +57,9 @@ public class SimpleMongoStoreInvocationContext implements MongoStoreInvocationCo
|
|||
@Override
|
||||
public void rollback() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MongoStore getMongoStore() {
|
||||
return mongoStore;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package org.keycloak.models.mongo.impl.context;
|
|||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -31,6 +32,12 @@ public class TransactionMongoStoreInvocationContext implements MongoStoreInvocat
|
|||
this.mongoStore = mongoStore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCreatedObject(MongoIdentifiableEntity entity) {
|
||||
// For now just add it to list of loaded objects
|
||||
addLoadedObject(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLoadedObject(MongoIdentifiableEntity entity) {
|
||||
loadedObjects.put(entity.getId(), entity);
|
||||
|
@ -49,7 +56,7 @@ public class TransactionMongoStoreInvocationContext implements MongoStoreInvocat
|
|||
|
||||
Set<MongoTask> currentObjectTasks = pendingUpdateTasks.get(entityToUpdate);
|
||||
if (currentObjectTasks == null) {
|
||||
currentObjectTasks = new HashSet<MongoTask>();
|
||||
currentObjectTasks = new LinkedHashSet<MongoTask>();
|
||||
pendingUpdateTasks.put(entityToUpdate, currentObjectTasks);
|
||||
} else {
|
||||
// if task is full update, then remove all other tasks as we need to do full update of object anyway
|
||||
|
@ -74,7 +81,7 @@ public class TransactionMongoStoreInvocationContext implements MongoStoreInvocat
|
|||
pendingUpdateTasks.remove(entityToRemove);
|
||||
loadedObjects.remove(entityToRemove.getId());
|
||||
|
||||
entityToRemove.afterRemove(mongoStore, this);
|
||||
entityToRemove.afterRemove(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -107,8 +114,6 @@ public class TransactionMongoStoreInvocationContext implements MongoStoreInvocat
|
|||
|
||||
@Override
|
||||
public void commit() {
|
||||
loadedObjects.clear();
|
||||
|
||||
// Now execute all pending update tasks
|
||||
for (Set<MongoTask> mongoTasks : pendingUpdateTasks.values()) {
|
||||
for (MongoTask currentTask : mongoTasks) {
|
||||
|
@ -117,13 +122,19 @@ public class TransactionMongoStoreInvocationContext implements MongoStoreInvocat
|
|||
}
|
||||
|
||||
// And clear it
|
||||
loadedObjects.clear();
|
||||
pendingUpdateTasks.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollback() {
|
||||
// Just clear the map without executions of tasks
|
||||
// Just clear the map without executions of tasks TODO: Attempt to do complete rollback (removal of created objects, restoring of removed objects, rollback of updates)
|
||||
loadedObjects.clear();
|
||||
pendingUpdateTasks.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MongoStore getMongoStore() {
|
||||
return mongoStore;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
package org.keycloak.models.mongo.impl.types;
|
||||
|
||||
import com.mongodb.BasicDBList;
|
||||
import org.keycloak.models.mongo.api.types.Converter;
|
||||
import org.keycloak.models.mongo.api.types.ConverterContext;
|
||||
import org.keycloak.models.mongo.api.types.TypeConverter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class BasicDBListConverter implements Converter<BasicDBList, List> {
|
||||
|
||||
private final TypeConverter typeConverter;
|
||||
|
||||
public BasicDBListConverter(TypeConverter typeConverter) {
|
||||
this.typeConverter = typeConverter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List convertObject(ConverterContext<BasicDBList> context) {
|
||||
BasicDBList dbList = context.getObjectToConvert();
|
||||
ArrayList<Object> appObjects = new ArrayList<Object>();
|
||||
Class<?> expectedListElementType = context.getGenericTypes().get(0);
|
||||
|
||||
for (Object dbObject : dbList) {
|
||||
ConverterContext<Object> newContext = new ConverterContext<Object>(dbObject, expectedListElementType, null);
|
||||
appObjects.add(typeConverter.convertDBObjectToApplicationObject(newContext));
|
||||
}
|
||||
return appObjects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends BasicDBList> getConverterObjectType() {
|
||||
return BasicDBList.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<List> getExpectedReturnType() {
|
||||
return List.class;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package org.keycloak.models.mongo.impl.types;
|
||||
|
||||
import com.mongodb.BasicDBList;
|
||||
import org.keycloak.models.mongo.api.types.Mapper;
|
||||
import org.keycloak.models.mongo.api.types.MapperContext;
|
||||
import org.keycloak.models.mongo.api.types.MapperRegistry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class BasicDBListMapper implements Mapper<BasicDBList, List> {
|
||||
|
||||
private final MapperRegistry mapperRegistry;
|
||||
|
||||
public BasicDBListMapper(MapperRegistry mapperRegistry) {
|
||||
this.mapperRegistry = mapperRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List convertObject(MapperContext<BasicDBList, List> context) {
|
||||
BasicDBList dbList = context.getObjectToConvert();
|
||||
ArrayList<Object> appObjects = new ArrayList<Object>();
|
||||
Class<?> expectedListElementType = context.getGenericTypes().get(0);
|
||||
|
||||
for (Object dbObject : dbList) {
|
||||
MapperContext<Object, Object> newContext = new MapperContext<Object, Object>(dbObject, expectedListElementType, null);
|
||||
appObjects.add(mapperRegistry.convertDBObjectToApplicationObject(newContext));
|
||||
}
|
||||
return appObjects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends BasicDBList> getTypeOfObjectToConvert() {
|
||||
return BasicDBList.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<List> getExpectedReturnType() {
|
||||
return List.class;
|
||||
}
|
||||
}
|
|
@ -9,39 +9,39 @@ import com.mongodb.BasicDBObject;
|
|||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.models.mongo.api.MongoEntity;
|
||||
import org.keycloak.models.mongo.api.MongoIdentifiableEntity;
|
||||
import org.keycloak.models.mongo.api.types.Converter;
|
||||
import org.keycloak.models.mongo.api.types.ConverterContext;
|
||||
import org.keycloak.models.mongo.api.types.TypeConverter;
|
||||
import org.keycloak.models.mongo.api.types.Mapper;
|
||||
import org.keycloak.models.mongo.api.types.MapperContext;
|
||||
import org.keycloak.models.mongo.api.types.MapperRegistry;
|
||||
import org.keycloak.models.mongo.impl.MongoStoreImpl;
|
||||
import org.keycloak.models.mongo.impl.ObjectInfo;
|
||||
import org.keycloak.models.mongo.impl.EntityInfo;
|
||||
import org.picketlink.common.properties.Property;
|
||||
import org.picketlink.common.reflection.Types;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class BasicDBObjectConverter<S extends MongoEntity> implements Converter<BasicDBObject, S> {
|
||||
public class BasicDBObjectMapper<S extends MongoEntity> implements Mapper<BasicDBObject, S> {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(BasicDBObjectConverter.class);
|
||||
private static final Logger logger = Logger.getLogger(BasicDBObjectMapper.class);
|
||||
|
||||
private final MongoStoreImpl mongoStoreImpl;
|
||||
private final TypeConverter typeConverter;
|
||||
private final MapperRegistry mapperRegistry;
|
||||
private final Class<S> expectedObjectType;
|
||||
|
||||
public BasicDBObjectConverter(MongoStoreImpl mongoStoreImpl, TypeConverter typeConverter, Class<S> expectedObjectType) {
|
||||
public BasicDBObjectMapper(MongoStoreImpl mongoStoreImpl, MapperRegistry mapperRegistry, Class<S> expectedObjectType) {
|
||||
this.mongoStoreImpl = mongoStoreImpl;
|
||||
this.typeConverter = typeConverter;
|
||||
this.mapperRegistry = mapperRegistry;
|
||||
this.expectedObjectType = expectedObjectType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public S convertObject(ConverterContext<BasicDBObject> context) {
|
||||
public S convertObject(MapperContext<BasicDBObject, S> context) {
|
||||
BasicDBObject dbObject = context.getObjectToConvert();
|
||||
if (dbObject == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ObjectInfo objectInfo = mongoStoreImpl.getObjectInfo(expectedObjectType);
|
||||
EntityInfo entityInfo = mongoStoreImpl.getEntityInfo(expectedObjectType);
|
||||
|
||||
S object;
|
||||
try {
|
||||
|
@ -60,7 +60,7 @@ public class BasicDBObjectConverter<S extends MongoEntity> implements Converter<
|
|||
((MongoIdentifiableEntity)object).setId(value.toString());
|
||||
}
|
||||
|
||||
} else if ((property = objectInfo.getPropertyByName(key)) != null) {
|
||||
} else if ((property = entityInfo.getPropertyByName(key)) != null) {
|
||||
// It's declared property with @DBField annotation
|
||||
setPropertyValue(object, value, property);
|
||||
|
||||
|
@ -79,7 +79,7 @@ public class BasicDBObjectConverter<S extends MongoEntity> implements Converter<
|
|||
return;
|
||||
}
|
||||
|
||||
ConverterContext<Object> context;
|
||||
MapperContext<Object, ?> context;
|
||||
|
||||
Type type = property.getBaseType();
|
||||
|
||||
|
@ -94,15 +94,15 @@ public class BasicDBObjectConverter<S extends MongoEntity> implements Converter<
|
|||
}
|
||||
|
||||
Class<?> expectedReturnType = (Class<?>)parameterized.getRawType();
|
||||
context = new ConverterContext<Object>(valueFromDB, expectedReturnType, genericTypes);
|
||||
context = new MapperContext<Object, Object>(valueFromDB, expectedReturnType, genericTypes);
|
||||
} else {
|
||||
Class<?> expectedReturnType = (Class<?>)type;
|
||||
// handle primitives
|
||||
expectedReturnType = Types.boxedClass(expectedReturnType);
|
||||
context = new ConverterContext<Object>(valueFromDB, expectedReturnType, null);
|
||||
context = new MapperContext<Object, Object>(valueFromDB, expectedReturnType, null);
|
||||
}
|
||||
|
||||
Object appObject = typeConverter.convertDBObjectToApplicationObject(context);
|
||||
Object appObject = mapperRegistry.convertDBObjectToApplicationObject(context);
|
||||
|
||||
if (Types.boxedClass(property.getJavaClass()).isAssignableFrom(appObject.getClass())) {
|
||||
property.setValue(object, appObject);
|
||||
|
@ -113,7 +113,7 @@ public class BasicDBObjectConverter<S extends MongoEntity> implements Converter<
|
|||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends BasicDBObject> getConverterObjectType() {
|
||||
public Class<? extends BasicDBObject> getTypeOfObjectToConvert() {
|
||||
return BasicDBObject.class;
|
||||
}
|
||||
|
|
@ -4,18 +4,18 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import org.keycloak.models.mongo.api.types.Converter;
|
||||
import org.keycloak.models.mongo.api.types.ConverterContext;
|
||||
import org.keycloak.models.mongo.api.types.Mapper;
|
||||
import org.keycloak.models.mongo.api.types.MapperContext;
|
||||
|
||||
/**
|
||||
* For now, we support just convert to Map<String, String>
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class BasicDBObjectToMapConverter implements Converter<BasicDBObject, Map> {
|
||||
public class BasicDBObjectToMapMapper implements Mapper<BasicDBObject, Map> {
|
||||
|
||||
@Override
|
||||
public Map convertObject(ConverterContext<BasicDBObject> context) {
|
||||
public Map convertObject(MapperContext<BasicDBObject, Map> context) {
|
||||
BasicDBObject objectToConvert = context.getObjectToConvert();
|
||||
|
||||
HashMap<String, String> result = new HashMap<String, String>();
|
||||
|
@ -23,8 +23,8 @@ public class BasicDBObjectToMapConverter implements Converter<BasicDBObject, Map
|
|||
String key = entry.getKey();
|
||||
String value = (String)entry.getValue();
|
||||
|
||||
if (key.contains(MapConverter.DOT_PLACEHOLDER)) {
|
||||
key = key.replaceAll(MapConverter.DOT_PLACEHOLDER, ".");
|
||||
if (key.contains(MapMapper.DOT_PLACEHOLDER)) {
|
||||
key = key.replaceAll(MapMapper.DOT_PLACEHOLDER, ".");
|
||||
}
|
||||
|
||||
result.put(key, value);
|
||||
|
@ -33,7 +33,7 @@ public class BasicDBObjectToMapConverter implements Converter<BasicDBObject, Map
|
|||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends BasicDBObject> getConverterObjectType() {
|
||||
public Class<? extends BasicDBObject> getTypeOfObjectToConvert() {
|
||||
return BasicDBObject.class;
|
||||
}
|
||||
|
|
@ -1,23 +1,23 @@
|
|||
package org.keycloak.models.mongo.impl.types;
|
||||
|
||||
import org.keycloak.models.mongo.api.types.Converter;
|
||||
import org.keycloak.models.mongo.api.types.ConverterContext;
|
||||
import org.keycloak.models.mongo.api.types.Mapper;
|
||||
import org.keycloak.models.mongo.api.types.MapperContext;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class EnumToStringConverter implements Converter<Enum, String> {
|
||||
public class EnumToStringMapper implements Mapper<Enum, String> {
|
||||
|
||||
// It will be saved in form of "org.keycloak.Gender#MALE" so it's possible to parse enumType out of it
|
||||
@Override
|
||||
public String convertObject(ConverterContext<Enum> context) {
|
||||
public String convertObject(MapperContext<Enum, String> context) {
|
||||
Enum objectToConvert = context.getObjectToConvert();
|
||||
|
||||
return objectToConvert.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Enum> getConverterObjectType() {
|
||||
public Class<? extends Enum> getTypeOfObjectToConvert() {
|
||||
return Enum.class;
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
package org.keycloak.models.mongo.impl.types;
|
||||
|
||||
import com.mongodb.BasicDBList;
|
||||
import com.mongodb.BasicDBObject;
|
||||
import org.keycloak.models.mongo.api.types.Converter;
|
||||
import org.keycloak.models.mongo.api.types.ConverterContext;
|
||||
import org.keycloak.models.mongo.api.types.TypeConverter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class ListConverter<T extends List> implements Converter<T, BasicDBList> {
|
||||
|
||||
private final TypeConverter typeConverter;
|
||||
private final Class<T> listType;
|
||||
|
||||
public ListConverter(TypeConverter typeConverter, Class<T> listType) {
|
||||
this.typeConverter = typeConverter;
|
||||
this.listType = listType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicDBList convertObject(ConverterContext<T> context) {
|
||||
T appObjectsList = context.getObjectToConvert();
|
||||
|
||||
BasicDBList dbObjects = new BasicDBList();
|
||||
for (Object appObject : appObjectsList) {
|
||||
Object dbObject = typeConverter.convertApplicationObjectToDBObject(appObject, Object.class);
|
||||
|
||||
dbObjects.add(dbObject);
|
||||
}
|
||||
return dbObjects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends T> getConverterObjectType() {
|
||||
return listType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<BasicDBList> getExpectedReturnType() {
|
||||
return BasicDBList.class;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package org.keycloak.models.mongo.impl.types;
|
||||
|
||||
import com.mongodb.BasicDBList;
|
||||
import org.keycloak.models.mongo.api.types.Mapper;
|
||||
import org.keycloak.models.mongo.api.types.MapperContext;
|
||||
import org.keycloak.models.mongo.api.types.MapperRegistry;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class ListMapper<T extends List> implements Mapper<T, BasicDBList> {
|
||||
|
||||
private final MapperRegistry mapperRegistry;
|
||||
private final Class<T> listType;
|
||||
|
||||
public ListMapper(MapperRegistry mapperRegistry, Class<T> listType) {
|
||||
this.mapperRegistry = mapperRegistry;
|
||||
this.listType = listType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicDBList convertObject(MapperContext<T, BasicDBList> context) {
|
||||
T appObjectsList = context.getObjectToConvert();
|
||||
|
||||
BasicDBList dbObjects = new BasicDBList();
|
||||
for (Object appObject : appObjectsList) {
|
||||
Object dbObject = mapperRegistry.convertApplicationObjectToDBObject(appObject, Object.class);
|
||||
|
||||
dbObjects.add(dbObject);
|
||||
}
|
||||
return dbObjects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends T> getTypeOfObjectToConvert() {
|
||||
return listType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<BasicDBList> getExpectedReturnType() {
|
||||
return BasicDBList.class;
|
||||
}
|
||||
}
|
|
@ -4,25 +4,27 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import org.keycloak.models.mongo.api.types.Converter;
|
||||
import org.keycloak.models.mongo.api.types.ConverterContext;
|
||||
import org.keycloak.models.mongo.api.types.Mapper;
|
||||
import org.keycloak.models.mongo.api.types.MapperContext;
|
||||
|
||||
/**
|
||||
* For now, we support just convert from Map<String, String>
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class MapConverter<T extends Map> implements Converter<T, BasicDBObject> {
|
||||
public class MapMapper<T extends Map> implements Mapper<T, BasicDBObject> {
|
||||
|
||||
// Just some dummy way of encoding . character as it's not allowed by mongo in key fields
|
||||
static final String DOT_PLACEHOLDER = "###";
|
||||
|
||||
private final Class<T> mapType;
|
||||
|
||||
public MapConverter(Class<T> mapType) {
|
||||
public MapMapper(Class<T> mapType) {
|
||||
this.mapType = mapType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicDBObject convertObject(ConverterContext<T> context) {
|
||||
public BasicDBObject convertObject(MapperContext<T, BasicDBObject> context) {
|
||||
T objectToConvert = context.getObjectToConvert();
|
||||
|
||||
BasicDBObject dbObject = new BasicDBObject();
|
||||
|
@ -41,7 +43,7 @@ public class MapConverter<T extends Map> implements Converter<T, BasicDBObject>
|
|||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends T> getConverterObjectType() {
|
||||
public Class<? extends T> getTypeOfObjectToConvert() {
|
||||
return mapType;
|
||||
}
|
||||
|
|
@ -2,11 +2,11 @@ package org.keycloak.models.mongo.impl.types;
|
|||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import org.keycloak.models.mongo.api.MongoEntity;
|
||||
import org.keycloak.models.mongo.api.types.Converter;
|
||||
import org.keycloak.models.mongo.api.types.ConverterContext;
|
||||
import org.keycloak.models.mongo.api.types.TypeConverter;
|
||||
import org.keycloak.models.mongo.api.types.Mapper;
|
||||
import org.keycloak.models.mongo.api.types.MapperContext;
|
||||
import org.keycloak.models.mongo.api.types.MapperRegistry;
|
||||
import org.keycloak.models.mongo.impl.MongoStoreImpl;
|
||||
import org.keycloak.models.mongo.impl.ObjectInfo;
|
||||
import org.keycloak.models.mongo.impl.EntityInfo;
|
||||
import org.picketlink.common.properties.Property;
|
||||
|
||||
import java.util.Collection;
|
||||
|
@ -14,32 +14,32 @@ import java.util.Collection;
|
|||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class MongoEntityConverter<T extends MongoEntity> implements Converter<T, BasicDBObject> {
|
||||
public class MongoEntityMapper<T extends MongoEntity> implements Mapper<T, BasicDBObject> {
|
||||
|
||||
private final MongoStoreImpl mongoStoreImpl;
|
||||
private final TypeConverter typeConverter;
|
||||
private final Class<T> expectedNoSQLObjectType;
|
||||
private final MapperRegistry mapperRegistry;
|
||||
private final Class<T> expectedMongoEntityType;
|
||||
|
||||
public MongoEntityConverter(MongoStoreImpl mongoStoreImpl, TypeConverter typeConverter, Class<T> expectedNoSQLObjectType) {
|
||||
public MongoEntityMapper(MongoStoreImpl mongoStoreImpl, MapperRegistry mapperRegistry, Class<T> expectedMongoEntityType) {
|
||||
this.mongoStoreImpl = mongoStoreImpl;
|
||||
this.typeConverter = typeConverter;
|
||||
this.expectedNoSQLObjectType = expectedNoSQLObjectType;
|
||||
this.mapperRegistry = mapperRegistry;
|
||||
this.expectedMongoEntityType = expectedMongoEntityType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicDBObject convertObject(ConverterContext<T> context) {
|
||||
public BasicDBObject convertObject(MapperContext<T, BasicDBObject> context) {
|
||||
T applicationObject = context.getObjectToConvert();
|
||||
|
||||
ObjectInfo objectInfo = mongoStoreImpl.getObjectInfo(applicationObject.getClass());
|
||||
EntityInfo entityInfo = mongoStoreImpl.getEntityInfo(applicationObject.getClass());
|
||||
|
||||
// Create instance of BasicDBObject and add all declared properties to it (properties with null value probably should be skipped)
|
||||
BasicDBObject dbObject = new BasicDBObject();
|
||||
Collection<Property<Object>> props = objectInfo.getProperties();
|
||||
Collection<Property<Object>> props = entityInfo.getProperties();
|
||||
for (Property<Object> property : props) {
|
||||
String propName = property.getName();
|
||||
Object propValue = property.getValue(applicationObject);
|
||||
|
||||
Object dbValue = propValue == null ? null : typeConverter.convertApplicationObjectToDBObject(propValue, Object.class);
|
||||
Object dbValue = propValue == null ? null : mapperRegistry.convertApplicationObjectToDBObject(propValue, Object.class);
|
||||
dbObject.put(propName, dbValue);
|
||||
}
|
||||
|
||||
|
@ -47,8 +47,8 @@ public class MongoEntityConverter<T extends MongoEntity> implements Converter<T,
|
|||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends T> getConverterObjectType() {
|
||||
return expectedNoSQLObjectType;
|
||||
public Class<? extends T> getTypeOfObjectToConvert() {
|
||||
return expectedMongoEntityType;
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,29 +1,29 @@
|
|||
package org.keycloak.models.mongo.impl.types;
|
||||
|
||||
import org.keycloak.models.mongo.api.types.Converter;
|
||||
import org.keycloak.models.mongo.api.types.ConverterContext;
|
||||
import org.keycloak.models.mongo.api.types.Mapper;
|
||||
import org.keycloak.models.mongo.api.types.MapperContext;
|
||||
|
||||
/**
|
||||
* Just returns input
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class SimpleConverter<T> implements Converter<T, T> {
|
||||
public class SimpleMapper<T> implements Mapper<T, T> {
|
||||
|
||||
private final Class<T> expectedType;
|
||||
|
||||
public SimpleConverter(Class<T> expectedType) {
|
||||
public SimpleMapper(Class<T> expectedType) {
|
||||
this.expectedType = expectedType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T convertObject(ConverterContext<T> context) {
|
||||
public T convertObject(MapperContext<T, T> context) {
|
||||
T objectToConvert = context.getObjectToConvert();
|
||||
return objectToConvert;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends T> getConverterObjectType() {
|
||||
public Class<? extends T> getTypeOfObjectToConvert() {
|
||||
return expectedType;
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
package org.keycloak.models.mongo.impl.types;
|
||||
|
||||
import org.keycloak.models.mongo.api.types.Converter;
|
||||
import org.keycloak.models.mongo.api.types.ConverterContext;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class StringToEnumConverter implements Converter<String, Enum> {
|
||||
|
||||
@Override
|
||||
public Enum convertObject(ConverterContext<String> context) {
|
||||
String enumValue = context.getObjectToConvert();
|
||||
|
||||
Class<? extends Enum> clazz = (Class<? extends Enum>)context.getExpectedReturnType();
|
||||
return Enum.valueOf(clazz, enumValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends String> getConverterObjectType() {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Enum> getExpectedReturnType() {
|
||||
return Enum.class;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package org.keycloak.models.mongo.impl.types;
|
||||
|
||||
import org.keycloak.models.mongo.api.types.Mapper;
|
||||
import org.keycloak.models.mongo.api.types.MapperContext;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class StringToEnumMapper implements Mapper<String, Enum> {
|
||||
|
||||
@Override
|
||||
public Enum convertObject(MapperContext<String, Enum> context) {
|
||||
String enumValue = context.getObjectToConvert();
|
||||
|
||||
Class<? extends Enum> clazz = context.getExpectedReturnType();
|
||||
return Enum.valueOf(clazz, enumValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends String> getTypeOfObjectToConvert() {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Enum> getExpectedReturnType() {
|
||||
return Enum.class;
|
||||
}
|
||||
}
|
|
@ -9,11 +9,9 @@ import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
|
|||
*/
|
||||
public abstract class AbstractAdapter {
|
||||
|
||||
protected MongoStore mongoStore;
|
||||
protected MongoStoreInvocationContext invocationContext;
|
||||
|
||||
public AbstractAdapter(MongoStore mongoStore, MongoStoreInvocationContext invocationContext) {
|
||||
this.mongoStore = mongoStore;
|
||||
public AbstractAdapter(MongoStoreInvocationContext invocationContext) {
|
||||
this.invocationContext = invocationContext;
|
||||
}
|
||||
|
||||
|
@ -35,4 +33,8 @@ public abstract class AbstractAdapter {
|
|||
public int hashCode() {
|
||||
return getMongoEntity()!=null ? getMongoEntity().hashCode() : super.hashCode();
|
||||
}
|
||||
|
||||
protected MongoStore getMongoStore() {
|
||||
return invocationContext.getMongoStore();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import org.keycloak.models.ApplicationModel;
|
|||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.mongo.api.AbstractMongoIdentifiableEntity;
|
||||
import org.keycloak.models.mongo.api.MongoStore;
|
||||
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
|
||||
import org.keycloak.models.mongo.keycloak.entities.ApplicationEntity;
|
||||
import org.keycloak.models.mongo.keycloak.entities.RoleEntity;
|
||||
|
@ -26,30 +25,30 @@ public class ApplicationAdapter extends AbstractAdapter implements ApplicationMo
|
|||
private final ApplicationEntity application;
|
||||
private UserAdapter resourceUser;
|
||||
|
||||
public ApplicationAdapter(ApplicationEntity applicationEntity, MongoStore mongoStore, MongoStoreInvocationContext invContext) {
|
||||
this(applicationEntity, null, mongoStore, invContext);
|
||||
public ApplicationAdapter(ApplicationEntity applicationEntity, MongoStoreInvocationContext invContext) {
|
||||
this(applicationEntity, null, invContext);
|
||||
}
|
||||
|
||||
public ApplicationAdapter(ApplicationEntity applicationEntity, UserAdapter resourceUser, MongoStore mongoStore, MongoStoreInvocationContext invContext) {
|
||||
super(mongoStore, invContext);
|
||||
public ApplicationAdapter(ApplicationEntity applicationEntity, UserAdapter resourceUser, MongoStoreInvocationContext invContext) {
|
||||
super(invContext);
|
||||
this.application = applicationEntity;
|
||||
this.resourceUser = resourceUser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateApplication() {
|
||||
mongoStore.updateObject(application, invocationContext);
|
||||
getMongoStore().updateEntity(application, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserAdapter getApplicationUser() {
|
||||
// This is not thread-safe. Assumption is that ApplicationAdapter instance is per-client object
|
||||
if (resourceUser == null) {
|
||||
UserEntity userEntity = mongoStore.loadObject(UserEntity.class, application.getResourceUserId(), invocationContext);
|
||||
UserEntity userEntity = getMongoStore().loadEntity(UserEntity.class, application.getResourceUserId(), invocationContext);
|
||||
if (userEntity == null) {
|
||||
throw new IllegalStateException("User " + application.getResourceUserId() + " not found");
|
||||
}
|
||||
resourceUser = new UserAdapter(userEntity, mongoStore, invocationContext);
|
||||
resourceUser = new UserAdapter(userEntity, invocationContext);
|
||||
}
|
||||
|
||||
return resourceUser;
|
||||
|
@ -116,21 +115,21 @@ public class ApplicationAdapter extends AbstractAdapter implements ApplicationMo
|
|||
.and("name").is(name)
|
||||
.and("applicationId").is(getId())
|
||||
.get();
|
||||
RoleEntity role = mongoStore.loadSingleObject(RoleEntity.class, query, invocationContext);
|
||||
RoleEntity role = getMongoStore().loadSingleEntity(RoleEntity.class, query, invocationContext);
|
||||
if (role == null) {
|
||||
return null;
|
||||
} else {
|
||||
return new RoleAdapter(role, this, mongoStore, invocationContext);
|
||||
return new RoleAdapter(role, invocationContext);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoleModel getRoleById(String id) {
|
||||
RoleEntity role = mongoStore.loadObject(RoleEntity.class, id, invocationContext);
|
||||
RoleEntity role = getMongoStore().loadEntity(RoleEntity.class, id, invocationContext);
|
||||
if (role == null) {
|
||||
return null;
|
||||
} else {
|
||||
return new RoleAdapter(role, this, mongoStore, invocationContext);
|
||||
return new RoleAdapter(role, this, invocationContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,13 +144,13 @@ public class ApplicationAdapter extends AbstractAdapter implements ApplicationMo
|
|||
roleEntity.setName(name);
|
||||
roleEntity.setApplicationId(getId());
|
||||
|
||||
mongoStore.insertObject(roleEntity, invocationContext);
|
||||
return new RoleAdapter(roleEntity, this, mongoStore, invocationContext);
|
||||
getMongoStore().insertEntity(roleEntity, invocationContext);
|
||||
return new RoleAdapter(roleEntity, this, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeRoleById(String id) {
|
||||
return mongoStore.removeObject(RoleEntity.class ,id, invocationContext);
|
||||
return getMongoStore().removeEntity(RoleEntity.class, id, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -159,11 +158,11 @@ public class ApplicationAdapter extends AbstractAdapter implements ApplicationMo
|
|||
DBObject query = new QueryBuilder()
|
||||
.and("applicationId").is(getId())
|
||||
.get();
|
||||
List<RoleEntity> roles = mongoStore.loadObjects(RoleEntity.class, query, invocationContext);
|
||||
List<RoleEntity> roles = getMongoStore().loadEntities(RoleEntity.class, query, invocationContext);
|
||||
|
||||
Set<RoleModel> result = new HashSet<RoleModel>();
|
||||
for (RoleEntity role : roles) {
|
||||
result.add(new RoleAdapter(role, this, mongoStore, invocationContext));
|
||||
result.add(new RoleAdapter(role, this, invocationContext));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -172,11 +171,11 @@ public class ApplicationAdapter extends AbstractAdapter implements ApplicationMo
|
|||
@Override
|
||||
public Set<RoleModel> getApplicationRoleMappings(UserModel user) {
|
||||
Set<RoleModel> result = new HashSet<RoleModel>();
|
||||
List<RoleEntity> roles = MongoModelUtils.getAllRolesOfUser(user, mongoStore, invocationContext);
|
||||
List<RoleEntity> roles = MongoModelUtils.getAllRolesOfUser(user, invocationContext);
|
||||
|
||||
for (RoleEntity role : roles) {
|
||||
if (getId().equals(role.getApplicationId())) {
|
||||
result.add(new RoleAdapter(role, this, mongoStore, invocationContext));
|
||||
result.add(new RoleAdapter(role, this, invocationContext));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -185,17 +184,17 @@ public class ApplicationAdapter extends AbstractAdapter implements ApplicationMo
|
|||
@Override
|
||||
public void addScope(RoleModel role) {
|
||||
UserAdapter appUser = getApplicationUser();
|
||||
mongoStore.pushItemToList(appUser.getUser(), "scopeIds", role.getId(), true, invocationContext);
|
||||
getMongoStore().pushItemToList(appUser.getUser(), "scopeIds", role.getId(), true, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getApplicationScopeMappings(UserModel user) {
|
||||
Set<RoleModel> result = new HashSet<RoleModel>();
|
||||
List<RoleEntity> roles = MongoModelUtils.getAllScopesOfUser(user, mongoStore, invocationContext);
|
||||
List<RoleEntity> roles = MongoModelUtils.getAllScopesOfUser(user, invocationContext);
|
||||
|
||||
for (RoleEntity role : roles) {
|
||||
if (getId().equals(role.getApplicationId())) {
|
||||
result.add(new RoleAdapter(role, this, mongoStore, invocationContext));
|
||||
result.add(new RoleAdapter(role, this, invocationContext));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -213,7 +212,7 @@ public class ApplicationAdapter extends AbstractAdapter implements ApplicationMo
|
|||
addRole(name);
|
||||
}
|
||||
|
||||
mongoStore.pushItemToList(application, "defaultRoles", name, true, invocationContext);
|
||||
getMongoStore().pushItemToList(application, "defaultRoles", name, true, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -9,7 +9,6 @@ import org.keycloak.models.RealmModel;
|
|||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.mongo.api.MongoStore;
|
||||
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
|
||||
import org.keycloak.models.mongo.impl.context.SimpleMongoStoreInvocationContext;
|
||||
import org.keycloak.models.mongo.impl.context.TransactionMongoStoreInvocationContext;
|
||||
import org.keycloak.models.mongo.keycloak.entities.RealmEntity;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
|
@ -24,10 +23,8 @@ public class MongoKeycloakSession implements KeycloakSession {
|
|||
|
||||
private final MongoStoreInvocationContext invocationContext;
|
||||
private final MongoKeycloakTransaction transaction;
|
||||
private final MongoStore mongoStore;
|
||||
|
||||
public MongoKeycloakSession(MongoStore mongoStore) {
|
||||
this.mongoStore = mongoStore;
|
||||
// this.invocationContext = new SimpleMongoStoreInvocationContext(mongoStore);
|
||||
this.invocationContext = new TransactionMongoStoreInvocationContext(mongoStore);
|
||||
this.transaction = new MongoKeycloakTransaction(invocationContext);
|
||||
|
@ -58,25 +55,25 @@ public class MongoKeycloakSession implements KeycloakSession {
|
|||
newRealm.setId(id);
|
||||
newRealm.setName(name);
|
||||
|
||||
mongoStore.insertObject(newRealm, invocationContext);
|
||||
getMongoStore().insertEntity(newRealm, invocationContext);
|
||||
|
||||
return new RealmAdapter(newRealm, mongoStore, invocationContext);
|
||||
return new RealmAdapter(newRealm, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RealmModel getRealm(String id) {
|
||||
RealmEntity realmEntity = mongoStore.loadObject(RealmEntity.class, id, invocationContext);
|
||||
return realmEntity != null ? new RealmAdapter(realmEntity, mongoStore, invocationContext) : null;
|
||||
RealmEntity realmEntity = getMongoStore().loadEntity(RealmEntity.class, id, invocationContext);
|
||||
return realmEntity != null ? new RealmAdapter(realmEntity, invocationContext) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RealmModel> getRealms(UserModel admin) {
|
||||
DBObject query = new BasicDBObject();
|
||||
List<RealmEntity> realms = mongoStore.loadObjects(RealmEntity.class, query, invocationContext);
|
||||
List<RealmEntity> realms = getMongoStore().loadEntities(RealmEntity.class, query, invocationContext);
|
||||
|
||||
List<RealmModel> results = new ArrayList<RealmModel>();
|
||||
for (RealmEntity realmEntity : realms) {
|
||||
results.add(new RealmAdapter(realmEntity, mongoStore, invocationContext));
|
||||
results.add(new RealmAdapter(realmEntity, invocationContext));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
@ -86,14 +83,18 @@ public class MongoKeycloakSession implements KeycloakSession {
|
|||
DBObject query = new QueryBuilder()
|
||||
.and("name").is(name)
|
||||
.get();
|
||||
RealmEntity realm = mongoStore.loadSingleObject(RealmEntity.class, query, invocationContext);
|
||||
RealmEntity realm = getMongoStore().loadSingleEntity(RealmEntity.class, query, invocationContext);
|
||||
|
||||
if (realm == null) return null;
|
||||
return new RealmAdapter(realm, mongoStore, invocationContext);
|
||||
return new RealmAdapter(realm, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeRealm(String id) {
|
||||
return mongoStore.removeObject(RealmEntity.class, id, invocationContext);
|
||||
return getMongoStore().removeEntity(RealmEntity.class, id, invocationContext);
|
||||
}
|
||||
|
||||
protected MongoStore getMongoStore() {
|
||||
return invocationContext.getMongoStore();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ import org.keycloak.models.mongo.keycloak.entities.RequiredCredentialEntity;
|
|||
import org.keycloak.models.mongo.keycloak.entities.RoleEntity;
|
||||
import org.keycloak.models.mongo.keycloak.entities.SocialLinkEntity;
|
||||
import org.keycloak.models.mongo.keycloak.entities.UserEntity;
|
||||
import org.keycloak.models.mongo.utils.EmbeddedMongo;
|
||||
import org.keycloak.models.mongo.utils.MongoConfiguration;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
|
@ -40,20 +39,12 @@ public class MongoKeycloakSessionFactory implements KeycloakSessionFactory {
|
|||
OAuthClientEntity.class
|
||||
};
|
||||
|
||||
private final EmbeddedMongo embeddedMongo;
|
||||
private final MongoClient mongoClient;
|
||||
private final MongoStore mongoStore;
|
||||
|
||||
public MongoKeycloakSessionFactory(MongoConfiguration config) {
|
||||
logger.info(String.format("Configuring MongoStore with: " + config));
|
||||
|
||||
if (config.isStartEmbedded()) {
|
||||
embeddedMongo = new EmbeddedMongo();
|
||||
embeddedMongo.startEmbeddedMongo(config.getPort());
|
||||
} else {
|
||||
embeddedMongo = null;
|
||||
}
|
||||
|
||||
try {
|
||||
// TODO: authentication support
|
||||
mongoClient = new MongoClient(config.getHost(), config.getPort());
|
||||
|
@ -75,9 +66,5 @@ public class MongoKeycloakSessionFactory implements KeycloakSessionFactory {
|
|||
public void close() {
|
||||
logger.info("Closing MongoDB client");
|
||||
mongoClient.close();
|
||||
|
||||
if (embeddedMongo != null) {
|
||||
embeddedMongo.stopEmbeddedMongo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package org.keycloak.models.mongo.keycloak.adapters;
|
|||
import org.keycloak.models.OAuthClientModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.mongo.api.AbstractMongoIdentifiableEntity;
|
||||
import org.keycloak.models.mongo.api.MongoStore;
|
||||
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
|
||||
import org.keycloak.models.mongo.keycloak.entities.OAuthClientEntity;
|
||||
import org.keycloak.models.mongo.keycloak.entities.UserEntity;
|
||||
|
@ -16,14 +15,14 @@ public class OAuthClientAdapter extends AbstractAdapter implements OAuthClientMo
|
|||
private final OAuthClientEntity delegate;
|
||||
private UserAdapter oauthAgent;
|
||||
|
||||
public OAuthClientAdapter(OAuthClientEntity oauthClientEntity, UserAdapter oauthAgent, MongoStore mongoStore, MongoStoreInvocationContext invContext) {
|
||||
super(mongoStore, invContext);
|
||||
public OAuthClientAdapter(OAuthClientEntity oauthClientEntity, UserAdapter oauthAgent, MongoStoreInvocationContext invContext) {
|
||||
super(invContext);
|
||||
this.delegate = oauthClientEntity;
|
||||
this.oauthAgent = oauthAgent;
|
||||
}
|
||||
|
||||
public OAuthClientAdapter(OAuthClientEntity oauthClientEntity, MongoStore mongoStore, MongoStoreInvocationContext invContext) {
|
||||
this(oauthClientEntity, null, mongoStore, invContext);
|
||||
public OAuthClientAdapter(OAuthClientEntity oauthClientEntity, MongoStoreInvocationContext invContext) {
|
||||
this(oauthClientEntity, null, invContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -35,8 +34,8 @@ public class OAuthClientAdapter extends AbstractAdapter implements OAuthClientMo
|
|||
public UserModel getOAuthAgent() {
|
||||
// This is not thread-safe. Assumption is that OAuthClientAdapter instance is per-client object
|
||||
if (oauthAgent == null) {
|
||||
UserEntity user = mongoStore.loadObject(UserEntity.class, delegate.getOauthAgentId(), invocationContext);
|
||||
oauthAgent = user!=null ? new UserAdapter(user, mongoStore, invocationContext) : null;
|
||||
UserEntity user = getMongoStore().loadEntity(UserEntity.class, delegate.getOauthAgentId(), invocationContext);
|
||||
oauthAgent = user!=null ? new UserAdapter(user, invocationContext) : null;
|
||||
}
|
||||
return oauthAgent;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ import org.keycloak.models.SocialLinkModel;
|
|||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.mongo.api.AbstractMongoIdentifiableEntity;
|
||||
import org.keycloak.models.mongo.api.MongoStore;
|
||||
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
|
||||
import org.keycloak.models.mongo.keycloak.entities.ApplicationEntity;
|
||||
import org.keycloak.models.mongo.keycloak.entities.CredentialEntity;
|
||||
|
@ -54,8 +53,8 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
|
||||
private volatile transient PasswordPolicy passwordPolicy;
|
||||
|
||||
public RealmAdapter(RealmEntity realmEntity, MongoStore mongoStore, MongoStoreInvocationContext invocationContext) {
|
||||
super(mongoStore, invocationContext);
|
||||
public RealmAdapter(RealmEntity realmEntity, MongoStoreInvocationContext invocationContext) {
|
||||
super(invocationContext);
|
||||
this.realm = realmEntity;
|
||||
}
|
||||
|
||||
|
@ -280,12 +279,12 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
.and("loginName").is(name)
|
||||
.and("realmId").is(getId())
|
||||
.get();
|
||||
UserEntity user = mongoStore.loadSingleObject(UserEntity.class, query, invocationContext);
|
||||
UserEntity user = getMongoStore().loadSingleEntity(UserEntity.class, query, invocationContext);
|
||||
|
||||
if (user == null) {
|
||||
return null;
|
||||
} else {
|
||||
return new UserAdapter(user, mongoStore, invocationContext);
|
||||
return new UserAdapter(user, invocationContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -295,12 +294,12 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
.and("email").is(email)
|
||||
.and("realmId").is(getId())
|
||||
.get();
|
||||
UserEntity user = mongoStore.loadSingleObject(UserEntity.class, query, invocationContext);
|
||||
UserEntity user = getMongoStore().loadSingleEntity(UserEntity.class, query, invocationContext);
|
||||
|
||||
if (user == null) {
|
||||
return null;
|
||||
} else {
|
||||
return new UserAdapter(user, mongoStore, invocationContext);
|
||||
return new UserAdapter(user, invocationContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -332,8 +331,8 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
userEntity.setEnabled(true);
|
||||
userEntity.setRealmId(getId());
|
||||
|
||||
mongoStore.insertObject(userEntity, invocationContext);
|
||||
return new UserAdapter(userEntity, mongoStore, invocationContext);
|
||||
getMongoStore().insertEntity(userEntity, invocationContext);
|
||||
return new UserAdapter(userEntity, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -342,7 +341,7 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
.and("loginName").is(name)
|
||||
.and("realmId").is(getId())
|
||||
.get();
|
||||
return mongoStore.removeObjects(UserEntity.class, query, invocationContext);
|
||||
return getMongoStore().removeEntities(UserEntity.class, query, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -351,11 +350,11 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
.and("name").is(name)
|
||||
.and("realmId").is(getId())
|
||||
.get();
|
||||
RoleEntity role = mongoStore.loadSingleObject(RoleEntity.class, query, invocationContext);
|
||||
RoleEntity role = getMongoStore().loadSingleEntity(RoleEntity.class, query, invocationContext);
|
||||
if (role == null) {
|
||||
return null;
|
||||
} else {
|
||||
return new RoleAdapter(role, this, mongoStore, invocationContext);
|
||||
return new RoleAdapter(role, this, invocationContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -372,13 +371,13 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
roleEntity.setName(name);
|
||||
roleEntity.setRealmId(getId());
|
||||
|
||||
mongoStore.insertObject(roleEntity, invocationContext);
|
||||
return new RoleAdapter(roleEntity, this, mongoStore, invocationContext);
|
||||
getMongoStore().insertEntity(roleEntity, invocationContext);
|
||||
return new RoleAdapter(roleEntity, this, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeRoleById(String id) {
|
||||
return mongoStore.removeObject(RoleEntity.class ,id, invocationContext);
|
||||
return getMongoStore().removeEntity(RoleEntity.class, id, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -386,13 +385,13 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
DBObject query = new QueryBuilder()
|
||||
.and("realmId").is(getId())
|
||||
.get();
|
||||
List<RoleEntity> roles = mongoStore.loadObjects(RoleEntity.class, query, invocationContext);
|
||||
List<RoleEntity> roles = getMongoStore().loadEntities(RoleEntity.class, query, invocationContext);
|
||||
|
||||
Set<RoleModel> result = new HashSet<RoleModel>();
|
||||
|
||||
if (roles == null) return result;
|
||||
for (RoleEntity role : roles) {
|
||||
result.add(new RoleAdapter(role, this, mongoStore, invocationContext));
|
||||
result.add(new RoleAdapter(role, this, invocationContext));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -400,11 +399,11 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
|
||||
@Override
|
||||
public RoleModel getRoleById(String id) {
|
||||
RoleEntity role = mongoStore.loadObject(RoleEntity.class, id, invocationContext);
|
||||
RoleEntity role = getMongoStore().loadEntity(RoleEntity.class, id, invocationContext);
|
||||
if (role == null) {
|
||||
return null;
|
||||
} else {
|
||||
return new RoleAdapter(role, this, mongoStore, invocationContext);
|
||||
return new RoleAdapter(role, this, invocationContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -420,7 +419,7 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
addRole(name);
|
||||
}
|
||||
|
||||
mongoStore.pushItemToList(realm, "defaultRoles", name, true, invocationContext);
|
||||
getMongoStore().pushItemToList(realm, "defaultRoles", name, true, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -441,14 +440,14 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
|
||||
@Override
|
||||
public ApplicationModel getApplicationById(String id) {
|
||||
ApplicationEntity appData = mongoStore.loadObject(ApplicationEntity.class, id, invocationContext);
|
||||
ApplicationEntity appData = getMongoStore().loadEntity(ApplicationEntity.class, id, invocationContext);
|
||||
|
||||
// Check if application belongs to this realm
|
||||
if (appData == null || !getId().equals(appData.getRealmId())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ApplicationAdapter(appData, mongoStore, invocationContext);
|
||||
return new ApplicationAdapter(appData, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -457,8 +456,8 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
.and("realmId").is(getId())
|
||||
.and("name").is(name)
|
||||
.get();
|
||||
ApplicationEntity appEntity = mongoStore.loadSingleObject(ApplicationEntity.class, query, invocationContext);
|
||||
return appEntity==null ? null : new ApplicationAdapter(appEntity, mongoStore, invocationContext);
|
||||
ApplicationEntity appEntity = getMongoStore().loadSingleEntity(ApplicationEntity.class, query, invocationContext);
|
||||
return appEntity==null ? null : new ApplicationAdapter(appEntity, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -475,11 +474,11 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
DBObject query = new QueryBuilder()
|
||||
.and("realmId").is(getId())
|
||||
.get();
|
||||
List<ApplicationEntity> appDatas = mongoStore.loadObjects(ApplicationEntity.class, query, invocationContext);
|
||||
List<ApplicationEntity> appDatas = getMongoStore().loadEntities(ApplicationEntity.class, query, invocationContext);
|
||||
|
||||
List<ApplicationModel> result = new ArrayList<ApplicationModel>();
|
||||
for (ApplicationEntity appData : appDatas) {
|
||||
result.add(new ApplicationAdapter(appData, mongoStore, invocationContext));
|
||||
result.add(new ApplicationAdapter(appData, invocationContext));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -493,14 +492,14 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
appData.setRealmId(getId());
|
||||
appData.setEnabled(true);
|
||||
appData.setResourceUserId(resourceUser.getUser().getId());
|
||||
mongoStore.insertObject(appData, invocationContext);
|
||||
getMongoStore().insertEntity(appData, invocationContext);
|
||||
|
||||
return new ApplicationAdapter(appData, resourceUser, mongoStore, invocationContext);
|
||||
return new ApplicationAdapter(appData, resourceUser, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeApplication(String id) {
|
||||
return mongoStore.removeObject(ApplicationEntity.class, id, invocationContext);
|
||||
return getMongoStore().removeEntity(ApplicationEntity.class, id, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -517,20 +516,20 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
@Override
|
||||
public void grantRole(UserModel user, RoleModel role) {
|
||||
UserEntity userEntity = ((UserAdapter)user).getUser();
|
||||
mongoStore.pushItemToList(userEntity, "roleIds", role.getId(), true, invocationContext);
|
||||
getMongoStore().pushItemToList(userEntity, "roleIds", role.getId(), true, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRoleMappings(UserModel user) {
|
||||
Set<RoleModel> result = new HashSet<RoleModel>();
|
||||
List<RoleEntity> roles = MongoModelUtils.getAllRolesOfUser(user, mongoStore, invocationContext);
|
||||
List<RoleEntity> roles = MongoModelUtils.getAllRolesOfUser(user, invocationContext);
|
||||
|
||||
for (RoleEntity role : roles) {
|
||||
if (getId().equals(role.getRealmId())) {
|
||||
result.add(new RoleAdapter(role, this, mongoStore, invocationContext));
|
||||
result.add(new RoleAdapter(role, this, invocationContext));
|
||||
} else {
|
||||
// Likely applicationRole, but we don't have this application yet
|
||||
result.add(new RoleAdapter(role, mongoStore, invocationContext));
|
||||
result.add(new RoleAdapter(role, invocationContext));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -555,20 +554,20 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
@Override
|
||||
public void deleteRoleMapping(UserModel user, RoleModel role) {
|
||||
UserEntity userEntity = ((UserAdapter)user).getUser();
|
||||
mongoStore.pullItemFromList(userEntity, "roleIds", role.getId(), invocationContext);
|
||||
getMongoStore().pullItemFromList(userEntity, "roleIds", role.getId(), invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getScopeMappings(UserModel user) {
|
||||
Set<RoleModel> result = new HashSet<RoleModel>();
|
||||
List<RoleEntity> roles = MongoModelUtils.getAllScopesOfUser(user, mongoStore, invocationContext);
|
||||
List<RoleEntity> roles = MongoModelUtils.getAllScopesOfUser(user, invocationContext);
|
||||
|
||||
for (RoleEntity role : roles) {
|
||||
if (getId().equals(role.getRealmId())) {
|
||||
result.add(new RoleAdapter(role, this, mongoStore, invocationContext));
|
||||
result.add(new RoleAdapter(role, this, invocationContext));
|
||||
} else {
|
||||
// Likely applicationRole, but we don't have this application yet
|
||||
result.add(new RoleAdapter(role, mongoStore, invocationContext));
|
||||
result.add(new RoleAdapter(role, invocationContext));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -593,13 +592,13 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
@Override
|
||||
public void addScopeMapping(UserModel agent, RoleModel role) {
|
||||
UserEntity userEntity = ((UserAdapter)agent).getUser();
|
||||
mongoStore.pushItemToList(userEntity, "scopeIds", role.getId(), true, invocationContext);
|
||||
getMongoStore().pushItemToList(userEntity, "scopeIds", role.getId(), true, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteScopeMapping(UserModel user, RoleModel role) {
|
||||
UserEntity userEntity = ((UserAdapter)user).getUser();
|
||||
mongoStore.pullItemFromList(userEntity, "scopeIds", role.getId(), invocationContext);
|
||||
getMongoStore().pullItemFromList(userEntity, "scopeIds", role.getId(), invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -610,14 +609,14 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
oauthClient.setOauthAgentId(oauthAgent.getUser().getId());
|
||||
oauthClient.setRealmId(getId());
|
||||
oauthClient.setName(name);
|
||||
mongoStore.insertObject(oauthClient, invocationContext);
|
||||
getMongoStore().insertEntity(oauthClient, invocationContext);
|
||||
|
||||
return new OAuthClientAdapter(oauthClient, oauthAgent, mongoStore, invocationContext);
|
||||
return new OAuthClientAdapter(oauthClient, oauthAgent, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeOAuthClient(String id) {
|
||||
return mongoStore.removeObject(OAuthClientEntity.class, id, invocationContext);
|
||||
return getMongoStore().removeEntity(OAuthClientEntity.class, id, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -628,15 +627,15 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
.and("realmId").is(getId())
|
||||
.and("oauthAgentId").is(user.getUser().getId())
|
||||
.get();
|
||||
OAuthClientEntity oauthClient = mongoStore.loadSingleObject(OAuthClientEntity.class, query, invocationContext);
|
||||
return oauthClient == null ? null : new OAuthClientAdapter(oauthClient, user, mongoStore, invocationContext);
|
||||
OAuthClientEntity oauthClient = getMongoStore().loadSingleEntity(OAuthClientEntity.class, query, invocationContext);
|
||||
return oauthClient == null ? null : new OAuthClientAdapter(oauthClient, user, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuthClientModel getOAuthClientById(String id) {
|
||||
OAuthClientEntity clientEntity = mongoStore.loadObject(OAuthClientEntity.class, id, invocationContext);
|
||||
OAuthClientEntity clientEntity = getMongoStore().loadEntity(OAuthClientEntity.class, id, invocationContext);
|
||||
if (clientEntity == null) return null;
|
||||
return new OAuthClientAdapter(clientEntity, mongoStore, invocationContext);
|
||||
return new OAuthClientAdapter(clientEntity, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -644,10 +643,10 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
DBObject query = new QueryBuilder()
|
||||
.and("realmId").is(getId())
|
||||
.get();
|
||||
List<OAuthClientEntity> results = mongoStore.loadObjects(OAuthClientEntity.class, query, invocationContext);
|
||||
List<OAuthClientEntity> results = getMongoStore().loadEntities(OAuthClientEntity.class, query, invocationContext);
|
||||
List<OAuthClientModel> list = new ArrayList<OAuthClientModel>();
|
||||
for (OAuthClientEntity data : results) {
|
||||
list.add(new OAuthClientAdapter(data, mongoStore, invocationContext));
|
||||
list.add(new OAuthClientAdapter(data, invocationContext));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
@ -795,7 +794,7 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
}
|
||||
credentialEntity.setDevice(cred.getDevice());
|
||||
|
||||
mongoStore.updateObject(userEntity, invocationContext);
|
||||
getMongoStore().updateEntity(userEntity, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -805,8 +804,8 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
.and("socialLinks.socialUsername").is(socialLink.getSocialUsername())
|
||||
.and("realmId").is(getId())
|
||||
.get();
|
||||
UserEntity userEntity = mongoStore.loadSingleObject(UserEntity.class, query, invocationContext);
|
||||
return userEntity==null ? null : new UserAdapter(userEntity, mongoStore, invocationContext);
|
||||
UserEntity userEntity = getMongoStore().loadSingleEntity(UserEntity.class, query, invocationContext);
|
||||
return userEntity==null ? null : new UserAdapter(userEntity, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -833,7 +832,7 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
socialLinkEntity.setSocialProvider(socialLink.getSocialProvider());
|
||||
socialLinkEntity.setSocialUsername(socialLink.getSocialUsername());
|
||||
|
||||
mongoStore.pushItemToList(userEntity, "socialLinks", socialLinkEntity, true, invocationContext);
|
||||
getMongoStore().pushItemToList(userEntity, "socialLinks", socialLinkEntity, true, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -843,11 +842,11 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
socialLinkEntity.setSocialUsername(socialLink.getSocialUsername());
|
||||
|
||||
UserEntity userEntity = ((UserAdapter)user).getUser();
|
||||
mongoStore.pullItemFromList(userEntity, "socialLinks", socialLinkEntity, invocationContext);
|
||||
getMongoStore().pullItemFromList(userEntity, "socialLinks", socialLinkEntity, invocationContext);
|
||||
}
|
||||
|
||||
protected void updateRealm() {
|
||||
mongoStore.updateObject(realm, invocationContext);
|
||||
getMongoStore().updateEntity(realm, invocationContext);
|
||||
}
|
||||
|
||||
protected RequiredCredentialModel initRequiredCredentialModel(String type) {
|
||||
|
@ -863,7 +862,7 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
DBObject query = new QueryBuilder()
|
||||
.and("realmId").is(getId())
|
||||
.get();
|
||||
List<UserEntity> users = mongoStore.loadObjects(UserEntity.class, query, invocationContext);
|
||||
List<UserEntity> users = getMongoStore().loadEntities(UserEntity.class, query, invocationContext);
|
||||
return convertUserEntities(users);
|
||||
}
|
||||
|
||||
|
@ -903,7 +902,7 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
).get()
|
||||
);
|
||||
|
||||
List<UserEntity> users = mongoStore.loadObjects(UserEntity.class, builder.get(), invocationContext);
|
||||
List<UserEntity> users = getMongoStore().loadEntities(UserEntity.class, builder.get(), invocationContext);
|
||||
return convertUserEntities(users);
|
||||
}
|
||||
|
||||
|
@ -925,14 +924,14 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
queryBuilder.and(UserModel.EMAIL).regex(Pattern.compile("(?i:" + entry.getValue() + "$)"));
|
||||
}
|
||||
}
|
||||
List<UserEntity> users = mongoStore.loadObjects(UserEntity.class, queryBuilder.get(), invocationContext);
|
||||
List<UserEntity> users = getMongoStore().loadEntities(UserEntity.class, queryBuilder.get(), invocationContext);
|
||||
return convertUserEntities(users);
|
||||
}
|
||||
|
||||
protected List<UserModel> convertUserEntities(List<UserEntity> userEntities) {
|
||||
List<UserModel> userModels = new ArrayList<UserModel>();
|
||||
for (UserEntity user : userEntities) {
|
||||
userModels.add(new UserAdapter(user, mongoStore, invocationContext));
|
||||
userModels.add(new UserAdapter(user, invocationContext));
|
||||
}
|
||||
return userModels;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ import com.mongodb.QueryBuilder;
|
|||
import org.keycloak.models.RoleContainerModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.mongo.api.AbstractMongoIdentifiableEntity;
|
||||
import org.keycloak.models.mongo.api.MongoStore;
|
||||
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
|
||||
import org.keycloak.models.mongo.keycloak.entities.ApplicationEntity;
|
||||
import org.keycloak.models.mongo.keycloak.entities.RealmEntity;
|
||||
|
@ -28,15 +27,14 @@ public class RoleAdapter extends AbstractAdapter implements RoleModel {
|
|||
private final RoleEntity role;
|
||||
private RoleContainerModel roleContainer;
|
||||
|
||||
public RoleAdapter(RoleEntity roleEntity, MongoStore mongoStore, MongoStoreInvocationContext invContext) {
|
||||
this(roleEntity, null, mongoStore, invContext);
|
||||
public RoleAdapter(RoleEntity roleEntity, MongoStoreInvocationContext invContext) {
|
||||
this(roleEntity, null, invContext);
|
||||
}
|
||||
|
||||
public RoleAdapter(RoleEntity roleEntity, RoleContainerModel roleContainer, MongoStore mongoStore, MongoStoreInvocationContext invContext) {
|
||||
super(mongoStore, invContext);
|
||||
public RoleAdapter(RoleEntity roleEntity, RoleContainerModel roleContainer, MongoStoreInvocationContext invContext) {
|
||||
super(invContext);
|
||||
this.role = roleEntity;
|
||||
this.roleContainer = roleContainer;
|
||||
this.mongoStore = mongoStore;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -72,17 +70,17 @@ public class RoleAdapter extends AbstractAdapter implements RoleModel {
|
|||
}
|
||||
|
||||
protected void updateRole() {
|
||||
mongoStore.updateObject(role, invocationContext);
|
||||
getMongoStore().updateEntity(role, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCompositeRole(RoleModel childRole) {
|
||||
mongoStore.pushItemToList(role, "compositeRoleIds", childRole.getId(), true, invocationContext);
|
||||
getMongoStore().pushItemToList(role, "compositeRoleIds", childRole.getId(), true, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCompositeRole(RoleModel childRole) {
|
||||
mongoStore.pullItemFromList(role, "compositeRoleIds", childRole.getId(), invocationContext);
|
||||
getMongoStore().pullItemFromList(role, "compositeRoleIds", childRole.getId(), invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -94,11 +92,11 @@ public class RoleAdapter extends AbstractAdapter implements RoleModel {
|
|||
DBObject query = new QueryBuilder()
|
||||
.and("_id").in(MongoModelUtils.convertStringsToObjectIds(role.getCompositeRoleIds()))
|
||||
.get();
|
||||
List<RoleEntity> childRoles = mongoStore.loadObjects(RoleEntity.class, query, invocationContext);
|
||||
List<RoleEntity> childRoles = getMongoStore().loadEntities(RoleEntity.class, query, invocationContext);
|
||||
|
||||
Set<RoleModel> set = new HashSet<RoleModel>();
|
||||
for (RoleEntity childRole : childRoles) {
|
||||
set.add(new RoleAdapter(childRole, mongoStore, invocationContext));
|
||||
set.add(new RoleAdapter(childRole, invocationContext));
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
@ -108,17 +106,17 @@ public class RoleAdapter extends AbstractAdapter implements RoleModel {
|
|||
if (roleContainer == null) {
|
||||
// Compute it
|
||||
if (role.getRealmId() != null) {
|
||||
RealmEntity realm = mongoStore.loadObject(RealmEntity.class, role.getRealmId(), invocationContext);
|
||||
RealmEntity realm = getMongoStore().loadEntity(RealmEntity.class, role.getRealmId(), invocationContext);
|
||||
if (realm == null) {
|
||||
throw new IllegalStateException("Realm with id: " + role.getRealmId() + " doesn't exists");
|
||||
}
|
||||
roleContainer = new RealmAdapter(realm, mongoStore, invocationContext);
|
||||
roleContainer = new RealmAdapter(realm, invocationContext);
|
||||
} else if (role.getApplicationId() != null) {
|
||||
ApplicationEntity appEntity = mongoStore.loadObject(ApplicationEntity.class, role.getApplicationId(), invocationContext);
|
||||
ApplicationEntity appEntity = getMongoStore().loadEntity(ApplicationEntity.class, role.getApplicationId(), invocationContext);
|
||||
if (appEntity == null) {
|
||||
throw new IllegalStateException("Application with id: " + role.getApplicationId() + " doesn't exists");
|
||||
}
|
||||
roleContainer = new ApplicationAdapter(appEntity, mongoStore, invocationContext);
|
||||
roleContainer = new ApplicationAdapter(appEntity, invocationContext);
|
||||
} else {
|
||||
throw new IllegalStateException("Both realmId and applicationId are null for role: " + this);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package org.keycloak.models.mongo.keycloak.adapters;
|
|||
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.mongo.api.AbstractMongoIdentifiableEntity;
|
||||
import org.keycloak.models.mongo.api.MongoStore;
|
||||
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
|
||||
import org.keycloak.models.mongo.keycloak.entities.UserEntity;
|
||||
|
||||
|
@ -23,8 +22,8 @@ public class UserAdapter extends AbstractAdapter implements UserModel {
|
|||
|
||||
private final UserEntity user;
|
||||
|
||||
public UserAdapter(UserEntity userEntity, MongoStore mongoStore, MongoStoreInvocationContext invContext) {
|
||||
super(mongoStore, invContext);
|
||||
public UserAdapter(UserEntity userEntity, MongoStoreInvocationContext invContext) {
|
||||
super(invContext);
|
||||
this.user = userEntity;
|
||||
}
|
||||
|
||||
|
@ -139,12 +138,12 @@ public class UserAdapter extends AbstractAdapter implements UserModel {
|
|||
|
||||
@Override
|
||||
public void addWebOrigin(String webOrigin) {
|
||||
mongoStore.pushItemToList(user, "webOrigins", webOrigin, true, invocationContext);
|
||||
getMongoStore().pushItemToList(user, "webOrigins", webOrigin, true, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeWebOrigin(String webOrigin) {
|
||||
mongoStore.pullItemFromList(user, "webOrigins", webOrigin, invocationContext);
|
||||
getMongoStore().pullItemFromList(user, "webOrigins", webOrigin, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -166,12 +165,12 @@ public class UserAdapter extends AbstractAdapter implements UserModel {
|
|||
|
||||
@Override
|
||||
public void addRedirectUri(String redirectUri) {
|
||||
mongoStore.pushItemToList(user, "redirectUris", redirectUri, true, invocationContext);
|
||||
getMongoStore().pushItemToList(user, "redirectUris", redirectUri, true, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRedirectUri(String redirectUri) {
|
||||
mongoStore.pullItemFromList(user, "redirectUris", redirectUri, invocationContext);
|
||||
getMongoStore().pullItemFromList(user, "redirectUris", redirectUri, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -185,12 +184,12 @@ public class UserAdapter extends AbstractAdapter implements UserModel {
|
|||
|
||||
@Override
|
||||
public void addRequiredAction(RequiredAction action) {
|
||||
mongoStore.pushItemToList(user, "requiredActions", action, true, invocationContext);
|
||||
getMongoStore().pushItemToList(user, "requiredActions", action, true, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRequiredAction(RequiredAction action) {
|
||||
mongoStore.pullItemFromList(user, "requiredActions", action, invocationContext);
|
||||
getMongoStore().pullItemFromList(user, "requiredActions", action, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -205,7 +204,7 @@ public class UserAdapter extends AbstractAdapter implements UserModel {
|
|||
}
|
||||
|
||||
protected void updateUser() {
|
||||
mongoStore.updateObject(user, invocationContext);
|
||||
getMongoStore().updateEntity(user, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -9,7 +9,6 @@ import org.keycloak.models.mongo.api.AbstractMongoIdentifiableEntity;
|
|||
import org.keycloak.models.mongo.api.MongoCollection;
|
||||
import org.keycloak.models.mongo.api.MongoEntity;
|
||||
import org.keycloak.models.mongo.api.MongoField;
|
||||
import org.keycloak.models.mongo.api.MongoStore;
|
||||
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
|
||||
|
||||
/**
|
||||
|
@ -103,14 +102,14 @@ public class ApplicationEntity extends AbstractMongoIdentifiableEntity implement
|
|||
}
|
||||
|
||||
@Override
|
||||
public void afterRemove(MongoStore mongoStore, MongoStoreInvocationContext invContext) {
|
||||
public void afterRemove(MongoStoreInvocationContext context) {
|
||||
// Remove resourceUser of this application
|
||||
mongoStore.removeObject(UserEntity.class, resourceUserId, invContext);
|
||||
context.getMongoStore().removeEntity(UserEntity.class, resourceUserId, context);
|
||||
|
||||
// Remove all roles, which belongs to this application
|
||||
DBObject query = new QueryBuilder()
|
||||
.and("applicationId").is(getId())
|
||||
.get();
|
||||
mongoStore.removeObjects(RoleEntity.class, query, invContext);
|
||||
context.getMongoStore().removeEntities(RoleEntity.class, query, context);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import org.keycloak.models.mongo.api.AbstractMongoIdentifiableEntity;
|
|||
import org.keycloak.models.mongo.api.MongoCollection;
|
||||
import org.keycloak.models.mongo.api.MongoEntity;
|
||||
import org.keycloak.models.mongo.api.MongoField;
|
||||
import org.keycloak.models.mongo.api.MongoStore;
|
||||
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
|
||||
|
||||
/**
|
||||
|
@ -46,8 +45,8 @@ public class OAuthClientEntity extends AbstractMongoIdentifiableEntity implement
|
|||
}
|
||||
|
||||
@Override
|
||||
public void afterRemove(MongoStore mongoStore, MongoStoreInvocationContext invContext) {
|
||||
public void afterRemove(MongoStoreInvocationContext context) {
|
||||
// Remove user of this oauthClient
|
||||
mongoStore.removeObject(UserEntity.class, oauthAgentId, invContext);
|
||||
context.getMongoStore().removeEntity(UserEntity.class, oauthAgentId, context);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import org.keycloak.models.mongo.api.AbstractMongoIdentifiableEntity;
|
|||
import org.keycloak.models.mongo.api.MongoCollection;
|
||||
import org.keycloak.models.mongo.api.MongoEntity;
|
||||
import org.keycloak.models.mongo.api.MongoField;
|
||||
import org.keycloak.models.mongo.api.MongoStore;
|
||||
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -249,18 +248,18 @@ public class RealmEntity extends AbstractMongoIdentifiableEntity implements Mong
|
|||
}
|
||||
|
||||
@Override
|
||||
public void afterRemove(MongoStore mongoStore, MongoStoreInvocationContext invContext) {
|
||||
public void afterRemove(MongoStoreInvocationContext context) {
|
||||
DBObject query = new QueryBuilder()
|
||||
.and("realmId").is(getId())
|
||||
.get();
|
||||
|
||||
// Remove all users of this realm
|
||||
mongoStore.removeObjects(UserEntity.class, query, invContext);
|
||||
context.getMongoStore().removeEntities(UserEntity.class, query, context);
|
||||
|
||||
// Remove all roles of this realm
|
||||
mongoStore.removeObjects(RoleEntity.class, query, invContext);
|
||||
context.getMongoStore().removeEntities(RoleEntity.class, query, context);
|
||||
|
||||
// Remove all applications of this realm
|
||||
mongoStore.removeObjects(ApplicationEntity.class, query, invContext);
|
||||
context.getMongoStore().removeEntities(ApplicationEntity.class, query, context);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,13 +74,15 @@ public class RoleEntity extends AbstractMongoIdentifiableEntity implements Mongo
|
|||
}
|
||||
|
||||
@Override
|
||||
public void afterRemove(MongoStore mongoStore, MongoStoreInvocationContext invContext) {
|
||||
public void afterRemove(MongoStoreInvocationContext invContext) {
|
||||
MongoStore mongoStore = invContext.getMongoStore();
|
||||
|
||||
// Remove this role from all users, which has it
|
||||
DBObject query = new QueryBuilder()
|
||||
.and("roleIds").is(getId())
|
||||
.get();
|
||||
|
||||
List<UserEntity> users = mongoStore.loadObjects(UserEntity.class, query, invContext);
|
||||
List<UserEntity> users = mongoStore.loadEntities(UserEntity.class, query, invContext);
|
||||
for (UserEntity user : users) {
|
||||
logger.info("Removing role " + getName() + " from user " + user.getLoginName());
|
||||
mongoStore.pullItemFromList(user, "roleIds", getId(), invContext);
|
||||
|
@ -91,7 +93,7 @@ public class RoleEntity extends AbstractMongoIdentifiableEntity implements Mongo
|
|||
.and("scopeIds").is(getId())
|
||||
.get();
|
||||
|
||||
users = mongoStore.loadObjects(UserEntity.class, query, invContext);
|
||||
users = mongoStore.loadEntities(UserEntity.class, query, invContext);
|
||||
for (UserEntity user : users) {
|
||||
logger.info("Removing scope " + getName() + " from user " + user.getLoginName());
|
||||
mongoStore.pullItemFromList(user, "scopeIds", getId(), invContext);
|
||||
|
@ -99,7 +101,7 @@ public class RoleEntity extends AbstractMongoIdentifiableEntity implements Mongo
|
|||
|
||||
// Remove defaultRoles from realm
|
||||
if (realmId != null) {
|
||||
RealmEntity realmEntity = mongoStore.loadObject(RealmEntity.class, realmId, invContext);
|
||||
RealmEntity realmEntity = mongoStore.loadEntity(RealmEntity.class, realmId, invContext);
|
||||
|
||||
// Realm might be already removed at this point
|
||||
if (realmEntity != null) {
|
||||
|
@ -109,7 +111,7 @@ public class RoleEntity extends AbstractMongoIdentifiableEntity implements Mongo
|
|||
|
||||
// Remove defaultRoles from application
|
||||
if (applicationId != null) {
|
||||
ApplicationEntity appEntity = mongoStore.loadObject(ApplicationEntity.class, applicationId, invContext);
|
||||
ApplicationEntity appEntity = mongoStore.loadEntity(ApplicationEntity.class, applicationId, invContext);
|
||||
|
||||
// Application might be already removed at this point
|
||||
if (appEntity != null) {
|
||||
|
@ -121,7 +123,7 @@ public class RoleEntity extends AbstractMongoIdentifiableEntity implements Mongo
|
|||
query = new QueryBuilder()
|
||||
.and("compositeRoleIds").is(getId())
|
||||
.get();
|
||||
List<RoleEntity> parentRoles = mongoStore.loadObjects(RoleEntity.class, query, invContext);
|
||||
List<RoleEntity> parentRoles = mongoStore.loadEntities(RoleEntity.class, query, invContext);
|
||||
for (RoleEntity role : parentRoles) {
|
||||
mongoStore.pullItemFromList(role, "compositeRoleIds", getId(), invContext);
|
||||
}
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
package org.keycloak.models.mongo.utils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import de.flapdoodle.embed.mongo.MongodExecutable;
|
||||
import de.flapdoodle.embed.mongo.MongodProcess;
|
||||
import de.flapdoodle.embed.mongo.MongodStarter;
|
||||
import de.flapdoodle.embed.mongo.config.IMongodConfig;
|
||||
import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
|
||||
import de.flapdoodle.embed.mongo.config.Net;
|
||||
import de.flapdoodle.embed.mongo.distribution.Version;
|
||||
import de.flapdoodle.embed.process.runtime.Network;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class EmbeddedMongo {
|
||||
|
||||
protected static final Logger logger = Logger.getLogger(EmbeddedMongo.class);
|
||||
|
||||
private MongodExecutable mongodExe;
|
||||
private MongodProcess mongod;
|
||||
|
||||
public void startEmbeddedMongo(int port) {
|
||||
logger.info("Going to start embedded Mongo on port=" + port);
|
||||
|
||||
try {
|
||||
IMongodConfig mongodConfig = new MongodConfigBuilder()
|
||||
.version(Version.Main.PRODUCTION)
|
||||
.net(new Net(port, Network.localhostIsIPv6()))
|
||||
.build();
|
||||
mongodExe = MongodStarter.getDefaultInstance().prepare(mongodConfig);
|
||||
mongod = mongodExe.start();
|
||||
} catch (IOException e) {
|
||||
logger.warn("Couldn't start Embedded Mongo on port " + port + ". Maybe it's already started? Cause: " + e.getClass() + " " + e.getMessage());
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void stopEmbeddedMongo() {
|
||||
if (mongodExe != null) {
|
||||
if (mongod != null) {
|
||||
logger.info("Going to stop embedded MongoDB.");
|
||||
mongod.stop();
|
||||
}
|
||||
mongodExe.stop();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,14 +12,12 @@ public class MongoConfiguration {
|
|||
private final String dbName;
|
||||
|
||||
private final boolean clearCollectionsOnStartup;
|
||||
private final boolean startEmbedded;
|
||||
|
||||
public MongoConfiguration(String host, int port, String dbName, boolean clearCollectionsOnStartup, boolean startEmbedded) {
|
||||
public MongoConfiguration(String host, int port, String dbName, boolean clearCollectionsOnStartup) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.dbName = dbName;
|
||||
this.clearCollectionsOnStartup = clearCollectionsOnStartup;
|
||||
this.startEmbedded = startEmbedded;
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
|
@ -38,13 +36,9 @@ public class MongoConfiguration {
|
|||
return clearCollectionsOnStartup;
|
||||
}
|
||||
|
||||
public boolean isStartEmbedded() {
|
||||
return startEmbedded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("MongoConfiguration: host: %s, port: %d, dbName: %s, clearCollectionsOnStartup: %b, startEmbedded: %b",
|
||||
host, port, dbName, clearCollectionsOnStartup, startEmbedded);
|
||||
return String.format("MongoConfiguration: host: %s, port: %d, dbName: %s, clearCollectionsOnStartup: %b",
|
||||
host, port, dbName, clearCollectionsOnStartup);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import com.mongodb.DBObject;
|
|||
import com.mongodb.QueryBuilder;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.mongo.api.MongoStore;
|
||||
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
|
||||
import org.keycloak.models.mongo.keycloak.adapters.UserAdapter;
|
||||
import org.keycloak.models.mongo.keycloak.entities.RoleEntity;
|
||||
|
@ -29,7 +28,7 @@ public class MongoModelUtils {
|
|||
}
|
||||
|
||||
// Get everything including both application and realm roles
|
||||
public static List<RoleEntity> getAllRolesOfUser(UserModel user, MongoStore mongoStore, MongoStoreInvocationContext invContext) {
|
||||
public static List<RoleEntity> getAllRolesOfUser(UserModel user, MongoStoreInvocationContext invContext) {
|
||||
UserEntity userEntity = ((UserAdapter)user).getUser();
|
||||
List<String> roleIds = userEntity.getRoleIds();
|
||||
|
||||
|
@ -40,11 +39,11 @@ public class MongoModelUtils {
|
|||
DBObject query = new QueryBuilder()
|
||||
.and("_id").in(convertStringsToObjectIds(roleIds))
|
||||
.get();
|
||||
return mongoStore.loadObjects(RoleEntity.class, query, invContext);
|
||||
return invContext.getMongoStore().loadEntities(RoleEntity.class, query, invContext);
|
||||
}
|
||||
|
||||
// Get everything including both application and realm scopes
|
||||
public static List<RoleEntity> getAllScopesOfUser(UserModel user, MongoStore mongoStore, MongoStoreInvocationContext invContext) {
|
||||
public static List<RoleEntity> getAllScopesOfUser(UserModel user, MongoStoreInvocationContext invContext) {
|
||||
UserEntity userEntity = ((UserAdapter)user).getUser();
|
||||
List<String> scopeIds = userEntity.getScopeIds();
|
||||
|
||||
|
@ -55,6 +54,6 @@ public class MongoModelUtils {
|
|||
DBObject query = new QueryBuilder()
|
||||
.and("_id").in(convertStringsToObjectIds(scopeIds))
|
||||
.get();
|
||||
return mongoStore.loadObjects(RoleEntity.class, query, invContext);
|
||||
return invContext.getMongoStore().loadEntities(RoleEntity.class, query, invContext);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,39 +8,39 @@ public class SystemPropertiesConfigurationProvider {
|
|||
private static final String MONGO_HOST = "keycloak.mongo.host";
|
||||
private static final String MONGO_PORT = "keycloak.mongo.port";
|
||||
private static final String MONGO_DB_NAME = "keycloak.mongo.db";
|
||||
private static final String MONGO_CLEAR_COLLECTIONS_ON_STARTUP = "keycloak.mongo.clearCollectionsOnStartup";
|
||||
private static final String MONGO_START_EMBEDDED = "keycloak.mongo.startEmbedded";
|
||||
private static final String MONGO_CLEAR_ON_STARTUP = "keycloak.mongo.clearOnStartup";
|
||||
|
||||
// Property names from Liveoak . Those are used as fallback in case that original value is not available
|
||||
private static final String MONGO_HOST_2 = "mongo.host";
|
||||
private static final String MONGO_PORT_2 = "mongo.port";
|
||||
private static final String MONGO_DB_NAME_2 = "mongo.db";
|
||||
private static final String MONGO_CLEAR_ON_STARTUP_2 = "mongo.clearCollectionsOnStartup";
|
||||
|
||||
// Port where MongoDB instance is normally started on linux. This port should be used if we're not starting embedded instance
|
||||
private static final int MONGO_DEFAULT_PORT = 27017;
|
||||
|
||||
// Port where embedded MongoDB instance will be started. Same port will be used by KeycloakApplication then
|
||||
public static final int MONGO_DEFAULT_PORT_EMBEDDED = 27018;
|
||||
private static final String MONGO_DEFAULT_PORT = "27017";
|
||||
|
||||
public static String getMongoHost() {
|
||||
return System.getProperty(MONGO_HOST, "localhost");
|
||||
return getSystemPropertyWithFallback(MONGO_HOST, MONGO_HOST_2, "localhost");
|
||||
}
|
||||
|
||||
public static int getMongoPort() {
|
||||
String portProp = System.getProperty(MONGO_PORT);
|
||||
if (portProp != null) {
|
||||
String portProp = getSystemPropertyWithFallback(MONGO_PORT, MONGO_PORT_2, MONGO_DEFAULT_PORT);
|
||||
return Integer.parseInt(portProp);
|
||||
} else {
|
||||
// Default port is 27017 in case of non-embedded, and 27018 in case of embedded
|
||||
return isStartEmbedded() ? MONGO_DEFAULT_PORT_EMBEDDED : MONGO_DEFAULT_PORT;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getMongoDbName() {
|
||||
return System.getProperty(MONGO_DB_NAME, "keycloak");
|
||||
return getSystemPropertyWithFallback(MONGO_DB_NAME, MONGO_DB_NAME_2, "keycloak");
|
||||
}
|
||||
|
||||
public static boolean isClearCollectionsOnStartup() {
|
||||
return Boolean.parseBoolean(System.getProperty(MONGO_CLEAR_COLLECTIONS_ON_STARTUP, "true"));
|
||||
String property = getSystemPropertyWithFallback(MONGO_CLEAR_ON_STARTUP, MONGO_CLEAR_ON_STARTUP_2, "false");
|
||||
return "true".equalsIgnoreCase(property);
|
||||
}
|
||||
|
||||
public static boolean isStartEmbedded() {
|
||||
return Boolean.parseBoolean(System.getProperty(MONGO_START_EMBEDDED, "false"));
|
||||
// Check if property propName1 (like "keycloak.mongo.host" is available and if not, then fallback to property "mongo.host" )
|
||||
private static String getSystemPropertyWithFallback(String propName1, String propName2, String defaultValue) {
|
||||
String propValue1 = System.getProperty(propName1);
|
||||
return propValue1!=null ? propValue1 : System.getProperty(propName2, defaultValue);
|
||||
}
|
||||
|
||||
// Create configuration based on system properties
|
||||
|
@ -49,8 +49,7 @@ public class SystemPropertiesConfigurationProvider {
|
|||
getMongoHost(),
|
||||
getMongoPort(),
|
||||
getMongoDbName(),
|
||||
isClearCollectionsOnStartup(),
|
||||
isStartEmbedded()
|
||||
isClearCollectionsOnStartup()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@ import org.keycloak.models.mongo.api.MongoEntity;
|
|||
import org.keycloak.models.mongo.api.MongoStore;
|
||||
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
|
||||
import org.keycloak.models.mongo.impl.MongoStoreImpl;
|
||||
import org.keycloak.models.mongo.impl.context.SimpleMongoStoreInvocationContext;
|
||||
import org.keycloak.models.mongo.impl.context.TransactionMongoStoreInvocationContext;
|
||||
import org.keycloak.models.mongo.utils.SystemPropertiesConfigurationProvider;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -37,7 +37,7 @@ public class MongoDBModelTest {
|
|||
public void before() throws Exception {
|
||||
try {
|
||||
// TODO: authentication support
|
||||
mongoClient = new MongoClient("localhost", 27017);
|
||||
mongoClient = new MongoClient("localhost", SystemPropertiesConfigurationProvider.getMongoPort());
|
||||
|
||||
DB db = mongoClient.getDB("keycloakTest");
|
||||
mongoStore = new MongoStoreImpl(db, true, MANAGED_DATA_TYPES);
|
||||
|
@ -62,7 +62,7 @@ public class MongoDBModelTest {
|
|||
john.setAge(25);
|
||||
john.setGender(Person.Gender.MALE);
|
||||
|
||||
mongoStore.insertObject(john, context);
|
||||
mongoStore.insertEntity(john, context);
|
||||
|
||||
// Add another user
|
||||
Person mary = new Person();
|
||||
|
@ -83,12 +83,12 @@ public class MongoDBModelTest {
|
|||
mary.setGender(Person.Gender.FEMALE);
|
||||
mary.setGenders(asList(Person.Gender.FEMALE));
|
||||
|
||||
mongoStore.insertObject(mary, context);
|
||||
mongoStore.insertEntity(mary, context);
|
||||
|
||||
Assert.assertEquals(2, mongoStore.loadObjects(Person.class, new QueryBuilder().get(), context).size());
|
||||
Assert.assertEquals(2, mongoStore.loadEntities(Person.class, new QueryBuilder().get(), context).size());
|
||||
|
||||
DBObject query = new QueryBuilder().and("addresses.flatNumbers").is("flat1").get();
|
||||
List<Person> persons = mongoStore.loadObjects(Person.class, query, context);
|
||||
List<Person> persons = mongoStore.loadEntities(Person.class, query, context);
|
||||
Assert.assertEquals(1, persons.size());
|
||||
mary = persons.get(0);
|
||||
Assert.assertEquals(mary.getFirstName(), "mary");
|
||||
|
@ -105,7 +105,7 @@ public class MongoDBModelTest {
|
|||
addr3.setStreet("Broadway");
|
||||
mongoStore.pushItemToList(mary, "addresses", addr3, true, context);
|
||||
|
||||
mary = mongoStore.loadObject(Person.class, mary.getId(), context);
|
||||
mary = mongoStore.loadEntity(Person.class, mary.getId(), context);
|
||||
Assert.assertEquals(3, mary.getKids().size());
|
||||
Assert.assertTrue(mary.getKids().contains("Pauline"));
|
||||
Assert.assertFalse(mary.getKids().contains("Paul"));
|
||||
|
@ -121,16 +121,16 @@ public class MongoDBModelTest {
|
|||
mary.addAttribute("attr1", "value1");
|
||||
mary.addAttribute("attr2", "value2");
|
||||
mary.addAttribute("attr.some3", "value3");
|
||||
mongoStore.updateObject(mary, context);
|
||||
mongoStore.updateEntity(mary, context);
|
||||
|
||||
mary = mongoStore.loadObject(Person.class, mary.getId(), context);
|
||||
mary = mongoStore.loadEntity(Person.class, mary.getId(), context);
|
||||
Assert.assertEquals(3, mary.getAttributes().size());
|
||||
|
||||
mary.removeAttribute("attr2");
|
||||
mary.removeAttribute("nonExisting");
|
||||
mongoStore.updateObject(mary, context);
|
||||
mongoStore.updateEntity(mary, context);
|
||||
|
||||
mary = mongoStore.loadObject(Person.class, mary.getId(), context);
|
||||
mary = mongoStore.loadEntity(Person.class, mary.getId(), context);
|
||||
Assert.assertEquals(2, mary.getAttributes().size());
|
||||
Assert.assertEquals("value1", mary.getAttributes().get("attr1"));
|
||||
Assert.assertEquals("value3", mary.getAttributes().get("attr.some3"));
|
||||
|
|
|
@ -38,5 +38,6 @@
|
|||
<!-- <module>picketlink</module> -->
|
||||
<module>jpa</module>
|
||||
<module>mongo</module>
|
||||
<module>tests</module>
|
||||
</modules>
|
||||
</project>
|
||||
|
|
69
model/tests/pom.xml
Normal file
69
model/tests/pom.xml
Normal file
|
@ -0,0 +1,69 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.0-alpha-2-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-model-tests</artifactId>
|
||||
<name>Keycloak Model Tests</name>
|
||||
<description/>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-services</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-core-asl</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-mapper-asl</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>package-tests-jar</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>test-jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<skipTests>true</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,55 @@
|
|||
package org.keycloak.model.test;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.jboss.resteasy.logging.Logger;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.resources.KeycloakApplication;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class AbstractModelTest {
|
||||
|
||||
private final Logger log = Logger.getLogger(getClass());
|
||||
|
||||
protected KeycloakSessionFactory factory;
|
||||
protected KeycloakSession identitySession;
|
||||
protected RealmManager realmManager;
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
factory = KeycloakApplication.createSessionFactory();
|
||||
identitySession = factory.createSession();
|
||||
identitySession.getTransaction().begin();
|
||||
realmManager = new RealmManager(identitySession);
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() throws Exception {
|
||||
identitySession.getTransaction().commit();
|
||||
identitySession.close();
|
||||
factory.close();
|
||||
}
|
||||
|
||||
public static RealmRepresentation loadJson(String path) throws IOException {
|
||||
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
int c;
|
||||
while ((c = is.read()) != -1) {
|
||||
os.write(c);
|
||||
}
|
||||
byte[] bytes = os.toByteArray();
|
||||
System.out.println(new String(bytes));
|
||||
|
||||
return JsonSerialization.readValue(bytes, RealmRepresentation.class);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package org.keycloak.test;
|
||||
package org.keycloak.model.test;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.FixMethodOrder;
|
||||
|
@ -23,36 +23,21 @@ import java.util.Arrays;
|
|||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
public class AdapterTest extends AbstractKeycloakTest {
|
||||
public class AdapterTest extends AbstractModelTest {
|
||||
private RealmModel realmModel;
|
||||
|
||||
public AdapterTest(String providerId) {
|
||||
super(providerId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void installTest() throws Exception {
|
||||
new ApplianceBootstrap().bootstrap(identitySession);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMe() {
|
||||
String hello = "Bill Burke";
|
||||
StringTokenizer tokenizer = new StringTokenizer(hello, " ");
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
System.out.println("token: " + tokenizer.nextToken());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void test1CreateRealm() throws Exception {
|
||||
realmModel = realmManager.createRealm("JUGGLER");
|
|
@ -1,4 +1,4 @@
|
|||
package org.keycloak.test;
|
||||
package org.keycloak.model.test;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
|
@ -16,15 +16,11 @@ import java.util.List;
|
|||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class ApplicationModelTest extends AbstractKeycloakTest {
|
||||
public class ApplicationModelTest extends AbstractModelTest {
|
||||
private ApplicationModel application;
|
||||
private RealmModel realm;
|
||||
private ApplicationManager appManager;
|
||||
|
||||
public ApplicationModelTest(String providerId) {
|
||||
super(providerId);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
super.before();
|
|
@ -1,4 +1,4 @@
|
|||
package org.keycloak.services.managers;
|
||||
package org.keycloak.model.test;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
|
@ -9,14 +9,14 @@ import org.keycloak.models.UserModel;
|
|||
import org.keycloak.models.UserModel.RequiredAction;
|
||||
import org.keycloak.models.utils.TimeBasedOTP;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.services.managers.AuthenticationManager;
|
||||
import org.keycloak.services.managers.AuthenticationManager.AuthenticationStatus;
|
||||
import org.keycloak.test.AbstractKeycloakTest;
|
||||
|
||||
import javax.ws.rs.core.MultivaluedHashMap;
|
||||
import javax.ws.rs.core.MultivaluedMap;
|
||||
import java.util.UUID;
|
||||
|
||||
public class AuthenticationManagerTest extends AbstractKeycloakTest {
|
||||
public class AuthenticationManagerTest extends AbstractModelTest {
|
||||
|
||||
private AuthenticationManager am;
|
||||
private MultivaluedMap<String, String> formData;
|
||||
|
@ -24,9 +24,6 @@ public class AuthenticationManagerTest extends AbstractKeycloakTest {
|
|||
private RealmModel realm;
|
||||
private UserModel user;
|
||||
|
||||
public AuthenticationManagerTest(String providerId) {
|
||||
super(providerId);
|
||||
}
|
||||
@Test
|
||||
public void authForm() {
|
||||
AuthenticationStatus status = am.authenticateForm(realm, user, formData);
|
|
@ -1,4 +1,4 @@
|
|||
package org.keycloak.test;
|
||||
package org.keycloak.model.test;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
@ -16,17 +16,13 @@ import org.keycloak.services.managers.RealmManager;
|
|||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class CompositeRolesModelTest extends AbstractKeycloakTest {
|
||||
|
||||
public CompositeRolesModelTest(String providerId) {
|
||||
super(providerId);
|
||||
}
|
||||
public class CompositeRolesModelTest extends AbstractModelTest {
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
super.before();
|
||||
RealmManager manager = realmManager;
|
||||
RealmRepresentation rep = AbstractKeycloakServerTest.loadJson("testcomposites.json");
|
||||
RealmRepresentation rep = AbstractModelTest.loadJson("testcomposites.json");
|
||||
RealmModel realm = manager.createRealm("Test", rep.getRealm());
|
||||
manager.importRealm(rep, realm);
|
||||
}
|
||||
|
@ -34,13 +30,42 @@ public class CompositeRolesModelTest extends AbstractKeycloakTest {
|
|||
@Test
|
||||
public void testAppComposites() {
|
||||
Set<RoleModel> requestedRoles = getRequestedRoles("APP_COMPOSITE_APPLICATION", "APP_COMPOSITE_USER");
|
||||
|
||||
Assert.assertEquals(2, requestedRoles.size());
|
||||
assertContains("APP_ROLE_APPLICATION", "APP_ROLE_1", requestedRoles);
|
||||
assertContains("realm", "REALM_ROLE_1", requestedRoles);
|
||||
}
|
||||
|
||||
RoleModel expectedRole1 = getRole("APP_ROLE_APPLICATION", "APP_ROLE_1");
|
||||
RoleModel expectedRole2 = getRole("realm", "REALM_ROLE_1");
|
||||
@Test
|
||||
public void testRealmAppComposites() {
|
||||
Set<RoleModel> requestedRoles = getRequestedRoles("APP_COMPOSITE_APPLICATION", "REALM_APP_COMPOSITE_USER");
|
||||
|
||||
assertContains(requestedRoles, expectedRole1);
|
||||
assertContains(requestedRoles, expectedRole2);
|
||||
Assert.assertEquals(1, requestedRoles.size());
|
||||
assertContains("APP_ROLE_APPLICATION", "APP_ROLE_1", requestedRoles);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRealmOnlyWithUserCompositeAppComposite() throws Exception {
|
||||
Set<RoleModel> requestedRoles = getRequestedRoles("REALM_COMPOSITE_1_APPLICATION", "REALM_COMPOSITE_1_USER");
|
||||
|
||||
Assert.assertEquals(1, requestedRoles.size());
|
||||
assertContains("realm", "REALM_COMPOSITE_1", requestedRoles);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRealmOnlyWithUserCompositeAppRole() throws Exception {
|
||||
Set<RoleModel> requestedRoles = getRequestedRoles("REALM_ROLE_1_APPLICATION", "REALM_COMPOSITE_1_USER");
|
||||
|
||||
Assert.assertEquals(1, requestedRoles.size());
|
||||
assertContains("realm", "REALM_ROLE_1", requestedRoles);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRealmOnlyWithUserRoleAppComposite() throws Exception {
|
||||
Set<RoleModel> requestedRoles = getRequestedRoles("REALM_COMPOSITE_1_APPLICATION", "REALM_ROLE_1_USER");
|
||||
|
||||
Assert.assertEquals(1, requestedRoles.size());
|
||||
assertContains("realm", "REALM_ROLE_1", requestedRoles);
|
||||
}
|
||||
|
||||
// TODO: more tests...
|
||||
|
@ -92,7 +117,9 @@ public class CompositeRolesModelTest extends AbstractKeycloakTest {
|
|||
}
|
||||
}
|
||||
|
||||
private void assertContains(Set<RoleModel> requestedRoles, RoleModel expectedRole) {
|
||||
private void assertContains(String appName, String roleName, Set<RoleModel> requestedRoles) {
|
||||
RoleModel expectedRole = getRole(appName, roleName);
|
||||
|
||||
Assert.assertTrue(requestedRoles.contains(expectedRole));
|
||||
|
||||
// Check if requestedRole has correct role container
|
|
@ -1,4 +1,4 @@
|
|||
package org.keycloak.test;
|
||||
package org.keycloak.model.test;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.FixMethodOrder;
|
||||
|
@ -23,16 +23,12 @@ import java.util.Set;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
public class ImportTest extends AbstractKeycloakTest {
|
||||
|
||||
public ImportTest(String providerId) {
|
||||
super(providerId);
|
||||
}
|
||||
public class ImportTest extends AbstractModelTest {
|
||||
|
||||
@Test
|
||||
public void install() throws Exception {
|
||||
RealmManager manager = realmManager;
|
||||
RealmRepresentation rep = AbstractKeycloakServerTest.loadJson("testrealm.json");
|
||||
RealmRepresentation rep = AbstractModelTest.loadJson("testrealm.json");
|
||||
RealmModel realm = manager.createRealm("demo", rep.getRealm());
|
||||
manager.importRealm(rep, realm);
|
||||
|
||||
|
@ -148,7 +144,7 @@ public class ImportTest extends AbstractKeycloakTest {
|
|||
@Test
|
||||
public void install2() throws Exception {
|
||||
RealmManager manager = realmManager;
|
||||
RealmRepresentation rep = AbstractKeycloakServerTest.loadJson("testrealm-demo.json");
|
||||
RealmRepresentation rep = AbstractModelTest.loadJson("testrealm-demo.json");
|
||||
RealmModel realm = manager.createRealm("demo", rep.getRealm());
|
||||
manager.importRealm(rep, realm);
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.keycloak.test;
|
||||
package org.keycloak.model.test;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
@ -12,11 +12,7 @@ import java.util.HashMap;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class ModelTest extends AbstractKeycloakTest {
|
||||
|
||||
public ModelTest(String providerId) {
|
||||
super(providerId);
|
||||
}
|
||||
public class ModelTest extends AbstractModelTest {
|
||||
|
||||
@Test
|
||||
public void importExportRealm() {
|
|
@ -1,4 +1,4 @@
|
|||
package org.keycloak.test;
|
||||
package org.keycloak.model.test;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
@ -14,11 +14,7 @@ import java.util.List;
|
|||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class UserModelTest extends AbstractKeycloakTest {
|
||||
|
||||
public UserModelTest(String providerId) {
|
||||
super(providerId);
|
||||
}
|
||||
public class UserModelTest extends AbstractModelTest {
|
||||
|
||||
@Test
|
||||
public void persistUser() {
|
12
pom.xml
12
pom.xml
|
@ -313,11 +313,6 @@
|
|||
<artifactId>mongo-java-driver</artifactId>
|
||||
<version>2.11.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.flapdoodle.embed</groupId>
|
||||
<artifactId>de.flapdoodle.embed.mongo</artifactId>
|
||||
<version>1.40</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.jmeter</groupId>
|
||||
<artifactId>ApacheJMeter_java</artifactId>
|
||||
|
@ -395,7 +390,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<!-- <version>2.5</version> -->
|
||||
<version>2.16</version>
|
||||
<configuration>
|
||||
<forkMode>once</forkMode>
|
||||
<argLine>-Xms512m -Xmx512m</argLine>
|
||||
|
@ -479,6 +474,11 @@
|
|||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>1.2.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.github.joelittlejohn.embedmongo</groupId>
|
||||
<artifactId>embedmongo-maven-plugin</artifactId>
|
||||
<version>0.1.10</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
|
||||
|
|
|
@ -56,41 +56,6 @@
|
|||
<artifactId>keycloak-jaxrs-oauth-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</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-picketlink</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
-->
|
||||
|
||||
<!-- TODO: remove -->
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-model-mongo</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongo-java-driver</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.picketlink</groupId>
|
||||
<artifactId>picketlink-common</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-social-core</artifactId>
|
||||
|
@ -141,21 +106,6 @@
|
|||
<artifactId>resteasy-multipart-provider</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-undertow</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.undertow</groupId>
|
||||
<artifactId>undertow-servlet</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.undertow</groupId>
|
||||
<artifactId>undertow-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-core-asl</artifactId>
|
||||
|
@ -185,21 +135,6 @@
|
|||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate.javax.persistence</groupId>
|
||||
<artifactId>hibernate-jpa-2.0-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-entitymanager</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.icegreen</groupId>
|
||||
<artifactId>greenmail</artifactId>
|
||||
|
|
|
@ -8,7 +8,7 @@ import org.keycloak.services.managers.ApplianceBootstrap;
|
|||
import org.keycloak.services.managers.SocialRequestManager;
|
||||
import org.keycloak.services.managers.TokenManager;
|
||||
import org.keycloak.services.resources.admin.AdminService;
|
||||
import org.keycloak.services.utils.ModelProviderUtils;
|
||||
import org.keycloak.models.utils.ModelProviderUtils;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.ws.rs.core.Application;
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
package org.keycloak.test;
|
||||
|
||||
import io.undertow.servlet.Servlets;
|
||||
import io.undertow.servlet.api.DeploymentInfo;
|
||||
import io.undertow.servlet.api.FilterInfo;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||
import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer;
|
||||
import org.jboss.resteasy.spi.ResteasyDeployment;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.keycloak.SkeletonKeyContextResolver;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.services.filters.KeycloakSessionServletFilter;
|
||||
import org.keycloak.services.resources.KeycloakApplication;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.ws.rs.client.Client;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class AbstractKeycloakServerTest {
|
||||
public static UndertowJaxrsServer server;
|
||||
public static ResteasyDeployment deployment;
|
||||
public static Client client;
|
||||
public static KeycloakApplication application;
|
||||
|
||||
@BeforeClass
|
||||
public static void undertowSetup() throws Exception {
|
||||
deployment = new ResteasyDeployment();
|
||||
deployment.setApplicationClass(KeycloakApplication.class.getName());
|
||||
server = new UndertowJaxrsServer().start();
|
||||
DeploymentInfo di = server.undertowDeployment(deployment);
|
||||
di.setClassLoader(AbstractKeycloakServerTest.class.getClassLoader());
|
||||
di.setContextPath("/");
|
||||
di.setDeploymentName("Keycloak");
|
||||
|
||||
FilterInfo filter = Servlets.filter("SessionFilter", KeycloakSessionServletFilter.class);
|
||||
di.addFilter(filter);
|
||||
di.addFilterUrlMapping("SessionFilter", "/*", DispatcherType.REQUEST);
|
||||
server.deploy(di);
|
||||
application = (KeycloakApplication) deployment.getApplication();
|
||||
client = new ResteasyClientBuilder().connectionPoolSize(10).build();
|
||||
client.register(SkeletonKeyContextResolver.class);
|
||||
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void undertowShutdown() throws Exception {
|
||||
server.stop();
|
||||
}
|
||||
|
||||
public static RealmRepresentation loadJson(String path) throws IOException {
|
||||
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
int c;
|
||||
while ((c = is.read()) != -1) {
|
||||
os.write(c);
|
||||
}
|
||||
byte[] bytes = os.toByteArray();
|
||||
System.out.println(new String(bytes));
|
||||
|
||||
return JsonSerialization.readValue(bytes, RealmRepresentation.class);
|
||||
}
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
package org.keycloak.test;
|
||||
|
||||
import org.jboss.resteasy.logging.Logger;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.models.ModelProvider;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.resources.KeycloakApplication;
|
||||
import org.keycloak.services.utils.ModelProviderUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public abstract class AbstractKeycloakTest {
|
||||
|
||||
private static final Logger log = Logger.getLogger(AbstractKeycloakTest.class);
|
||||
|
||||
protected KeycloakSessionFactory factory;
|
||||
protected KeycloakSession identitySession;
|
||||
protected RealmManager realmManager;
|
||||
|
||||
@Parameterized.Parameters
|
||||
public static Iterable<Object[]> parameters() {
|
||||
Iterable<ModelProvider> modelProviders;
|
||||
|
||||
// We will run tests with all registered models if -Dkeycloak.model=all . Otherwise just with configured provider
|
||||
String configuredProvider = System.getProperty(ModelProviderUtils.MODEL_PROVIDER);
|
||||
if ("all".equalsIgnoreCase(configuredProvider)) {
|
||||
modelProviders = ModelProviderUtils.getRegisteredProviders();
|
||||
} else {
|
||||
ModelProvider provider = ModelProviderUtils.getConfiguredModelProvider();
|
||||
modelProviders = Arrays.asList(provider);
|
||||
}
|
||||
|
||||
log.debug("Will use model providers: " + modelProviders);
|
||||
|
||||
List<Object[]> params = new ArrayList<Object[]>();
|
||||
|
||||
for (ModelProvider provider : modelProviders) {
|
||||
params.add(new Object[] { provider.getId() });
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
|
||||
public AbstractKeycloakTest(String providerId) {
|
||||
System.setProperty(ModelProviderUtils.MODEL_PROVIDER, providerId);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
factory = KeycloakApplication.createSessionFactory();
|
||||
identitySession = factory.createSession();
|
||||
identitySession.getTransaction().begin();
|
||||
realmManager = new RealmManager(identitySession);
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() throws Exception {
|
||||
identitySession.getTransaction().commit();
|
||||
identitySession.close();
|
||||
factory.close();
|
||||
}
|
||||
|
||||
}
|
|
@ -8,6 +8,13 @@ The testsuite uses Sellenium. By default it uses the HtmlUnit WebDriver, but can
|
|||
|
||||
To run the tests with Firefox add `-Dbrowser=firefox` or for Chrome add `-Dbrowser=chrome`
|
||||
|
||||
Mongo
|
||||
-----
|
||||
|
||||
The testsuite is executed with JPA model implementation with data saved in H2 database by default. To run testsuite with Mongo model, just add property `-Dkeycloak.model=mongo` when executing it.
|
||||
|
||||
Note that this will automatically run embedded Mongo database on localhost/27018 and it will stop it after whole testsuite is finished.
|
||||
So you don't need to have Mongo installed on your laptop to run mongo execution tests.
|
||||
|
||||
Test utils
|
||||
==========
|
||||
|
@ -41,6 +48,16 @@ For example to use the example themes run the server with:
|
|||
|
||||
**NOTE:** If `keycloak.theme.dir` is specified the default themes (base, rcue and keycloak) are loaded from the classpath
|
||||
|
||||
### Run server with Mongo model
|
||||
|
||||
To start a Keycloak server with identity model data persisted in Mongo database instead of default JPA/H2 you can run:
|
||||
|
||||
mvn exec:java -Pkeycloak-server -Dkeycloak.model=mongo
|
||||
|
||||
By default it's using database `keycloak` on localhost/27017 and it uses already existing data from this DB (no cleanup of existing data during bootstrap). Assumption is that you already have DB running on localhost/27017 . Use system properties to configure things differently:
|
||||
|
||||
mvn exec:java -Pkeycloak-server -Dkeycloak.model=mongo -Dkeycloak.mongo.host=localhost -Dkeycloak.mongo.port=27017 -Dkeycloak.mongo.db=keycloak -Dkeycloak.mongo.clearCollectionsOnStartup=false
|
||||
|
||||
TOTP codes
|
||||
----------
|
||||
|
||||
|
|
|
@ -350,11 +350,72 @@
|
|||
|
||||
<properties>
|
||||
<keycloak.mongo.host>localhost</keycloak.mongo.host>
|
||||
<keycloak.mongo.port>27017</keycloak.mongo.port>
|
||||
<keycloak.mongo.port>27018</keycloak.mongo.port>
|
||||
<keycloak.mongo.db>keycloak</keycloak.mongo.db>
|
||||
<keycloak.mongo.clearCollectionsOnStartup>true</keycloak.mongo.clearCollectionsOnStartup>
|
||||
<keycloak.mongo.clearOnStartup>true</keycloak.mongo.clearOnStartup>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
<!-- 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.mongo.host>${keycloak.mongo.host}</keycloak.mongo.host>
|
||||
<keycloak.mongo.port>${keycloak.mongo.port}</keycloak.mongo.port>
|
||||
<keycloak.mongo.db>${keycloak.mongo.db}</keycloak.mongo.db>
|
||||
<keycloak.mongo.clearOnStartup>${keycloak.mongo.clearOnStartup}</keycloak.mongo.clearOnStartup>
|
||||
</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.mongo.port}</port>
|
||||
<logging>file</logging>
|
||||
<logFile>${project.build.directory}/mongodb.log</logFile>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>stop-mongodb</id>
|
||||
<phase>post-integration-test</phase>
|
||||
<goals>
|
||||
<goal>stop</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
Loading…
Reference in a new issue