Full export-import implemented. Remove dependency of mongo on picketlink-common

This commit is contained in:
mposolda committed 2014-05-06 22:15:57 +02:00
1 parent e4e02a2615
commit 0801c9c120
100 files changed
+4878 -1004

No files matched your search

-5
View File
@@ -61,11 +61,6 @@
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.picketlink</groupId>
<artifactId>picketlink-common</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
@@ -1,50 +0,0 @@
package org.keycloak.models.mongo.api;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class AbstractMongoIdentifiableEntity implements MongoIdentifiableEntity {
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public void afterRemove(MongoStoreInvocationContext invocationContext) {
// Empty by default
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (this.id == null) return false;
if (o == null || getClass() != o.getClass()) return false;
AbstractMongoIdentifiableEntity that = (AbstractMongoIdentifiableEntity) o;
if (!getId().equals(that.getId())) return false;
return true;
}
@Override
public int hashCode() {
return id!=null ? id.hashCode() : super.hashCode();
}
@Override
public String toString() {
return String.format("%s [ id=%s ]", getClass().getSimpleName(), getId());
}
}
@@ -40,4 +40,9 @@ public interface MongoStore {
<S> boolean pushItemToList(MongoIdentifiableEntity entity, String listPropertyName, S itemToPush, boolean skipIfAlreadyPresent, MongoStoreInvocationContext context);
<S> boolean pullItemFromList(MongoIdentifiableEntity entity, String listPropertyName, S itemToPull, MongoStoreInvocationContext context);
/**
* Completely remove all data from DB
*/
void removeAllEntities();
}
@@ -1,12 +1,9 @@
package org.keycloak.models.mongo.impl;
import org.keycloak.models.mongo.api.MongoEntity;
import org.picketlink.common.properties.Property;
import org.keycloak.models.utils.reflection.Property;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
@@ -14,24 +11,19 @@ import java.util.Map;
*/
public class EntityInfo {
private final Class<? extends MongoEntity> entityClass;
private final Class<?> entityClass;
private final String dbCollectionName;
private final Map<String, Property<Object>> properties;
public EntityInfo(Class<? extends MongoEntity> entityClass, String dbCollectionName, List<Property<Object>> properties) {
public EntityInfo(Class<?> entityClass, String dbCollectionName, Map<String, Property<Object>> properties) {
this.entityClass = entityClass;
this.dbCollectionName = dbCollectionName;
Map<String, Property<Object>> props= new HashMap<String, Property<Object>>();
for (Property<Object> property : properties) {
props.put(property.getName(), property);
}
this.properties = Collections.unmodifiableMap(props);
this.properties = properties;
}
public Class<? extends MongoEntity> getEntityClass() {
public Class<?> getEntityClass() {
return entityClass;
}
@@ -32,15 +32,16 @@ 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.keycloak.models.utils.KeycloakModelUtils;
import org.picketlink.common.properties.Property;
import org.picketlink.common.properties.query.AnnotatedPropertyCriteria;
import org.picketlink.common.properties.query.PropertyQueries;
import org.keycloak.models.utils.reflection.AnnotatedPropertyCriteria;
import org.keycloak.models.utils.reflection.Property;
import org.keycloak.models.utils.reflection.PropertyQueries;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -55,19 +56,19 @@ public class MongoStoreImpl implements MongoStore {
private static final Logger logger = Logger.getLogger(MongoStoreImpl.class);
private final MapperRegistry mapperRegistry;
private ConcurrentMap<Class<? extends MongoEntity>, EntityInfo> entityInfoCache =
new ConcurrentHashMap<Class<? extends MongoEntity>, EntityInfo>();
private ConcurrentMap<Class<?>, EntityInfo> entityInfoCache =
new ConcurrentHashMap<Class<?>, EntityInfo>();
public MongoStoreImpl(DB database, boolean clearCollectionsOnStartup, Class<? extends MongoEntity>[] managedEntityTypes) {
public MongoStoreImpl(DB database, boolean clearCollectionsOnStartup, Class<?>[] managedEntityTypes) {
this.database = database;
mapperRegistry = new MapperRegistry();
for (Class<?> simpleConverterClass : SIMPLE_TYPES) {
SimpleMapper converter = new SimpleMapper(simpleConverterClass);
mapperRegistry.addAppObjectMapper(converter);
mapperRegistry.addDBObjectMapper(converter);
for (Class<?> simpleMapperClass : SIMPLE_TYPES) {
SimpleMapper mapper = new SimpleMapper(simpleMapperClass);
mapperRegistry.addAppObjectMapper(mapper);
mapperRegistry.addDBObjectMapper(mapper);
}
// Specific converter for ArrayList is added just for performance purposes to avoid recursive converter lookup (most of list idm will be ArrayList)
@@ -83,7 +84,7 @@ public class MongoStoreImpl implements MongoStore {
mapperRegistry.addAppObjectMapper(new EnumToStringMapper());
mapperRegistry.addDBObjectMapper(new StringToEnumMapper());
for (Class<? extends MongoEntity> type : managedEntityTypes) {
for (Class<?> type : managedEntityTypes) {
getEntityInfo(type);
mapperRegistry.addAppObjectMapper(new MongoEntityMapper(this, mapperRegistry, type));
mapperRegistry.addDBObjectMapper(new BasicDBObjectMapper(this, mapperRegistry, type));
@@ -102,9 +103,9 @@ public class MongoStoreImpl implements MongoStore {
logger.info("Database " + this.database.getName() + " dropped in MongoDB");
}
// Don't drop database, but just clear all data in managed collections (useful for development)
protected void clearManagedCollections(Class<? extends MongoEntity>[] managedEntityTypes) {
for (Class<? extends MongoEntity> clazz : managedEntityTypes) {
// Don't drop database, but just clear all data in managed collections (useful for export/import or during development)
protected void clearManagedCollections(Class<?>[] managedEntityTypes) {
for (Class<?> clazz : managedEntityTypes) {
DBCollection dbCollection = getDBCollectionForType(clazz);
if (dbCollection != null) {
dbCollection.remove(new BasicDBObject());
@@ -113,8 +114,8 @@ public class MongoStoreImpl implements MongoStore {
}
}
protected void initManagedCollections(Class<? extends MongoEntity>[] managedEntityTypes) {
for (Class<? extends MongoEntity> clazz : managedEntityTypes) {
protected void initManagedCollections(Class<?>[] managedEntityTypes) {
for (Class<?> clazz : managedEntityTypes) {
EntityInfo entityInfo = getEntityInfo(clazz);
String dbCollectionName = entityInfo.getDbCollectionName();
if (dbCollectionName != null && !database.collectionExists(dbCollectionName)) {
@@ -416,6 +417,13 @@ public class MongoStoreImpl implements MongoStore {
}
}
@Override
public void removeAllEntities() {
Set<Class<?>> managedTypes = this.entityInfoCache.keySet();
Class<? extends MongoEntity>[] arrayTemplate = (Class<? extends MongoEntity>[])new Class<?>[0];
this.clearManagedCollections(managedTypes.toArray(arrayTemplate));
}
// Possibility to add user-defined mappers
public void addAppObjectConverter(Mapper<?, ?> mapper) {
mapperRegistry.addAppObjectMapper(mapper);
@@ -425,10 +433,10 @@ public class MongoStoreImpl implements MongoStore {
mapperRegistry.addDBObjectMapper(mapper);
}
public EntityInfo getEntityInfo(Class<? extends MongoEntity> entityClass) {
public EntityInfo getEntityInfo(Class<?> entityClass) {
EntityInfo entityInfo = entityInfoCache.get(entityClass);
if (entityInfo == null) {
List<Property<Object>> properties = PropertyQueries.createQuery(entityClass).addCriteria(new AnnotatedPropertyCriteria(MongoField.class)).getResultList();
Map<String, Property<Object>> properties = PropertyQueries.createQuery(entityClass).getWritableResultList();
MongoCollection classAnnotation = entityClass.getAnnotation(MongoCollection.class);
@@ -473,7 +481,7 @@ public class MongoStoreImpl implements MongoStore {
return object;
}
protected DBCollection getDBCollectionForType(Class<? extends MongoEntity> type) {
protected DBCollection getDBCollectionForType(Class<?> type) {
EntityInfo entityInfo = getEntityInfo(type);
String dbCollectionName = entityInfo.getDbCollectionName();
return dbCollectionName==null ? null : database.getCollection(dbCollectionName);
@@ -14,13 +14,13 @@ 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.EntityInfo;
import org.picketlink.common.properties.Property;
import org.picketlink.common.reflection.Types;
import org.keycloak.models.utils.reflection.Property;
import org.keycloak.models.utils.reflection.Types;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class BasicDBObjectMapper<S extends MongoEntity> implements Mapper<BasicDBObject, S> {
public class BasicDBObjectMapper<S> implements Mapper<BasicDBObject, S> {
private static final Logger logger = Logger.getLogger(BasicDBObjectMapper.class);
@@ -73,7 +73,7 @@ public class BasicDBObjectMapper<S extends MongoEntity> implements Mapper<BasicD
return entity;
}
private void setPropertyValue(MongoEntity entity, Object valueFromDB, Property property) {
private void setPropertyValue(Object entity, Object valueFromDB, Property property) {
if (valueFromDB == null) {
property.setValue(entity, null);
return;
@@ -1,20 +1,19 @@
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.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.EntityInfo;
import org.picketlink.common.properties.Property;
import org.keycloak.models.utils.reflection.Property;
import java.util.Collection;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class MongoEntityMapper<T extends MongoEntity> implements Mapper<T, BasicDBObject> {
public class MongoEntityMapper<T> implements Mapper<T, BasicDBObject> {
private final MongoStoreImpl mongoStoreImpl;
private final MapperRegistry mapperRegistry;
@@ -37,11 +36,14 @@ public class MongoEntityMapper<T extends MongoEntity> implements Mapper<T, Basic
Collection<Property<Object>> props = entityInfo.getProperties();
for (Property<Object> property : props) {
String propName = property.getName();
Object propValue = property.getValue(applicationObject);
if (propValue != null) {
Object dbValue = mapperRegistry.convertApplicationObjectToDBObject(propValue, Object.class);
dbObject.put(propName, dbValue);
// Ignore "id" property
if (!"id".equals(propName)) {
Object propValue = property.getValue(applicationObject);
if (propValue != null) {
Object dbValue = propValue == null ? null : mapperRegistry.convertApplicationObjectToDBObject(propValue, Object.class);
dbObject.put(propName, dbValue);
}
}
}
@@ -1,13 +1,13 @@
package org.keycloak.models.mongo.keycloak.adapters;
import org.keycloak.models.mongo.api.AbstractMongoIdentifiableEntity;
import org.keycloak.models.mongo.api.MongoIdentifiableEntity;
import org.keycloak.models.mongo.api.MongoStore;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public abstract class AbstractMongoAdapter<T extends AbstractMongoIdentifiableEntity> {
public abstract class AbstractMongoAdapter<T extends MongoIdentifiableEntity> {
protected final MongoStoreInvocationContext invocationContext;
@@ -8,8 +8,8 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.mongo.keycloak.entities.ApplicationEntity;
import org.keycloak.models.mongo.keycloak.entities.RoleEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoApplicationEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
import org.keycloak.models.mongo.utils.MongoModelUtils;
import java.util.ArrayList;
@@ -20,9 +20,9 @@ import java.util.Set;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ApplicationAdapter extends ClientAdapter<ApplicationEntity> implements ApplicationModel {
public class ApplicationAdapter extends ClientAdapter<MongoApplicationEntity> implements ApplicationModel {
public ApplicationAdapter(RealmModel realm, ApplicationEntity applicationEntity, MongoStoreInvocationContext invContext) {
public ApplicationAdapter(RealmModel realm, MongoApplicationEntity applicationEntity, MongoStoreInvocationContext invContext) {
super(realm, applicationEntity, invContext);
}
@@ -103,7 +103,7 @@ public class ApplicationAdapter extends ClientAdapter<ApplicationEntity> impleme
.and("name").is(name)
.and("applicationId").is(getId())
.get();
RoleEntity role = getMongoStore().loadSingleEntity(RoleEntity.class, query, invocationContext);
MongoRoleEntity role = getMongoStore().loadSingleEntity(MongoRoleEntity.class, query, invocationContext);
if (role == null) {
return null;
} else {
@@ -113,7 +113,13 @@ public class ApplicationAdapter extends ClientAdapter<ApplicationEntity> impleme
@Override
public RoleAdapter addRole(String name) {
RoleEntity roleEntity = new RoleEntity();
return this.addRole(null, name);
}
@Override
public RoleAdapter addRole(String id, String name) {
MongoRoleEntity roleEntity = new MongoRoleEntity();
roleEntity.setId(id);
roleEntity.setName(name);
roleEntity.setApplicationId(getId());
@@ -124,7 +130,7 @@ public class ApplicationAdapter extends ClientAdapter<ApplicationEntity> impleme
@Override
public boolean removeRole(RoleModel role) {
return getMongoStore().removeEntity(RoleEntity.class, role.getId(), invocationContext);
return getMongoStore().removeEntity(MongoRoleEntity.class, role.getId(), invocationContext);
}
@Override
@@ -132,10 +138,10 @@ public class ApplicationAdapter extends ClientAdapter<ApplicationEntity> impleme
DBObject query = new QueryBuilder()
.and("applicationId").is(getId())
.get();
List<RoleEntity> roles = getMongoStore().loadEntities(RoleEntity.class, query, invocationContext);
List<MongoRoleEntity> roles = getMongoStore().loadEntities(MongoRoleEntity.class, query, invocationContext);
Set<RoleModel> result = new HashSet<RoleModel>();
for (RoleEntity role : roles) {
for (MongoRoleEntity role : roles) {
result.add(new RoleAdapter(getRealm(), role, this, invocationContext));
}
@@ -145,9 +151,9 @@ public class ApplicationAdapter extends ClientAdapter<ApplicationEntity> impleme
@Override
public Set<RoleModel> getApplicationRoleMappings(UserModel user) {
Set<RoleModel> result = new HashSet<RoleModel>();
List<RoleEntity> roles = MongoModelUtils.getAllRolesOfUser(user, invocationContext);
List<MongoRoleEntity> roles = MongoModelUtils.getAllRolesOfUser(user, invocationContext);
for (RoleEntity role : roles) {
for (MongoRoleEntity role : roles) {
if (getId().equals(role.getApplicationId())) {
result.add(new RoleAdapter(getRealm(), role, this, invocationContext));
}
@@ -158,9 +164,9 @@ public class ApplicationAdapter extends ClientAdapter<ApplicationEntity> impleme
@Override
public Set<RoleModel> getApplicationScopeMappings(ClientModel client) {
Set<RoleModel> result = new HashSet<RoleModel>();
List<RoleEntity> roles = MongoModelUtils.getAllScopesOfClient(client, invocationContext);
List<MongoRoleEntity> roles = MongoModelUtils.getAllScopesOfClient(client, invocationContext);
for (RoleEntity role : roles) {
for (MongoRoleEntity role : roles) {
if (getId().equals(role.getApplicationId())) {
result.add(new RoleAdapter(getRealm(), role, this, invocationContext));
}
@@ -7,13 +7,14 @@ import java.util.Set;
import org.keycloak.models.ClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.entities.ClientEntity;
import org.keycloak.models.mongo.api.MongoIdentifiableEntity;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.mongo.keycloak.entities.ClientEntity;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ClientAdapter<T extends ClientEntity> extends AbstractMongoAdapter<T> implements ClientModel {
public class ClientAdapter<T extends MongoIdentifiableEntity> extends AbstractMongoAdapter<T> implements ClientModel {
protected final T clientEntity;
private final RealmModel realm;
@@ -29,6 +30,11 @@ public class ClientAdapter<T extends ClientEntity> extends AbstractMongoAdapter<
return clientEntity;
}
// ClientEntity doesn't extend MongoIdentifiableEntity
public ClientEntity getMongoEntityAsClient() {
return (ClientEntity)getMongoEntity();
}
@Override
public String getId() {
return getMongoEntity().getId();
@@ -36,25 +42,25 @@ public class ClientAdapter<T extends ClientEntity> extends AbstractMongoAdapter<
@Override
public String getClientId() {
return getMongoEntity().getName();
return getMongoEntityAsClient().getName();
}
@Override
public long getAllowedClaimsMask() {
return getMongoEntity().getAllowedClaimsMask();
return getMongoEntityAsClient().getAllowedClaimsMask();
}
@Override
public void setAllowedClaimsMask(long mask) {
getMongoEntity().setAllowedClaimsMask(mask);
getMongoEntityAsClient().setAllowedClaimsMask(mask);
updateMongoEntity();
}
@Override
public Set<String> getWebOrigins() {
Set<String> result = new HashSet<String>();
if (getMongoEntity().getWebOrigins() != null) {
result.addAll(clientEntity.getWebOrigins());
if (getMongoEntityAsClient().getWebOrigins() != null) {
result.addAll(getMongoEntityAsClient().getWebOrigins());
}
return result;
}
@@ -63,7 +69,7 @@ public class ClientAdapter<T extends ClientEntity> extends AbstractMongoAdapter<
public void setWebOrigins(Set<String> webOrigins) {
List<String> result = new ArrayList<String>();
result.addAll(webOrigins);
clientEntity.setWebOrigins(result);
getMongoEntityAsClient().setWebOrigins(result);
updateMongoEntity();
}
@@ -80,8 +86,8 @@ public class ClientAdapter<T extends ClientEntity> extends AbstractMongoAdapter<
@Override
public Set<String> getRedirectUris() {
Set<String> result = new HashSet<String>();
if (clientEntity.getRedirectUris() != null) {
result.addAll(clientEntity.getRedirectUris());
if (getMongoEntityAsClient().getRedirectUris() != null) {
result.addAll(getMongoEntityAsClient().getRedirectUris());
}
return result;
}
@@ -90,7 +96,7 @@ public class ClientAdapter<T extends ClientEntity> extends AbstractMongoAdapter<
public void setRedirectUris(Set<String> redirectUris) {
List<String> result = new ArrayList<String>();
result.addAll(redirectUris);
clientEntity.setRedirectUris(result);
getMongoEntityAsClient().setRedirectUris(result);
updateMongoEntity();
}
@@ -106,39 +112,39 @@ public class ClientAdapter<T extends ClientEntity> extends AbstractMongoAdapter<
@Override
public boolean isEnabled() {
return clientEntity.isEnabled();
return getMongoEntityAsClient().isEnabled();
}
@Override
public void setEnabled(boolean enabled) {
clientEntity.setEnabled(enabled);
getMongoEntityAsClient().setEnabled(enabled);
updateMongoEntity();
}
@Override
public boolean validateSecret(String secret) {
return secret.equals(clientEntity.getSecret());
return secret.equals(getMongoEntityAsClient().getSecret());
}
@Override
public String getSecret() {
return clientEntity.getSecret();
return getMongoEntityAsClient().getSecret();
}
@Override
public void setSecret(String secret) {
clientEntity.setSecret(secret);
getMongoEntityAsClient().setSecret(secret);
updateMongoEntity();
}
@Override
public boolean isPublicClient() {
return clientEntity.isPublicClient();
return getMongoEntityAsClient().isPublicClient();
}
@Override
public void setPublicClient(boolean flag) {
clientEntity.setPublicClient(flag);
getMongoEntityAsClient().setPublicClient(flag);
updateMongoEntity();
}
@@ -149,12 +155,12 @@ public class ClientAdapter<T extends ClientEntity> extends AbstractMongoAdapter<
@Override
public int getNotBefore() {
return clientEntity.getNotBefore();
return getMongoEntityAsClient().getNotBefore();
}
@Override
public void setNotBefore(int notBefore) {
clientEntity.setNotBefore(notBefore);
getMongoEntityAsClient().setNotBefore(notBefore);
updateMongoEntity();
}
@@ -9,7 +9,7 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.mongo.api.MongoStore;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.mongo.impl.context.TransactionMongoStoreInvocationContext;
import org.keycloak.models.mongo.keycloak.entities.RealmEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity;
import org.keycloak.models.utils.KeycloakModelUtils;
import java.util.ArrayList;
@@ -39,6 +39,11 @@ public class MongoKeycloakSession implements KeycloakSession {
// TODO
}
@Override
public void removeAllData() {
getMongoStore().removeAllEntities();
}
@Override
public RealmModel createRealm(String name) {
return createRealm(KeycloakModelUtils.generateId(), name);
@@ -46,7 +51,7 @@ public class MongoKeycloakSession implements KeycloakSession {
@Override
public RealmModel createRealm(String id, String name) {
RealmEntity newRealm = new RealmEntity();
MongoRealmEntity newRealm = new MongoRealmEntity();
newRealm.setId(id);
newRealm.setName(name);
@@ -57,17 +62,17 @@ public class MongoKeycloakSession implements KeycloakSession {
@Override
public RealmModel getRealm(String id) {
RealmEntity realmEntity = getMongoStore().loadEntity(RealmEntity.class, id, invocationContext);
MongoRealmEntity realmEntity = getMongoStore().loadEntity(MongoRealmEntity.class, id, invocationContext);
return realmEntity != null ? new RealmAdapter(realmEntity, invocationContext) : null;
}
@Override
public List<RealmModel> getRealms() {
DBObject query = new BasicDBObject();
List<RealmEntity> realms = getMongoStore().loadEntities(RealmEntity.class, query, invocationContext);
List<MongoRealmEntity> realms = getMongoStore().loadEntities(MongoRealmEntity.class, query, invocationContext);
List<RealmModel> results = new ArrayList<RealmModel>();
for (RealmEntity realmEntity : realms) {
for (MongoRealmEntity realmEntity : realms) {
results.add(new RealmAdapter(realmEntity, invocationContext));
}
return results;
@@ -78,7 +83,7 @@ public class MongoKeycloakSession implements KeycloakSession {
DBObject query = new QueryBuilder()
.and("name").is(name)
.get();
RealmEntity realm = getMongoStore().loadSingleEntity(RealmEntity.class, query, invocationContext);
MongoRealmEntity realm = getMongoStore().loadSingleEntity(MongoRealmEntity.class, query, invocationContext);
if (realm == null) return null;
return new RealmAdapter(realm, invocationContext);
@@ -86,7 +91,7 @@ public class MongoKeycloakSession implements KeycloakSession {
@Override
public boolean removeRealm(String id) {
return getMongoStore().removeEntity(RealmEntity.class, id, invocationContext);
return getMongoStore().removeEntity(MongoRealmEntity.class, id, invocationContext);
}
protected MongoStore getMongoStore() {
@@ -3,20 +3,20 @@ package org.keycloak.models.mongo.keycloak.adapters;
import org.jboss.logging.Logger;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.mongo.api.MongoEntity;
import org.keycloak.models.entities.AuthenticationLinkEntity;
import org.keycloak.models.entities.AuthenticationProviderEntity;
import org.keycloak.models.entities.CredentialEntity;
import org.keycloak.models.entities.RequiredCredentialEntity;
import org.keycloak.models.entities.SocialLinkEntity;
import org.keycloak.models.mongo.api.MongoStore;
import org.keycloak.models.mongo.impl.MongoStoreImpl;
import org.keycloak.models.mongo.keycloak.config.MongoClientProvider;
import org.keycloak.models.mongo.keycloak.entities.ApplicationEntity;
import org.keycloak.models.mongo.keycloak.entities.AuthenticationLinkEntity;
import org.keycloak.models.mongo.keycloak.entities.AuthenticationProviderEntity;
import org.keycloak.models.mongo.keycloak.entities.CredentialEntity;
import org.keycloak.models.mongo.keycloak.entities.OAuthClientEntity;
import org.keycloak.models.mongo.keycloak.entities.RealmEntity;
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.keycloak.entities.MongoApplicationEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoOAuthClientEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoUsernameLoginFailureEntity;
/**
* KeycloakSessionFactory implementation based on MongoDB
@@ -26,17 +26,18 @@ import org.keycloak.models.mongo.keycloak.entities.UserEntity;
public class MongoKeycloakSessionFactory implements KeycloakSessionFactory {
protected static final Logger logger = Logger.getLogger(MongoKeycloakSessionFactory.class);
private static final Class<? extends MongoEntity>[] MANAGED_ENTITY_TYPES = (Class<? extends MongoEntity>[])new Class<?>[] {
RealmEntity.class,
UserEntity.class,
RoleEntity.class,
private static final Class<?>[] MANAGED_ENTITY_TYPES = (Class<?>[])new Class<?>[] {
MongoRealmEntity.class,
MongoUserEntity.class,
MongoRoleEntity.class,
RequiredCredentialEntity.class,
AuthenticationProviderEntity.class,
CredentialEntity.class,
SocialLinkEntity.class,
AuthenticationLinkEntity.class,
ApplicationEntity.class,
OAuthClientEntity.class
MongoApplicationEntity.class,
MongoOAuthClientEntity.class,
MongoUsernameLoginFailureEntity.class
};
private final MongoClientProvider mongoClientProvider;
@@ -3,14 +3,14 @@ package org.keycloak.models.mongo.keycloak.adapters;
import org.keycloak.models.OAuthClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.mongo.keycloak.entities.OAuthClientEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoOAuthClientEntity;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class OAuthClientAdapter extends ClientAdapter<OAuthClientEntity> implements OAuthClientModel {
public class OAuthClientAdapter extends ClientAdapter<MongoOAuthClientEntity> implements OAuthClientModel {
public OAuthClientAdapter(RealmModel realm, OAuthClientEntity oauthClientEntity, MongoStoreInvocationContext invContext) {
public OAuthClientAdapter(RealmModel realm, MongoOAuthClientEntity oauthClientEntity, MongoStoreInvocationContext invContext) {
super(realm, oauthClientEntity, invContext);
}
@@ -14,19 +14,21 @@ import org.keycloak.models.RequiredCredentialModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.SocialLinkModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserCredentialValueModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UsernameLoginFailureModel;
import org.keycloak.models.entities.AuthenticationLinkEntity;
import org.keycloak.models.entities.AuthenticationProviderEntity;
import org.keycloak.models.entities.CredentialEntity;
import org.keycloak.models.entities.RequiredCredentialEntity;
import org.keycloak.models.entities.SocialLinkEntity;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.mongo.keycloak.entities.ApplicationEntity;
import org.keycloak.models.mongo.keycloak.entities.AuthenticationLinkEntity;
import org.keycloak.models.mongo.keycloak.entities.AuthenticationProviderEntity;
import org.keycloak.models.mongo.keycloak.entities.CredentialEntity;
import org.keycloak.models.mongo.keycloak.entities.OAuthClientEntity;
import org.keycloak.models.mongo.keycloak.entities.RealmEntity;
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.keycloak.entities.UsernameLoginFailureEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoApplicationEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoOAuthClientEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoUsernameLoginFailureEntity;
import org.keycloak.models.mongo.utils.MongoModelUtils;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
@@ -39,7 +41,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -48,18 +49,18 @@ import java.util.regex.Pattern;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements RealmModel {
public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> implements RealmModel {
private static final Logger logger = Logger.getLogger(RealmAdapter.class);
private final RealmEntity realm;
private final MongoRealmEntity realm;
protected volatile transient PublicKey publicKey;
protected volatile transient PrivateKey privateKey;
private volatile transient PasswordPolicy passwordPolicy;
public RealmAdapter(RealmEntity realmEntity, MongoStoreInvocationContext invocationContext) {
public RealmAdapter(MongoRealmEntity realmEntity, MongoStoreInvocationContext invocationContext) {
super(invocationContext);
this.realm = realmEntity;
}
@@ -132,6 +133,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
@Override
public void setBruteForceProtected(boolean value) {
realm.setBruteForceProtected(value);
updateRealm();
}
@Override
@@ -142,6 +144,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
@Override
public void setMaxFailureWaitSeconds(int val) {
realm.setMaxFailureWaitSeconds(val);
updateRealm();
}
@Override
@@ -152,6 +155,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
@Override
public void setWaitIncrementSeconds(int val) {
realm.setWaitIncrementSeconds(val);
updateRealm();
}
@Override
@@ -162,6 +166,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
@Override
public void setQuickLoginCheckMilliSeconds(long val) {
realm.setQuickLoginCheckMilliSeconds(val);
updateRealm();
}
@Override
@@ -172,6 +177,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
@Override
public void setMinimumQuickLoginWaitSeconds(int val) {
realm.setMinimumQuickLoginWaitSeconds(val);
updateRealm();
}
@@ -183,6 +189,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
@Override
public void setMaxDeltaTimeSeconds(int val) {
realm.setMaxDeltaTimeSeconds(val);
updateRealm();
}
@Override
@@ -193,6 +200,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
@Override
public void setFailureFactor(int failureFactor) {
realm.setFailureFactor(failureFactor);
updateRealm();
}
@@ -403,7 +411,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
.and("loginName").is(name)
.and("realmId").is(getId())
.get();
UserEntity user = getMongoStore().loadSingleEntity(UserEntity.class, query, invocationContext);
MongoUserEntity user = getMongoStore().loadSingleEntity(MongoUserEntity.class, query, invocationContext);
if (user == null) {
return null;
@@ -418,7 +426,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
.and("username").is(name)
.and("realmId").is(getId())
.get();
UsernameLoginFailureEntity user = getMongoStore().loadSingleEntity(UsernameLoginFailureEntity.class, query, invocationContext);
MongoUsernameLoginFailureEntity user = getMongoStore().loadSingleEntity(MongoUsernameLoginFailureEntity.class, query, invocationContext);
if (user == null) {
return null;
@@ -434,23 +442,38 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
return userLoginFailure;
}
UsernameLoginFailureEntity userEntity = new UsernameLoginFailureEntity();
MongoUsernameLoginFailureEntity userEntity = new MongoUsernameLoginFailureEntity();
userEntity.setUsername(username);
// Compatibility with JPA model, which has user disabled by default
// userEntity.setEnabled(true);
userEntity.setRealmId(getId());
getMongoStore().insertEntity(userEntity, invocationContext);
return new UsernameLoginFailureAdapter(invocationContext, userEntity);
}
@Override
public List<UsernameLoginFailureModel> getAllUserLoginFailures() {
DBObject query = new QueryBuilder()
.and("realmId").is(getId())
.get();
List<MongoUsernameLoginFailureEntity> failures = getMongoStore().loadEntities(MongoUsernameLoginFailureEntity.class, query, invocationContext);
List<UsernameLoginFailureModel> result = new ArrayList<UsernameLoginFailureModel>();
if (failures == null) return result;
for (MongoUsernameLoginFailureEntity failure : failures) {
result.add(new UsernameLoginFailureAdapter(invocationContext, failure));
}
return result;
}
@Override
public UserModel getUserByEmail(String email) {
DBObject query = new QueryBuilder()
.and("email").is(email)
.and("realmId").is(getId())
.get();
UserEntity user = getMongoStore().loadSingleEntity(UserEntity.class, query, invocationContext);
MongoUserEntity user = getMongoStore().loadSingleEntity(MongoUserEntity.class, query, invocationContext);
if (user == null) {
return null;
@@ -461,7 +484,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
@Override
public UserModel getUserById(String id) {
UserEntity user = getMongoStore().loadEntity(UserEntity.class, id, invocationContext);
MongoUserEntity user = getMongoStore().loadEntity(MongoUserEntity.class, id, invocationContext);
// Check that it's user from this realm
if (user == null || !getId().equals(user.getRealmId())) {
@@ -473,7 +496,12 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
@Override
public UserAdapter addUser(String username) {
UserAdapter userModel = addUserEntity(username);
return this.addUser(null, username);
}
@Override
public UserAdapter addUser(String id, String username) {
UserAdapter userModel = addUserEntity(id, username);
for (String r : getDefaultRoles()) {
grantRole(userModel, getRole(r));
@@ -488,9 +516,9 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
return userModel;
}
// Add just user entity without defaultRoles
protected UserAdapter addUserEntity(String username) {
UserEntity userEntity = new UserEntity();
protected UserAdapter addUserEntity(String id, String username) {
MongoUserEntity userEntity = new MongoUserEntity();
userEntity.setId(id);
userEntity.setLoginName(username);
// Compatibility with JPA model, which has user disabled by default
// userEntity.setEnabled(true);
@@ -506,7 +534,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
.and("loginName").is(name)
.and("realmId").is(getId())
.get();
return getMongoStore().removeEntities(UserEntity.class, query, invocationContext);
return getMongoStore().removeEntities(MongoUserEntity.class, query, invocationContext);
}
@Override
@@ -515,7 +543,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
.and("name").is(name)
.and("realmId").is(getId())
.get();
RoleEntity role = getMongoStore().loadSingleEntity(RoleEntity.class, query, invocationContext);
MongoRoleEntity role = getMongoStore().loadSingleEntity(MongoRoleEntity.class, query, invocationContext);
if (role == null) {
return null;
} else {
@@ -525,7 +553,13 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
@Override
public RoleModel addRole(String name) {
RoleEntity roleEntity = new RoleEntity();
return this.addRole(null, name);
}
@Override
public RoleModel addRole(String id, String name) {
MongoRoleEntity roleEntity = new MongoRoleEntity();
roleEntity.setId(id);
roleEntity.setName(name);
roleEntity.setRealmId(getId());
@@ -541,7 +575,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
@Override
public boolean removeRoleById(String id) {
return getMongoStore().removeEntity(RoleEntity.class, id, invocationContext);
return getMongoStore().removeEntity(MongoRoleEntity.class, id, invocationContext);
}
@Override
@@ -549,12 +583,12 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
DBObject query = new QueryBuilder()
.and("realmId").is(getId())
.get();
List<RoleEntity> roles = getMongoStore().loadEntities(RoleEntity.class, query, invocationContext);
List<MongoRoleEntity> roles = getMongoStore().loadEntities(MongoRoleEntity.class, query, invocationContext);
Set<RoleModel> result = new HashSet<RoleModel>();
if (roles == null) return result;
for (RoleEntity role : roles) {
for (MongoRoleEntity role : roles) {
result.add(new RoleAdapter(this, role, this, invocationContext));
}
@@ -563,7 +597,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
@Override
public RoleModel getRoleById(String id) {
RoleEntity role = getMongoStore().loadEntity(RoleEntity.class, id, invocationContext);
MongoRoleEntity role = getMongoStore().loadEntity(MongoRoleEntity.class, id, invocationContext);
if (role == null) return null;
if (role.getRealmId() != null) {
if (!role.getRealmId().equals(this.getId())) return null;
@@ -615,7 +649,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
@Override
public ApplicationModel getApplicationById(String id) {
ApplicationEntity appData = getMongoStore().loadEntity(ApplicationEntity.class, id, invocationContext);
MongoApplicationEntity appData = getMongoStore().loadEntity(MongoApplicationEntity.class, id, invocationContext);
// Check if application belongs to this realm
if (appData == null || !getId().equals(appData.getRealmId())) {
@@ -631,7 +665,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
.and("realmId").is(getId())
.and("name").is(name)
.get();
ApplicationEntity appEntity = getMongoStore().loadSingleEntity(ApplicationEntity.class, query, invocationContext);
MongoApplicationEntity appEntity = getMongoStore().loadSingleEntity(MongoApplicationEntity.class, query, invocationContext);
return appEntity == null ? null : new ApplicationAdapter(this, appEntity, invocationContext);
}
@@ -649,10 +683,10 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
DBObject query = new QueryBuilder()
.and("realmId").is(getId())
.get();
List<ApplicationEntity> appDatas = getMongoStore().loadEntities(ApplicationEntity.class, query, invocationContext);
List<MongoApplicationEntity> appDatas = getMongoStore().loadEntities(MongoApplicationEntity.class, query, invocationContext);
List<ApplicationModel> result = new ArrayList<ApplicationModel>();
for (ApplicationEntity appData : appDatas) {
for (MongoApplicationEntity appData : appDatas) {
result.add(new ApplicationAdapter(this, appData, invocationContext));
}
return result;
@@ -660,7 +694,13 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
@Override
public ApplicationModel addApplication(String name) {
ApplicationEntity appData = new ApplicationEntity();
return this.addApplication(null, name);
}
@Override
public ApplicationModel addApplication(String id, String name) {
MongoApplicationEntity appData = new MongoApplicationEntity();
appData.setId(id);
appData.setName(name);
appData.setRealmId(getId());
appData.setEnabled(true);
@@ -671,7 +711,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
@Override
public boolean removeApplication(String id) {
return getMongoStore().removeEntity(ApplicationEntity.class, id, invocationContext);
return getMongoStore().removeEntity(MongoApplicationEntity.class, id, invocationContext);
}
@Override
@@ -687,16 +727,16 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
@Override
public void grantRole(UserModel user, RoleModel role) {
UserEntity userEntity = ((UserAdapter) user).getUser();
MongoUserEntity userEntity = ((UserAdapter) user).getUser();
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, invocationContext);
List<MongoRoleEntity> roles = MongoModelUtils.getAllRolesOfUser(user, invocationContext);
for (RoleEntity role : roles) {
for (MongoRoleEntity role : roles) {
if (getId().equals(role.getRealmId())) {
result.add(new RoleAdapter(this, role, this, invocationContext));
} else {
@@ -714,7 +754,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
// Filter to retrieve just realm roles TODO: Maybe improve to avoid filter programmatically... Maybe have separate fields for realmRoles and appRoles on user?
Set<RoleModel> realmRoles = new HashSet<RoleModel>();
for (RoleModel role : allRoles) {
RoleEntity roleEntity = ((RoleAdapter) role).getRole();
MongoRoleEntity roleEntity = ((RoleAdapter) role).getRole();
if (getId().equals(roleEntity.getRealmId())) {
realmRoles.add(role);
@@ -727,16 +767,16 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
public void deleteRoleMapping(UserModel user, RoleModel role) {
if (user == null || role == null) return;
UserEntity userEntity = ((UserAdapter) user).getUser();
MongoUserEntity userEntity = ((UserAdapter) user).getUser();
getMongoStore().pullItemFromList(userEntity, "roleIds", role.getId(), invocationContext);
}
@Override
public Set<RoleModel> getScopeMappings(ClientModel client) {
Set<RoleModel> result = new HashSet<RoleModel>();
List<RoleEntity> roles = MongoModelUtils.getAllScopesOfClient(client, invocationContext);
List<MongoRoleEntity> roles = MongoModelUtils.getAllScopesOfClient(client, invocationContext);
for (RoleEntity role : roles) {
for (MongoRoleEntity role : roles) {
if (getId().equals(role.getRealmId())) {
result.add(new RoleAdapter(this, role, this, invocationContext));
} else {
@@ -754,7 +794,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
// Filter to retrieve just realm roles TODO: Maybe improve to avoid filter programmatically... Maybe have separate fields for realmRoles and appRoles on user?
Set<RoleModel> realmRoles = new HashSet<RoleModel>();
for (RoleModel role : allScopes) {
RoleEntity roleEntity = ((RoleAdapter) role).getRole();
MongoRoleEntity roleEntity = ((RoleAdapter) role).getRole();
if (getId().equals(roleEntity.getRealmId())) {
realmRoles.add(role);
@@ -787,7 +827,13 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
@Override
public OAuthClientModel addOAuthClient(String name) {
OAuthClientEntity oauthClient = new OAuthClientEntity();
return this.addOAuthClient(null, name);
}
@Override
public OAuthClientModel addOAuthClient(String id, String name) {
MongoOAuthClientEntity oauthClient = new MongoOAuthClientEntity();
oauthClient.setId(id);
oauthClient.setRealmId(getId());
oauthClient.setName(name);
getMongoStore().insertEntity(oauthClient, invocationContext);
@@ -797,7 +843,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
@Override
public boolean removeOAuthClient(String id) {
return getMongoStore().removeEntity(OAuthClientEntity.class, id, invocationContext);
return getMongoStore().removeEntity(MongoOAuthClientEntity.class, id, invocationContext);
}
@Override
@@ -806,13 +852,13 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
.and("realmId").is(getId())
.and("name").is(name)
.get();
OAuthClientEntity oauthClient = getMongoStore().loadSingleEntity(OAuthClientEntity.class, query, invocationContext);
MongoOAuthClientEntity oauthClient = getMongoStore().loadSingleEntity(MongoOAuthClientEntity.class, query, invocationContext);
return oauthClient == null ? null : new OAuthClientAdapter(this, oauthClient, invocationContext);
}
@Override
public OAuthClientModel getOAuthClientById(String id) {
OAuthClientEntity clientEntity = getMongoStore().loadEntity(OAuthClientEntity.class, id, invocationContext);
MongoOAuthClientEntity clientEntity = getMongoStore().loadEntity(MongoOAuthClientEntity.class, id, invocationContext);
// Check if client belongs to this realm
if (clientEntity == null || !getId().equals(clientEntity.getRealmId())) return null;
@@ -825,9 +871,9 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
DBObject query = new QueryBuilder()
.and("realmId").is(getId())
.get();
List<OAuthClientEntity> results = getMongoStore().loadEntities(OAuthClientEntity.class, query, invocationContext);
List<MongoOAuthClientEntity> results = getMongoStore().loadEntities(MongoOAuthClientEntity.class, query, invocationContext);
List<OAuthClientModel> list = new ArrayList<OAuthClientModel>();
for (OAuthClientEntity data : results) {
for (MongoOAuthClientEntity data : results) {
list.add(new OAuthClientAdapter(this, data, invocationContext));
}
return list;
@@ -923,13 +969,8 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
@Override
public void updateCredential(UserModel user, UserCredentialModel cred) {
CredentialEntity credentialEntity = null;
UserEntity userEntity = ((UserAdapter) user).getUser();
for (CredentialEntity entity : userEntity.getCredentials()) {
if (entity.getType().equals(cred.getType())) {
credentialEntity = entity;
}
}
MongoUserEntity userEntity = ((UserAdapter) user).getUser();
CredentialEntity credentialEntity = getCredentialEntity(userEntity, cred.getType());
if (credentialEntity == null) {
credentialEntity = new CredentialEntity();
@@ -949,6 +990,52 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
getMongoStore().updateEntity(userEntity, invocationContext);
}
private CredentialEntity getCredentialEntity(MongoUserEntity userEntity, String credType) {
for (CredentialEntity entity : userEntity.getCredentials()) {
if (entity.getType().equals(credType)) {
return entity;
}
}
return null;
}
@Override
public List<UserCredentialValueModel> getCredentialsDirectly(UserModel user) {
MongoUserEntity userEntity = ((UserAdapter) user).getUser();
List<CredentialEntity> credentials = userEntity.getCredentials();
List<UserCredentialValueModel> result = new ArrayList<UserCredentialValueModel>();
for (CredentialEntity credEntity : credentials) {
UserCredentialValueModel credModel = new UserCredentialValueModel();
credModel.setType(credEntity.getType());
credModel.setDevice(credEntity.getDevice());
credModel.setValue(credEntity.getValue());
credModel.setSalt(credEntity.getSalt());
result.add(credModel);
}
return result;
}
@Override
public void updateCredentialDirectly(UserModel user, UserCredentialValueModel credModel) {
MongoUserEntity userEntity = ((UserAdapter) user).getUser();
CredentialEntity credentialEntity = getCredentialEntity(userEntity, credModel.getType());
if (credentialEntity == null) {
credentialEntity = new CredentialEntity();
credentialEntity.setType(credModel.getType());
userEntity.getCredentials().add(credentialEntity);
}
credentialEntity.setValue(credModel.getValue());
credentialEntity.setSalt(credModel.getSalt());
credentialEntity.setDevice(credModel.getDevice());
getMongoStore().updateEntity(userEntity, invocationContext);
}
@Override
public UserModel getUserBySocialLink(SocialLinkModel socialLink) {
DBObject query = new QueryBuilder()
@@ -956,13 +1043,13 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
.and("socialLinks.socialUserId").is(socialLink.getSocialUserId())
.and("realmId").is(getId())
.get();
UserEntity userEntity = getMongoStore().loadSingleEntity(UserEntity.class, query, invocationContext);
MongoUserEntity userEntity = getMongoStore().loadSingleEntity(MongoUserEntity.class, query, invocationContext);
return userEntity == null ? null : new UserAdapter(userEntity, invocationContext);
}
@Override
public Set<SocialLinkModel> getSocialLinks(UserModel user) {
UserEntity userEntity = ((UserAdapter) user).getUser();
MongoUserEntity userEntity = ((UserAdapter) user).getUser();
List<SocialLinkEntity> linkEntities = userEntity.getSocialLinks();
if (linkEntities == null) {
@@ -985,7 +1072,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
@Override
public void addSocialLink(UserModel user, SocialLinkModel socialLink) {
UserEntity userEntity = ((UserAdapter) user).getUser();
MongoUserEntity userEntity = ((UserAdapter) user).getUser();
SocialLinkEntity socialLinkEntity = new SocialLinkEntity();
socialLinkEntity.setSocialProvider(socialLink.getSocialProvider());
socialLinkEntity.setSocialUserId(socialLink.getSocialUserId());
@@ -1000,13 +1087,13 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
if (socialLinkEntity == null) {
return false;
}
UserEntity userEntity = ((UserAdapter) user).getUser();
MongoUserEntity userEntity = ((UserAdapter) user).getUser();
return getMongoStore().pullItemFromList(userEntity, "socialLinks", socialLinkEntity, invocationContext);
}
private SocialLinkEntity findSocialLink(UserModel user, String socialProvider) {
UserEntity userEntity = ((UserAdapter) user).getUser();
MongoUserEntity userEntity = ((UserAdapter) user).getUser();
List<SocialLinkEntity> linkEntities = userEntity.getSocialLinks();
if (linkEntities == null) {
return null;
@@ -1022,7 +1109,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
@Override
public AuthenticationLinkModel getAuthenticationLink(UserModel user) {
UserEntity userEntity = ((UserAdapter) user).getUser();
MongoUserEntity userEntity = ((UserAdapter) user).getUser();
AuthenticationLinkEntity authLinkEntity = userEntity.getAuthenticationLink();
if (authLinkEntity == null) {
@@ -1034,7 +1121,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
@Override
public void setAuthenticationLink(UserModel user, AuthenticationLinkModel authenticationLink) {
UserEntity userEntity = ((UserAdapter) user).getUser();
MongoUserEntity userEntity = ((UserAdapter) user).getUser();
AuthenticationLinkEntity authLinkEntity = new AuthenticationLinkEntity();
authLinkEntity.setAuthProvider(authenticationLink.getAuthProvider());
authLinkEntity.setAuthUserId(authenticationLink.getAuthUserId());
@@ -1060,7 +1147,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
DBObject query = new QueryBuilder()
.and("realmId").is(getId())
.get();
List<UserEntity> users = getMongoStore().loadEntities(UserEntity.class, query, invocationContext);
List<MongoUserEntity> users = getMongoStore().loadEntities(MongoUserEntity.class, query, invocationContext);
return convertUserEntities(users);
}
@@ -1100,7 +1187,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
).get()
);
List<UserEntity> users = getMongoStore().loadEntities(UserEntity.class, builder.get(), invocationContext);
List<MongoUserEntity> users = getMongoStore().loadEntities(MongoUserEntity.class, builder.get(), invocationContext);
return convertUserEntities(users);
}
@@ -1122,13 +1209,13 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
queryBuilder.and(UserModel.EMAIL).regex(Pattern.compile("(?i:" + entry.getValue() + "$)"));
}
}
List<UserEntity> users = getMongoStore().loadEntities(UserEntity.class, queryBuilder.get(), invocationContext);
List<MongoUserEntity> users = getMongoStore().loadEntities(MongoUserEntity.class, queryBuilder.get(), invocationContext);
return convertUserEntities(users);
}
protected List<UserModel> convertUserEntities(List<UserEntity> userEntities) {
protected List<UserModel> convertUserEntities(List<MongoUserEntity> userEntities) {
List<UserModel> userModels = new ArrayList<UserModel>();
for (UserEntity user : userEntities) {
for (MongoUserEntity user : userEntities) {
userModels.add(new UserAdapter(user, invocationContext));
}
return userModels;
@@ -1232,17 +1319,18 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
@Override
public ApplicationModel getAdminApp() {
ApplicationEntity appData = getMongoStore().loadEntity(ApplicationEntity.class, realm.getAdminAppId(), invocationContext);
return new ApplicationAdapter(this, appData, invocationContext);
MongoApplicationEntity appData = getMongoStore().loadEntity(MongoApplicationEntity.class, realm.getAdminAppId(), invocationContext);
return appData != null ? new ApplicationAdapter(this, appData, invocationContext) : null;
}
@Override
public void setAdminApp(ApplicationModel app) {
realm.setAdminAppId(app.getId());
updateRealm();
}
@Override
public RealmEntity getMongoEntity() {
public MongoRealmEntity getMongoEntity() {
return realm;
}
}
@@ -10,11 +10,10 @@ import com.mongodb.QueryBuilder;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.mongo.api.AbstractMongoIdentifiableEntity;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.mongo.keycloak.entities.ApplicationEntity;
import org.keycloak.models.mongo.keycloak.entities.RealmEntity;
import org.keycloak.models.mongo.keycloak.entities.RoleEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoApplicationEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
import org.keycloak.models.utils.KeycloakModelUtils;
/**
@@ -22,17 +21,17 @@ import org.keycloak.models.utils.KeycloakModelUtils;
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class RoleAdapter extends AbstractMongoAdapter<RoleEntity> implements RoleModel {
public class RoleAdapter extends AbstractMongoAdapter<MongoRoleEntity> implements RoleModel {
private final RoleEntity role;
private final MongoRoleEntity role;
private RoleContainerModel roleContainer;
private RealmModel realm;
public RoleAdapter(RealmModel realm, RoleEntity roleEntity, MongoStoreInvocationContext invContext) {
public RoleAdapter(RealmModel realm, MongoRoleEntity roleEntity, MongoStoreInvocationContext invContext) {
this(realm, roleEntity, null, invContext);
}
public RoleAdapter(RealmModel realm, RoleEntity roleEntity, RoleContainerModel roleContainer, MongoStoreInvocationContext invContext) {
public RoleAdapter(RealmModel realm, MongoRoleEntity roleEntity, RoleContainerModel roleContainer, MongoStoreInvocationContext invContext) {
super(invContext);
this.role = roleEntity;
this.roleContainer = roleContainer;
@@ -94,10 +93,10 @@ public class RoleAdapter extends AbstractMongoAdapter<RoleEntity> implements Rol
DBObject query = new QueryBuilder()
.and("_id").in(role.getCompositeRoleIds())
.get();
List<RoleEntity> childRoles = getMongoStore().loadEntities(RoleEntity.class, query, invocationContext);
List<MongoRoleEntity> childRoles = getMongoStore().loadEntities(MongoRoleEntity.class, query, invocationContext);
Set<RoleModel> set = new HashSet<RoleModel>();
for (RoleEntity childRole : childRoles) {
for (MongoRoleEntity childRole : childRoles) {
set.add(new RoleAdapter(realm, childRole, invocationContext));
}
return set;
@@ -108,13 +107,13 @@ public class RoleAdapter extends AbstractMongoAdapter<RoleEntity> implements Rol
if (roleContainer == null) {
// Compute it
if (role.getRealmId() != null) {
RealmEntity realm = getMongoStore().loadEntity(RealmEntity.class, role.getRealmId(), invocationContext);
MongoRealmEntity realm = getMongoStore().loadEntity(MongoRealmEntity.class, role.getRealmId(), invocationContext);
if (realm == null) {
throw new IllegalStateException("Realm with id: " + role.getRealmId() + " doesn't exists");
}
roleContainer = new RealmAdapter(realm, invocationContext);
} else if (role.getApplicationId() != null) {
ApplicationEntity appEntity = getMongoStore().loadEntity(ApplicationEntity.class, role.getApplicationId(), invocationContext);
MongoApplicationEntity appEntity = getMongoStore().loadEntity(MongoApplicationEntity.class, role.getApplicationId(), invocationContext);
if (appEntity == null) {
throw new IllegalStateException("Application with id: " + role.getApplicationId() + " doesn't exists");
}
@@ -135,12 +134,12 @@ public class RoleAdapter extends AbstractMongoAdapter<RoleEntity> implements Rol
return KeycloakModelUtils.searchFor(role, this, visited);
}
public RoleEntity getRole() {
public MongoRoleEntity getRole() {
return role;
}
@Override
public RoleEntity getMongoEntity() {
public MongoRoleEntity getMongoEntity() {
return role;
}
}
@@ -2,7 +2,7 @@ package org.keycloak.models.mongo.keycloak.adapters;
import org.keycloak.models.UserModel;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.mongo.keycloak.entities.UserEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity;
import java.util.Collections;
import java.util.HashMap;
@@ -15,11 +15,11 @@ import java.util.Set;
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class UserAdapter extends AbstractMongoAdapter<UserEntity> implements UserModel {
public class UserAdapter extends AbstractMongoAdapter<MongoUserEntity> implements UserModel {
private final UserEntity user;
private final MongoUserEntity user;
public UserAdapter(UserEntity userEntity, MongoStoreInvocationContext invContext) {
public UserAdapter(MongoUserEntity userEntity, MongoStoreInvocationContext invContext) {
super(invContext);
this.user = userEntity;
}
@@ -133,7 +133,7 @@ public class UserAdapter extends AbstractMongoAdapter<UserEntity> implements Use
return user.getAttributes()==null ? Collections.EMPTY_MAP : Collections.unmodifiableMap(user.getAttributes());
}
public UserEntity getUser() {
public MongoUserEntity getUser() {
return user;
}
@@ -173,7 +173,7 @@ public class UserAdapter extends AbstractMongoAdapter<UserEntity> implements Use
}
@Override
public UserEntity getMongoEntity() {
public MongoUserEntity getMongoEntity() {
return user;
}
@@ -2,23 +2,22 @@ package org.keycloak.models.mongo.keycloak.adapters;
import org.keycloak.models.UsernameLoginFailureModel;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.mongo.keycloak.entities.UserEntity;
import org.keycloak.models.mongo.keycloak.entities.UsernameLoginFailureEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoUsernameLoginFailureEntity;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UsernameLoginFailureAdapter extends AbstractMongoAdapter<UsernameLoginFailureEntity> implements UsernameLoginFailureModel {
protected UsernameLoginFailureEntity user;
public class UsernameLoginFailureAdapter extends AbstractMongoAdapter<MongoUsernameLoginFailureEntity> implements UsernameLoginFailureModel {
protected MongoUsernameLoginFailureEntity user;
public UsernameLoginFailureAdapter(MongoStoreInvocationContext invocationContext, UsernameLoginFailureEntity user) {
public UsernameLoginFailureAdapter(MongoStoreInvocationContext invocationContext, MongoUsernameLoginFailureEntity user) {
super(invocationContext);
this.user = user;
}
@Override
protected UsernameLoginFailureEntity getMongoEntity() {
protected MongoUsernameLoginFailureEntity getMongoEntity() {
return user;
}
@@ -35,6 +34,7 @@ public class UsernameLoginFailureAdapter extends AbstractMongoAdapter<UsernameL
@Override
public void setFailedLoginNotBefore(int notBefore) {
user.setFailedLoginNotBefore(notBefore);
updateMongoEntity();
}
@Override
@@ -45,11 +45,13 @@ public class UsernameLoginFailureAdapter extends AbstractMongoAdapter<UsernameL
@Override
public void incrementFailures() {
user.setNumFailures(getNumFailures() + 1);
updateMongoEntity();
}
@Override
public void clearFailures() {
user.setNumFailures(0);
updateMongoEntity();
}
@Override
@@ -60,6 +62,7 @@ public class UsernameLoginFailureAdapter extends AbstractMongoAdapter<UsernameL
@Override
public void setLastFailure(long lastFailure) {
user.setLastFailure(lastFailure);
updateMongoEntity();
}
@Override
@@ -70,4 +73,5 @@ public class UsernameLoginFailureAdapter extends AbstractMongoAdapter<UsernameL
@Override
public void setLastIPFailure(String ip) {
user.setLastIPFailure(ip);
updateMongoEntity();
}}
@@ -15,12 +15,12 @@ public class SystemPropertiesMongoClientProvider implements MongoClientProvider
protected static final Logger logger = Logger.getLogger(SystemPropertiesMongoClientProvider.class);
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_ON_STARTUP = "keycloak.mongo.clearOnStartup";
public static final String MONGO_HOST = "keycloak.mongo.host";
public static final String MONGO_PORT = "keycloak.mongo.port";
public static final String MONGO_DB_NAME = "keycloak.mongo.db";
public 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
// Property names from Liveoak . Those are used as fallback
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";
@@ -1,81 +0,0 @@
package org.keycloak.models.mongo.keycloak.entities;
import java.util.ArrayList;
import java.util.List;
import com.mongodb.DBObject;
import com.mongodb.QueryBuilder;
import org.keycloak.models.mongo.api.MongoCollection;
import org.keycloak.models.mongo.api.MongoField;
import org.keycloak.models.mongo.api.MongoIndex;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@MongoCollection(collectionName = "applications")
@MongoIndex(fields = { "realmId", "name" }, unique = true)
public class ApplicationEntity extends ClientEntity {
private boolean surrogateAuthRequired;
private String managementUrl;
private String baseUrl;
private boolean bearerOnly;
// We are using names of defaultRoles (not ids)
private List<String> defaultRoles = new ArrayList<String>();
@MongoField
public boolean isSurrogateAuthRequired() {
return surrogateAuthRequired;
}
public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
this.surrogateAuthRequired = surrogateAuthRequired;
}
@MongoField
public String getManagementUrl() {
return managementUrl;
}
public void setManagementUrl(String managementUrl) {
this.managementUrl = managementUrl;
}
@MongoField
public String getBaseUrl() {
return baseUrl;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
@MongoField
public List<String> getDefaultRoles() {
return defaultRoles;
}
public void setDefaultRoles(List<String> defaultRoles) {
this.defaultRoles = defaultRoles;
}
@MongoField
public boolean isBearerOnly() {
return bearerOnly;
}
public void setBearerOnly(boolean bearerOnly) {
this.bearerOnly = bearerOnly;
}
@Override
public void afterRemove(MongoStoreInvocationContext context) {
// Remove all roles, which belongs to this application
DBObject query = new QueryBuilder()
.and("applicationId").is(getId())
.get();
context.getMongoStore().removeEntities(RoleEntity.class, query, context);
}
}
@@ -1,31 +0,0 @@
package org.keycloak.models.mongo.keycloak.entities;
import org.keycloak.models.mongo.api.MongoEntity;
import org.keycloak.models.mongo.api.MongoField;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class AuthenticationLinkEntity implements MongoEntity {
private String authUserId;
private String authProvider;
@MongoField
public String getAuthUserId() {
return authUserId;
}
public void setAuthUserId(String authUserId) {
this.authUserId = authUserId;
}
@MongoField
public String getAuthProvider() {
return authProvider;
}
public void setAuthProvider(String authProvider) {
this.authProvider = authProvider;
}
}
@@ -1,43 +0,0 @@
package org.keycloak.models.mongo.keycloak.entities;
import java.util.Map;
import org.keycloak.models.mongo.api.MongoEntity;
import org.keycloak.models.mongo.api.MongoField;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class AuthenticationProviderEntity implements MongoEntity {
private String providerName;
private boolean passwordUpdateSupported;
private Map<String, String> config;
@MongoField
public String getProviderName() {
return providerName;
}
public void setProviderName(String providerName) {
this.providerName = providerName;
}
@MongoField
public boolean isPasswordUpdateSupported() {
return passwordUpdateSupported;
}
public void setPasswordUpdateSupported(boolean passwordUpdateSupported) {
this.passwordUpdateSupported = passwordUpdateSupported;
}
@MongoField
public Map<String, String> getConfig() {
return config;
}
public void setConfig(Map<String, String> config) {
this.config = config;
}
}
@@ -1,117 +0,0 @@
package org.keycloak.models.mongo.keycloak.entities;
import java.util.ArrayList;
import java.util.List;
import org.keycloak.models.mongo.api.AbstractMongoIdentifiableEntity;
import org.keycloak.models.mongo.api.MongoEntity;
import org.keycloak.models.mongo.api.MongoField;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ClientEntity extends AbstractMongoIdentifiableEntity implements MongoEntity {
private String name;
private boolean enabled;
private String secret;
private long allowedClaimsMask;
private int notBefore;
private boolean publicClient;
private String realmId;
private List<String> webOrigins = new ArrayList<String>();
private List<String> redirectUris = new ArrayList<String>();
private List<String> scopeIds = new ArrayList<String>();
@MongoField
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@MongoField
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@MongoField
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
@MongoField
public long getAllowedClaimsMask() {
return allowedClaimsMask;
}
public void setAllowedClaimsMask(long allowedClaimsMask) {
this.allowedClaimsMask = allowedClaimsMask;
}
@MongoField
public int getNotBefore() {
return notBefore;
}
public void setNotBefore(int notBefore) {
this.notBefore = notBefore;
}
@MongoField
public boolean isPublicClient() {
return publicClient;
}
public void setPublicClient(boolean publicClient) {
this.publicClient = publicClient;
}
@MongoField
public String getRealmId() {
return realmId;
}
public void setRealmId(String realmId) {
this.realmId = realmId;
}
@MongoField
public List<String> getWebOrigins() {
return webOrigins;
}
public void setWebOrigins(List<String> webOrigins) {
this.webOrigins = webOrigins;
}
@MongoField
public List<String> getRedirectUris() {
return redirectUris;
}
public void setRedirectUris(List<String> redirectUris) {
this.redirectUris = redirectUris;
}
@MongoField
public List<String> getScopeIds() {
return scopeIds;
}
public void setScopeIds(List<String> scopeIds) {
this.scopeIds = scopeIds;
}
}
@@ -1,51 +0,0 @@
package org.keycloak.models.mongo.keycloak.entities;
import org.keycloak.models.mongo.api.MongoEntity;
import org.keycloak.models.mongo.api.MongoField;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class CredentialEntity implements MongoEntity {
private String type;
private String value;
private String device;
private byte[] salt;
@MongoField
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@MongoField
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@MongoField
public String getDevice() {
return device;
}
public void setDevice(String device) {
this.device = device;
}
@MongoField
public byte[] getSalt() {
return salt;
}
public void setSalt(byte[] salt) {
this.salt = salt;
}
}
@@ -0,0 +1,26 @@
package org.keycloak.models.mongo.keycloak.entities;
import com.mongodb.DBObject;
import com.mongodb.QueryBuilder;
import org.keycloak.models.entities.ApplicationEntity;
import org.keycloak.models.mongo.api.MongoCollection;
import org.keycloak.models.mongo.api.MongoIdentifiableEntity;
import org.keycloak.models.mongo.api.MongoIndex;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@MongoCollection(collectionName = "applications")
@MongoIndex(fields = { "realmId", "name" }, unique = true)
public class MongoApplicationEntity extends ApplicationEntity implements MongoIdentifiableEntity {
@Override
public void afterRemove(MongoStoreInvocationContext context) {
// Remove all roles, which belongs to this application
DBObject query = new QueryBuilder()
.and("applicationId").is(getId())
.get();
context.getMongoStore().removeEntities(MongoRoleEntity.class, query, context);
}
}
@@ -0,0 +1,19 @@
package org.keycloak.models.mongo.keycloak.entities;
import org.keycloak.models.entities.OAuthClientEntity;
import org.keycloak.models.mongo.api.MongoCollection;
import org.keycloak.models.mongo.api.MongoIdentifiableEntity;
import org.keycloak.models.mongo.api.MongoIndex;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@MongoCollection(collectionName = "oauthClients")
@MongoIndex(fields = { "realmId", "name" }, unique = true)
public class MongoOAuthClientEntity extends OAuthClientEntity implements MongoIdentifiableEntity {
@Override
public void afterRemove(MongoStoreInvocationContext invocationContext) {
}
}
@@ -0,0 +1,36 @@
package org.keycloak.models.mongo.keycloak.entities;
import com.mongodb.DBObject;
import com.mongodb.QueryBuilder;
import org.keycloak.models.entities.RealmEntity;
import org.keycloak.models.mongo.api.MongoCollection;
import org.keycloak.models.mongo.api.MongoIdentifiableEntity;
import org.keycloak.models.mongo.api.MongoIndex;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@MongoCollection(collectionName = "realms")
@MongoIndex(fields = { "name" }, unique = true)
public class MongoRealmEntity extends RealmEntity implements MongoIdentifiableEntity {
@Override
public void afterRemove(MongoStoreInvocationContext context) {
DBObject query = new QueryBuilder()
.and("realmId").is(getId())
.get();
// Remove all users of this realm
context.getMongoStore().removeEntities(MongoUserEntity.class, query, context);
// Remove all roles of this realm
context.getMongoStore().removeEntities(MongoRoleEntity.class, query, context);
// Remove all applications of this realm
context.getMongoStore().removeEntities(MongoApplicationEntity.class, query, context);
// Remove all clients of this realm
context.getMongoStore().removeEntities(MongoOAuthClientEntity.class, query, context);
}
}
@@ -3,10 +3,10 @@ package org.keycloak.models.mongo.keycloak.entities;
import com.mongodb.DBObject;
import com.mongodb.QueryBuilder;
import org.jboss.logging.Logger;
import org.keycloak.models.mongo.api.AbstractMongoIdentifiableEntity;
import org.keycloak.models.entities.RoleEntity;
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.MongoIdentifiableEntity;
import org.keycloak.models.mongo.api.MongoIndex;
import org.keycloak.models.mongo.api.MongoStore;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
@@ -18,21 +18,17 @@ import java.util.List;
*/
@MongoCollection(collectionName = "roles")
@MongoIndex(fields = "nameIndex", unique = true)
public class RoleEntity extends AbstractMongoIdentifiableEntity implements MongoEntity {
public class MongoRoleEntity extends RoleEntity implements MongoIdentifiableEntity {
private static final Logger logger = Logger.getLogger(RoleEntity.class);
private String name;
private String description;
private List<String> compositeRoleIds;
private String realmId;
private String applicationId;
private static final Logger logger = Logger.getLogger(MongoRoleEntity.class);
@MongoField
// TODO This is required as Mongo doesn't support sparse indexes with compound keys (see https://jira.mongodb.org/browse/SERVER-2193)
public String getNameIndex() {
String realmId = getRealmId();
String applicationId = getApplicationId();
String name = getName();
if (realmId != null) {
return realmId + "//" + name;
} else {
@@ -43,51 +39,6 @@ public class RoleEntity extends AbstractMongoIdentifiableEntity implements Mongo
public void setNameIndex(String ignored) {
}
@MongoField
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@MongoField
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@MongoField
public List<String> getCompositeRoleIds() {
return compositeRoleIds;
}
public void setCompositeRoleIds(List<String> compositeRoleIds) {
this.compositeRoleIds = compositeRoleIds;
}
@MongoField
public String getRealmId() {
return realmId;
}
public void setRealmId(String realmId) {
this.realmId = realmId;
}
@MongoField
public String getApplicationId() {
return applicationId;
}
public void setApplicationId(String applicationId) {
this.applicationId = applicationId;
}
@Override
public void afterRemove(MongoStoreInvocationContext invContext) {
MongoStore mongoStore = invContext.getMongoStore();
@@ -97,8 +48,8 @@ public class RoleEntity extends AbstractMongoIdentifiableEntity implements Mongo
.and("roleIds").is(getId())
.get();
List<UserEntity> users = mongoStore.loadEntities(UserEntity.class, query, invContext);
for (UserEntity user : users) {
List<MongoUserEntity> users = mongoStore.loadEntities(MongoUserEntity.class, query, invContext);
for (MongoUserEntity user : users) {
logger.info("Removing role " + getName() + " from user " + user.getLoginName());
mongoStore.pullItemFromList(user, "roleIds", getId(), invContext);
}
@@ -108,15 +59,15 @@ public class RoleEntity extends AbstractMongoIdentifiableEntity implements Mongo
.and("scopeIds").is(getId())
.get();
users = mongoStore.loadEntities(UserEntity.class, query, invContext);
for (UserEntity user : users) {
users = mongoStore.loadEntities(MongoUserEntity.class, query, invContext);
for (MongoUserEntity user : users) {
logger.info("Removing scope " + getName() + " from user " + user.getLoginName());
mongoStore.pullItemFromList(user, "scopeIds", getId(), invContext);
}
// Remove defaultRoles from realm
if (realmId != null) {
RealmEntity realmEntity = mongoStore.loadEntity(RealmEntity.class, realmId, invContext);
if (getRealmId() != null) {
MongoRealmEntity realmEntity = mongoStore.loadEntity(MongoRealmEntity.class, getRealmId(), invContext);
// Realm might be already removed at this point
if (realmEntity != null) {
@@ -125,8 +76,8 @@ public class RoleEntity extends AbstractMongoIdentifiableEntity implements Mongo
}
// Remove defaultRoles from application
if (applicationId != null) {
ApplicationEntity appEntity = mongoStore.loadEntity(ApplicationEntity.class, applicationId, invContext);
if (getApplicationId() != null) {
MongoApplicationEntity appEntity = mongoStore.loadEntity(MongoApplicationEntity.class, getApplicationId(), invContext);
// Application might be already removed at this point
if (appEntity != null) {
@@ -138,8 +89,8 @@ public class RoleEntity extends AbstractMongoIdentifiableEntity implements Mongo
query = new QueryBuilder()
.and("compositeRoleIds").is(getId())
.get();
List<RoleEntity> parentRoles = mongoStore.loadEntities(RoleEntity.class, query, invContext);
for (RoleEntity role : parentRoles) {
List<MongoRoleEntity> parentRoles = mongoStore.loadEntities(MongoRoleEntity.class, query, invContext);
for (MongoRoleEntity role : parentRoles) {
mongoStore.pullItemFromList(role, "compositeRoleIds", getId(), invContext);
}
}
@@ -0,0 +1,32 @@
package org.keycloak.models.mongo.keycloak.entities;
import org.keycloak.models.entities.UserEntity;
import org.keycloak.models.mongo.api.MongoCollection;
import org.keycloak.models.mongo.api.MongoIdentifiableEntity;
import org.keycloak.models.mongo.api.MongoIndex;
import org.keycloak.models.mongo.api.MongoIndexes;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@MongoCollection(collectionName = "users")
@MongoIndexes({
@MongoIndex(fields = { "realmId", "loginName" }, unique = true),
@MongoIndex(fields = { "emailIndex" }, unique = true, sparse = true),
})
public class MongoUserEntity extends UserEntity implements MongoIdentifiableEntity {
public String getEmailIndex() {
return getEmail() != null ? getRealmId() + "//" + getEmail() : null;
}
public void setEmailIndex(String ignored) {
}
@Override
public void afterRemove(MongoStoreInvocationContext invocationContext) {
//To change body of implemented methods use File | Settings | File Templates.
}
}
@@ -0,0 +1,18 @@
package org.keycloak.models.mongo.keycloak.entities;
import org.keycloak.models.entities.UsernameLoginFailureEntity;
import org.keycloak.models.mongo.api.MongoCollection;
import org.keycloak.models.mongo.api.MongoIdentifiableEntity;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@MongoCollection(collectionName = "userFailures")
public class MongoUsernameLoginFailureEntity extends UsernameLoginFailureEntity implements MongoIdentifiableEntity {
@Override
public void afterRemove(MongoStoreInvocationContext invocationContext) {
}
}
@@ -1,15 +0,0 @@
package org.keycloak.models.mongo.keycloak.entities;
import org.keycloak.models.mongo.api.MongoCollection;
import org.keycloak.models.mongo.api.MongoIndex;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@MongoCollection(collectionName = "oauthClients")
@MongoIndex(fields = { "realmId", "name" }, unique = true)
public class OAuthClientEntity extends ClientEntity {
}
@@ -1,429 +0,0 @@
package org.keycloak.models.mongo.keycloak.entities;
import com.mongodb.DBObject;
import com.mongodb.QueryBuilder;
import org.keycloak.models.ApplicationModel;
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.MongoIndex;
import org.keycloak.models.mongo.api.MongoIndexes;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@MongoCollection(collectionName = "realms")
@MongoIndex(fields = { "name" }, unique = true)
public class RealmEntity extends AbstractMongoIdentifiableEntity implements MongoEntity {
private String name;
private boolean enabled;
private boolean sslNotRequired;
private boolean registrationAllowed;
private boolean rememberMe;
private boolean verifyEmail;
private boolean resetPasswordAllowed;
private boolean social;
private boolean updateProfileOnInitialSocialLogin;
private String passwordPolicy;
//--- brute force settings
private boolean bruteForceProtected;
private int maxFailureWaitSeconds;
private int minimumQuickLoginWaitSeconds;
private int waitIncrementSeconds;
private long quickLoginCheckMilliSeconds;
private int maxDeltaTimeSeconds;
private int failureFactor;
//--- end brute force settings
private int centralLoginLifespan;
private int accessTokenLifespan;
private int accessCodeLifespan;
private int accessCodeLifespanUserAction;
private int refreshTokenLifespan;
private int notBefore;
private String publicKeyPem;
private String privateKeyPem;
private String loginTheme;
private String accountTheme;
// We are using names of defaultRoles (not ids)
private List<String> defaultRoles = new ArrayList<String>();
private List<RequiredCredentialEntity> requiredCredentials = new ArrayList<RequiredCredentialEntity>();
private List<AuthenticationProviderEntity> authenticationProviders = new ArrayList<AuthenticationProviderEntity>();
private Map<String, String> smtpConfig = new HashMap<String, String>();
private Map<String, String> socialConfig = new HashMap<String, String>();
private Map<String, String> ldapServerConfig;
private boolean auditEnabled;
private long auditExpiration;
private List<String> auditListeners = new ArrayList<String>();
private String adminAppId;
@MongoField
public String getName() {
return name;
}
public void setName(String realmName) {
this.name = realmName;
}
@MongoField
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@MongoField
public boolean isSslNotRequired() {
return sslNotRequired;
}
public void setSslNotRequired(boolean sslNotRequired) {
this.sslNotRequired = sslNotRequired;
}
@MongoField
public boolean isRegistrationAllowed() {
return registrationAllowed;
}
public void setRegistrationAllowed(boolean registrationAllowed) {
this.registrationAllowed = registrationAllowed;
}
@MongoField
public boolean isRememberMe() {
return rememberMe;
}
public void setRememberMe(boolean rememberMe) {
this.rememberMe = rememberMe;
}
@MongoField
public boolean isVerifyEmail() {
return verifyEmail;
}
public void setVerifyEmail(boolean verifyEmail) {
this.verifyEmail = verifyEmail;
}
@MongoField
public boolean isResetPasswordAllowed() {
return resetPasswordAllowed;
}
public void setResetPasswordAllowed(boolean resetPasswordAllowed) {
this.resetPasswordAllowed = resetPasswordAllowed;
}
@MongoField
public boolean isSocial() {
return social;
}
public void setSocial(boolean social) {
this.social = social;
}
@MongoField
public boolean isUpdateProfileOnInitialSocialLogin() {
return updateProfileOnInitialSocialLogin;
}
public void setUpdateProfileOnInitialSocialLogin(boolean updateProfileOnInitialSocialLogin) {
this.updateProfileOnInitialSocialLogin = updateProfileOnInitialSocialLogin;
}
@MongoField
public boolean isBruteForceProtected() {
return bruteForceProtected;
}
public void setBruteForceProtected(boolean bruteForceProtected) {
this.bruteForceProtected = bruteForceProtected;
}
@MongoField
public int getMaxFailureWaitSeconds() {
return maxFailureWaitSeconds;
}
public void setMaxFailureWaitSeconds(int maxFailureWaitSeconds) {
this.maxFailureWaitSeconds = maxFailureWaitSeconds;
}
@MongoField
public int getMinimumQuickLoginWaitSeconds() {
return minimumQuickLoginWaitSeconds;
}
public void setMinimumQuickLoginWaitSeconds(int minimumQuickLoginWaitSeconds) {
this.minimumQuickLoginWaitSeconds = minimumQuickLoginWaitSeconds;
}
@MongoField
public int getWaitIncrementSeconds() {
return waitIncrementSeconds;
}
public void setWaitIncrementSeconds(int waitIncrementSeconds) {
this.waitIncrementSeconds = waitIncrementSeconds;
}
@MongoField
public long getQuickLoginCheckMilliSeconds() {
return quickLoginCheckMilliSeconds;
}
public void setQuickLoginCheckMilliSeconds(long quickLoginCheckMilliSeconds) {
this.quickLoginCheckMilliSeconds = quickLoginCheckMilliSeconds;
}
@MongoField
public int getMaxDeltaTimeSeconds() {
return maxDeltaTimeSeconds;
}
public void setMaxDeltaTimeSeconds(int maxDeltaTimeSeconds) {
this.maxDeltaTimeSeconds = maxDeltaTimeSeconds;
}
@MongoField
public int getFailureFactor() {
return failureFactor;
}
public void setFailureFactor(int failureFactor) {
this.failureFactor = failureFactor;
}
@MongoField
public String getPasswordPolicy() {
return passwordPolicy;
}
public void setPasswordPolicy(String passwordPolicy) {
this.passwordPolicy = passwordPolicy;
}
@MongoField
public int getNotBefore() {
return notBefore;
}
public void setNotBefore(int notBefore) {
this.notBefore = notBefore;
}
@MongoField
public int getCentralLoginLifespan() {
return centralLoginLifespan;
}
public void setCentralLoginLifespan(int centralLoginLifespan) {
this.centralLoginLifespan = centralLoginLifespan;
}
@MongoField
public int getAccessTokenLifespan() {
return accessTokenLifespan;
}
public void setAccessTokenLifespan(int accessTokenLifespan) {
this.accessTokenLifespan = accessTokenLifespan;
}
@MongoField
public int getRefreshTokenLifespan() {
return refreshTokenLifespan;
}
public void setRefreshTokenLifespan(int refreshTokenLifespan) {
this.refreshTokenLifespan = refreshTokenLifespan;
}
@MongoField
public int getAccessCodeLifespan() {
return accessCodeLifespan;
}
public void setAccessCodeLifespan(int accessCodeLifespan) {
this.accessCodeLifespan = accessCodeLifespan;
}
@MongoField
public int getAccessCodeLifespanUserAction() {
return accessCodeLifespanUserAction;
}
public void setAccessCodeLifespanUserAction(int accessCodeLifespanUserAction) {
this.accessCodeLifespanUserAction = accessCodeLifespanUserAction;
}
@MongoField
public String getPublicKeyPem() {
return publicKeyPem;
}
public void setPublicKeyPem(String publicKeyPem) {
this.publicKeyPem = publicKeyPem;
}
@MongoField
public String getPrivateKeyPem() {
return privateKeyPem;
}
public void setPrivateKeyPem(String privateKeyPem) {
this.privateKeyPem = privateKeyPem;
}
@MongoField
public String getLoginTheme() {
return loginTheme;
}
public void setLoginTheme(String loginTheme) {
this.loginTheme = loginTheme;
}
@MongoField
public String getAccountTheme() {
return accountTheme;
}
public void setAccountTheme(String accountTheme) {
this.accountTheme = accountTheme;
}
@MongoField
public List<String> getDefaultRoles() {
return defaultRoles;
}
public void setDefaultRoles(List<String> defaultRoles) {
this.defaultRoles = defaultRoles;
}
@MongoField
public List<RequiredCredentialEntity> getRequiredCredentials() {
return requiredCredentials;
}
public void setRequiredCredentials(List<RequiredCredentialEntity> requiredCredentials) {
this.requiredCredentials = requiredCredentials;
}
@MongoField
public List<AuthenticationProviderEntity> getAuthenticationProviders() {
return authenticationProviders;
}
public void setAuthenticationProviders(List<AuthenticationProviderEntity> authenticationProviders) {
this.authenticationProviders = authenticationProviders;
}
@MongoField
public Map<String, String> getSmtpConfig() {
return smtpConfig;
}
public void setSmtpConfig(Map<String, String> smptConfig) {
this.smtpConfig = smptConfig;
}
@MongoField
public Map<String, String> getSocialConfig() {
return socialConfig;
}
public void setSocialConfig(Map<String, String> socialConfig) {
this.socialConfig = socialConfig;
}
@MongoField
public Map<String, String> getLdapServerConfig() {
return ldapServerConfig;
}
public void setLdapServerConfig(Map<String, String> ldapServerConfig) {
this.ldapServerConfig = ldapServerConfig;
}
@MongoField
public boolean isAuditEnabled() {
return auditEnabled;
}
public void setAuditEnabled(boolean auditEnabled) {
this.auditEnabled = auditEnabled;
}
@MongoField
public long getAuditExpiration() {
return auditExpiration;
}
public void setAuditExpiration(long auditExpiration) {
this.auditExpiration = auditExpiration;
}
@MongoField
public List<String> getAuditListeners() {
return auditListeners;
}
public void setAuditListeners(List<String> auditListeners) {
this.auditListeners = auditListeners;
}
@MongoField
public String getAdminAppId() {
return adminAppId;
}
public void setAdminAppId(String adminAppId) {
this.adminAppId = adminAppId;
}
@Override
public void afterRemove(MongoStoreInvocationContext context) {
DBObject query = new QueryBuilder()
.and("realmId").is(getId())
.get();
// Remove all users of this realm
context.getMongoStore().removeEntities(UserEntity.class, query, context);
// Remove all roles of this realm
context.getMongoStore().removeEntities(RoleEntity.class, query, context);
// Remove all applications of this realm
context.getMongoStore().removeEntities(ApplicationEntity.class, query, context);
// Remove all clients of this realm
context.getMongoStore().removeEntities(OAuthClientEntity.class, query, context);
}
}
@@ -1,51 +0,0 @@
package org.keycloak.models.mongo.keycloak.entities;
import org.keycloak.models.mongo.api.MongoEntity;
import org.keycloak.models.mongo.api.MongoField;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class RequiredCredentialEntity implements MongoEntity {
private String type;
private boolean input;
private boolean secret;
private String formLabel;
@MongoField
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@MongoField
public boolean isInput() {
return input;
}
public void setInput(boolean input) {
this.input = input;
}
@MongoField
public boolean isSecret() {
return secret;
}
public void setSecret(boolean secret) {
this.secret = secret;
}
@MongoField
public String getFormLabel() {
return formLabel;
}
public void setFormLabel(String formLabel) {
this.formLabel = formLabel;
}
}
@@ -1,68 +0,0 @@
package org.keycloak.models.mongo.keycloak.entities;
import org.keycloak.models.mongo.api.MongoEntity;
import org.keycloak.models.mongo.api.MongoField;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class SocialLinkEntity implements MongoEntity {
private String socialUserId;
private String socialUsername;
private String socialProvider;
@MongoField
public String getSocialUserId() {
return socialUserId;
}
public void setSocialUserId(String socialUserId) {
this.socialUserId = socialUserId;
}
@MongoField
public String getSocialUsername() {
return socialUsername;
}
public void setSocialUsername(String socialUsername) {
this.socialUsername = socialUsername;
}
@MongoField
public String getSocialProvider() {
return socialProvider;
}
public void setSocialProvider(String socialProvider) {
this.socialProvider = socialProvider;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SocialLinkEntity that = (SocialLinkEntity) o;
if (socialProvider != null && (that.socialProvider == null || !socialProvider.equals(that.socialProvider))) return false;
if (socialUserId != null && (that.socialUserId == null || !socialUserId.equals(that.socialUserId))) return false;
if (socialProvider == null && that.socialProvider != null)return false;
if (socialUserId == null && that.socialUserId != null) return false;
return true;
}
@Override
public int hashCode() {
int code = 1;
if (socialUserId != null) {
code = code * socialUserId.hashCode() * 13;
}
if (socialProvider != null) {
code = code * socialProvider.hashCode() * 17;
}
return code;
}
}
@@ -1,193 +0,0 @@
package org.keycloak.models.mongo.keycloak.entities;
import org.keycloak.models.UserModel;
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.MongoIndex;
import org.keycloak.models.mongo.api.MongoIndexes;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@MongoCollection(collectionName = "users")
@MongoIndexes({
@MongoIndex(fields = { "realmId", "loginName" }, unique = true),
@MongoIndex(fields = { "emailIndex" }, unique = true, sparse = true),
})
public class UserEntity extends AbstractMongoIdentifiableEntity implements MongoEntity {
private String loginName;
private String firstName;
private String lastName;
private String email;
private boolean emailVerified;
private boolean totp;
private boolean enabled;
private int notBefore;
private int failedLoginNotBefore;
private int numFailures;
private long lastFailure;
private String lastIPFailure;
private String realmId;
private List<String> roleIds;
private Map<String, String> attributes;
private List<UserModel.RequiredAction> requiredActions;
private List<CredentialEntity> credentials = new ArrayList<CredentialEntity>();
private List<SocialLinkEntity> socialLinks;
private AuthenticationLinkEntity authenticationLink;
@MongoField
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
@MongoField
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
@MongoField
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@MongoField
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@MongoField
// TODO This is required as Mongo doesn't support sparse indexes with compound keys (see https://jira.mongodb.org/browse/SERVER-2193)
public String getEmailIndex() {
return email != null ? realmId + "//" + email : null;
}
public void setEmailIndex(String ignored) {
}
@MongoField
public boolean isEmailVerified() {
return emailVerified;
}
public void setEmailVerified(boolean emailVerified) {
this.emailVerified = emailVerified;
}
@MongoField
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@MongoField
public boolean isTotp() {
return totp;
}
public void setTotp(boolean totp) {
this.totp = totp;
}
@MongoField
public int getNotBefore() {
return notBefore;
}
public void setNotBefore(int notBefore) {
this.notBefore = notBefore;
}
@MongoField
public String getRealmId() {
return realmId;
}
public void setRealmId(String realmId) {
this.realmId = realmId;
}
@MongoField
public List<String> getRoleIds() {
return roleIds;
}
public void setRoleIds(List<String> roleIds) {
this.roleIds = roleIds;
}
@MongoField
public Map<String, String> getAttributes() {
return attributes;
}
public void setAttributes(Map<String, String> attributes) {
this.attributes = attributes;
}
@MongoField
public List<UserModel.RequiredAction> getRequiredActions() {
return requiredActions;
}
public void setRequiredActions(List<UserModel.RequiredAction> requiredActions) {
this.requiredActions = requiredActions;
}
@MongoField
public List<CredentialEntity> getCredentials() {
return credentials;
}
public void setCredentials(List<CredentialEntity> credentials) {
this.credentials = credentials;
}
@MongoField
public List<SocialLinkEntity> getSocialLinks() {
return socialLinks;
}
public void setSocialLinks(List<SocialLinkEntity> socialLinks) {
this.socialLinks = socialLinks;
}
@MongoField
public AuthenticationLinkEntity getAuthenticationLink() {
return authenticationLink;
}
public void setAuthenticationLink(AuthenticationLinkEntity authenticationLink) {
this.authenticationLink = authenticationLink;
}
}
@@ -1,76 +0,0 @@
package org.keycloak.models.mongo.keycloak.entities;
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;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@MongoCollection(collectionName = "userFailures")
public class UsernameLoginFailureEntity extends AbstractMongoIdentifiableEntity implements MongoEntity {
private String username;
private int failedLoginNotBefore;
private int numFailures;
private long lastFailure;
private String lastIPFailure;
private String realmId;
@MongoField
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@MongoField
public int getFailedLoginNotBefore() {
return failedLoginNotBefore;
}
public void setFailedLoginNotBefore(int failedLoginNotBefore) {
this.failedLoginNotBefore = failedLoginNotBefore;
}
@MongoField
public int getNumFailures() {
return numFailures;
}
public void setNumFailures(int numFailures) {
this.numFailures = numFailures;
}
@MongoField
public long getLastFailure() {
return lastFailure;
}
public void setLastFailure(long lastFailure) {
this.lastFailure = lastFailure;
}
@MongoField
public String getLastIPFailure() {
return lastIPFailure;
}
public void setLastIPFailure(String lastIPFailure) {
this.lastIPFailure = lastIPFailure;
}
@MongoField
public String getRealmId() {
return realmId;
}
public void setRealmId(String realmId) {
this.realmId = realmId;
}
}
@@ -7,12 +7,12 @@ import com.mongodb.DBObject;
import com.mongodb.QueryBuilder;
import org.keycloak.models.ClientModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.entities.ClientEntity;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.mongo.keycloak.adapters.ClientAdapter;
import org.keycloak.models.mongo.keycloak.adapters.UserAdapter;
import org.keycloak.models.mongo.keycloak.entities.ClientEntity;
import org.keycloak.models.mongo.keycloak.entities.RoleEntity;
import org.keycloak.models.mongo.keycloak.entities.UserEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -20,8 +20,8 @@ import org.keycloak.models.mongo.keycloak.entities.UserEntity;
public class MongoModelUtils {
// Get everything including both application and realm roles
public static List<RoleEntity> getAllRolesOfUser(UserModel user, MongoStoreInvocationContext invContext) {
UserEntity userEntity = ((UserAdapter)user).getUser();
public static List<MongoRoleEntity> getAllRolesOfUser(UserModel user, MongoStoreInvocationContext invContext) {
MongoUserEntity userEntity = ((UserAdapter)user).getUser();
List<String> roleIds = userEntity.getRoleIds();
if (roleIds == null || roleIds.isEmpty()) {
@@ -31,12 +31,12 @@ public class MongoModelUtils {
DBObject query = new QueryBuilder()
.and("_id").in(roleIds)
.get();
return invContext.getMongoStore().loadEntities(RoleEntity.class, query, invContext);
return invContext.getMongoStore().loadEntities(MongoRoleEntity.class, query, invContext);
}
// Get everything including both application and realm scopes
public static List<RoleEntity> getAllScopesOfClient(ClientModel client, MongoStoreInvocationContext invContext) {
ClientEntity scopedEntity = ((ClientAdapter)client).getMongoEntity();
public static List<MongoRoleEntity> getAllScopesOfClient(ClientModel client, MongoStoreInvocationContext invContext) {
ClientEntity scopedEntity = ((ClientAdapter)client).getMongoEntityAsClient();
List<String> scopeIds = scopedEntity.getScopeIds();
if (scopeIds == null || scopeIds.isEmpty()) {
@@ -46,6 +46,6 @@ public class MongoModelUtils {
DBObject query = new QueryBuilder()
.and("_id").in(scopeIds)
.get();
return invContext.getMongoStore().loadEntities(RoleEntity.class, query, invContext);
return invContext.getMongoStore().loadEntities(MongoRoleEntity.class, query, invContext);
}
}
@@ -8,12 +8,11 @@ import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class Address implements MongoEntity {
public class Address {
private String street;
private int number;
@MongoField
public String getStreet() {
return street;
}
@@ -22,7 +21,6 @@ public class Address implements MongoEntity {
this.street = street;
}
@MongoField
public int getNumber() {
return number;
}
@@ -13,7 +13,6 @@ public class AddressWithFlats extends Address {
private List<String> flatNumbers;
@MongoField
public List<String> getFlatNumbers() {
return flatNumbers;
}
@@ -6,7 +6,6 @@ import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
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;
@@ -22,7 +21,7 @@ import java.util.List;
*/
public class MongoStoreTest {
private static final Class<? extends MongoEntity>[] MANAGED_DATA_TYPES = (Class<? extends MongoEntity>[])new Class<?>[] {
private static final Class<?>[] MANAGED_DATA_TYPES = (Class<?>[])new Class<?>[] {
Person.class,
Address.class,
AddressWithFlats.class
@@ -1,8 +1,8 @@
package org.keycloak.models.mongo.test;
import org.keycloak.models.mongo.api.AbstractMongoIdentifiableEntity;
import org.keycloak.models.mongo.api.MongoCollection;
import org.keycloak.models.mongo.api.MongoField;
import org.keycloak.models.mongo.api.MongoIdentifiableEntity;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
import java.util.HashMap;
import java.util.List;
@@ -12,8 +12,9 @@ import java.util.Map;
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@MongoCollection(collectionName = "persons")
public class Person extends AbstractMongoIdentifiableEntity {
public class Person implements MongoIdentifiableEntity {
private String id;
private String firstName;
private int age;
private List<String> kids;
@@ -23,7 +24,14 @@ public class Person extends AbstractMongoIdentifiableEntity {
private List<Gender> genders;
private Map<String, String> attributes = new HashMap<String, String>();
@MongoField
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
@@ -32,7 +40,6 @@ public class Person extends AbstractMongoIdentifiableEntity {
this.firstName = firstName;
}
@MongoField
public int getAge() {
return age;
}
@@ -41,7 +48,6 @@ public class Person extends AbstractMongoIdentifiableEntity {
this.age = age;
}
@MongoField
public Gender getGender() {
return gender;
}
@@ -50,7 +56,6 @@ public class Person extends AbstractMongoIdentifiableEntity {
this.gender = gender;
}
@MongoField
public List<Gender> getGenders() {
return genders;
}
@@ -59,7 +64,6 @@ public class Person extends AbstractMongoIdentifiableEntity {
this.genders = genders;
}
@MongoField
public List<String> getKids() {
return kids;
}
@@ -68,7 +72,6 @@ public class Person extends AbstractMongoIdentifiableEntity {
this.kids = kids;
}
@MongoField
public List<AddressWithFlats> getAddresses() {
return addresses;
}
@@ -77,7 +80,6 @@ public class Person extends AbstractMongoIdentifiableEntity {
this.addresses = addresses;
}
@MongoField
public Address getMainAddress() {
return mainAddress;
}
@@ -86,7 +88,6 @@ public class Person extends AbstractMongoIdentifiableEntity {
this.mainAddress = mainAddress;
}
@MongoField
public Map<String, String> getAttributes() {
return attributes;
}
@@ -103,6 +104,10 @@ public class Person extends AbstractMongoIdentifiableEntity {
attributes.remove(key);
}
@Override
public void afterRemove(MongoStoreInvocationContext invocationContext) {
}
public static enum Gender {
MALE, FEMALE
}