Merge pull request #510 from stianst/master

Revert JPA model provider
This commit is contained in:
Stian Thorgersen 2014-07-09 15:44:05 +01:00
commit 38abcd4a90
44 changed files with 5168 additions and 155 deletions

View file

@ -101,6 +101,19 @@
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-jpa</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-jpa</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-mongo</artifactId>

View file

@ -1,6 +1,5 @@
package org.keycloak.exportimport;
import org.junit.Ignore;
import org.keycloak.exportimport.io.directory.TmpDirExportImportIOProvider;
import org.keycloak.models.KeycloakSessionFactory;
@ -8,10 +7,7 @@ import org.keycloak.models.KeycloakSessionFactory;
* Test for full export of data from JPA and import them to Mongo. Using "directory" provider
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*
* TODO Update to work with hybrid model provider
*/
@Ignore
public class JPAToMongoExportImportTest extends ExportImportTestBase {
@Override

View file

@ -1,7 +1,6 @@
package org.keycloak.exportimport;
import org.junit.Assert;
import org.junit.Ignore;
import org.keycloak.exportimport.io.zip.EncryptedZIPIOProvider;
import org.keycloak.models.KeycloakSessionFactory;
@ -11,10 +10,7 @@ import java.io.File;
* Test for full export of data from Mongo and import them to JPA. Using export into encrypted ZIP and import from it
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*
* TODO Update to work with hybrid model provider
*/
@Ignore
public class MongoToJPAExportImportTest extends ExportImportTestBase {
private static final String zipFile = "keycloak-export.zip";

139
model/jpa/pom.xml Executable file
View file

@ -0,0 +1,139 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-beta-4-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-model-jpa</artifactId>
<name>Keycloak Model JPA</name>
<description/>
<dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.iharder</groupId>
<artifactId>base64</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-invalidation-cache-model</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.entitymanager.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-tests</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-tests</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
<!-- Test jar used in export-import -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>package-tests-jar</id>
<phase>package</phase>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>default-test</id>
<configuration>
<dependenciesToScan>
<dependency>org.keycloak:keycloak-model-tests</dependency>
</dependenciesToScan>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,268 @@
package org.keycloak.models.jpa;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.jpa.entities.*;
import org.keycloak.models.utils.KeycloakModelUtils;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ApplicationAdapter extends ClientAdapter implements ApplicationModel {
protected EntityManager em;
protected ApplicationEntity applicationEntity;
public ApplicationAdapter(RealmModel realm, EntityManager em, ApplicationEntity applicationEntity) {
super(realm, applicationEntity, em);
this.realm = realm;
this.em = em;
this.applicationEntity = applicationEntity;
}
@Override
public void updateApplication() {
em.flush();
}
@Override
public String getName() {
return entity.getName();
}
@Override
public void setName(String name) {
entity.setName(name);
}
@Override
public boolean isSurrogateAuthRequired() {
return applicationEntity.isSurrogateAuthRequired();
}
@Override
public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
applicationEntity.setSurrogateAuthRequired(surrogateAuthRequired);
}
@Override
public String getManagementUrl() {
return applicationEntity.getManagementUrl();
}
@Override
public void setManagementUrl(String url) {
applicationEntity.setManagementUrl(url);
}
@Override
public String getBaseUrl() {
return applicationEntity.getBaseUrl();
}
@Override
public void setBaseUrl(String url) {
applicationEntity.setBaseUrl(url);
}
@Override
public boolean isBearerOnly() {
return applicationEntity.isBearerOnly();
}
@Override
public void setBearerOnly(boolean only) {
applicationEntity.setBearerOnly(only);
}
@Override
public boolean isDirectGrantsOnly() {
return false; // applications can't be grant only
}
@Override
public void setDirectGrantsOnly(boolean flag) {
// applications can't be grant only
}
@Override
public RoleModel getRole(String name) {
TypedQuery<RoleEntity> query = em.createNamedQuery("getAppRoleByName", RoleEntity.class);
query.setParameter("name", name);
query.setParameter("application", entity);
List<RoleEntity> roles = query.getResultList();
if (roles.size() == 0) return null;
return new RoleAdapter(realm, em, roles.get(0));
}
@Override
public RoleModel addRole(String name) {
return this.addRole(KeycloakModelUtils.generateId(), name);
}
@Override
public RoleModel addRole(String id, String name) {
RoleEntity roleEntity = new RoleEntity();
roleEntity.setId(id);
roleEntity.setName(name);
roleEntity.setApplication(applicationEntity);
roleEntity.setApplicationRole(true);
roleEntity.setRealmId(realm.getId());
em.persist(roleEntity);
applicationEntity.getRoles().add(roleEntity);
em.flush();
return new RoleAdapter(realm, em, roleEntity);
}
@Override
public boolean removeRole(RoleModel roleModel) {
if (roleModel == null) {
return false;
}
if (!roleModel.getContainer().equals(this)) return false;
RoleEntity role = RoleAdapter.toRoleEntity(roleModel, em);
if (!role.isApplicationRole()) return false;
applicationEntity.getRoles().remove(role);
applicationEntity.getDefaultRoles().remove(role);
em.createNativeQuery("delete from CompositeRole where childRole = :role").setParameter("role", role).executeUpdate();
em.createQuery("delete from " + ScopeMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", role).executeUpdate();
em.createQuery("delete from " + UserRoleMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", role).executeUpdate();
role.setApplication(null);
em.flush();
em.remove(role);
em.flush();
return true;
}
@Override
public Set<RoleModel> getRoles() {
Set<RoleModel> list = new HashSet<RoleModel>();
Collection<RoleEntity> roles = applicationEntity.getRoles();
if (roles == null) return list;
for (RoleEntity entity : roles) {
list.add(new RoleAdapter(realm, em, entity));
}
return list;
}
@Override
public Set<RoleModel> getApplicationScopeMappings(ClientModel client) {
Set<RoleModel> roleMappings = client.getScopeMappings();
Set<RoleModel> appRoles = new HashSet<RoleModel>();
for (RoleModel role : roleMappings) {
RoleContainerModel container = role.getContainer();
if (container instanceof RealmModel) {
} else {
ApplicationModel app = (ApplicationModel)container;
if (app.getId().equals(getId())) {
appRoles.add(role);
}
}
}
return appRoles;
}
@Override
public List<String> getDefaultRoles() {
Collection<RoleEntity> entities = applicationEntity.getDefaultRoles();
List<String> roles = new ArrayList<String>();
if (entities == null) return roles;
for (RoleEntity entity : entities) {
roles.add(entity.getName());
}
return roles;
}
@Override
public void addDefaultRole(String name) {
RoleModel role = getRole(name);
if (role == null) {
role = addRole(name);
}
Collection<RoleEntity> entities = applicationEntity.getDefaultRoles();
for (RoleEntity entity : entities) {
if (entity.getId().equals(role.getId())) {
return;
}
}
RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
entities.add(roleEntity);
em.flush();
}
public static boolean contains(String str, String[] array) {
for (String s : array) {
if (str.equals(s)) return true;
}
return false;
}
@Override
public void updateDefaultRoles(String[] defaultRoles) {
Collection<RoleEntity> entities = applicationEntity.getDefaultRoles();
Set<String> already = new HashSet<String>();
List<RoleEntity> remove = new ArrayList<RoleEntity>();
for (RoleEntity rel : entities) {
if (!contains(rel.getName(), defaultRoles)) {
remove.add(rel);
} else {
already.add(rel.getName());
}
}
for (RoleEntity entity : remove) {
entities.remove(entity);
}
em.flush();
for (String roleName : defaultRoles) {
if (!already.contains(roleName)) {
addDefaultRole(roleName);
}
}
em.flush();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || !(o instanceof ApplicationModel)) return false;
ApplicationModel that = (ApplicationModel) o;
return that.getId().equals(getId());
}
@Override
public int hashCode() {
return getId().hashCode();
}
public String toString() {
return getName();
}
ApplicationEntity getJpaEntity() {
return applicationEntity;
}
}

View file

@ -0,0 +1,268 @@
package org.keycloak.models.jpa;
import org.keycloak.models.ClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.jpa.entities.ClientEntity;
import org.keycloak.models.jpa.entities.ClientUserSessionAssociationEntity;
import org.keycloak.models.jpa.entities.RoleEntity;
import org.keycloak.models.jpa.entities.ScopeMappingEntity;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public abstract class ClientAdapter implements ClientModel {
protected ClientEntity entity;
protected RealmModel realm;
protected EntityManager em;
public ClientAdapter(RealmModel realm, ClientEntity entity, EntityManager em) {
this.realm = realm;
this.entity = entity;
this.em = em;
}
public ClientEntity getEntity() {
return entity;
}
@Override
public String getId() {
return entity.getId();
}
@Override
public RealmModel getRealm() {
return realm;
}
@Override
public String getClientId() {
return entity.getName();
}
@Override
public boolean isEnabled() {
return entity.isEnabled();
}
@Override
public void setEnabled(boolean enabled) {
entity.setEnabled(enabled);
}
@Override
public long getAllowedClaimsMask() {
return entity.getAllowedClaimsMask();
}
@Override
public void setAllowedClaimsMask(long mask) {
entity.setAllowedClaimsMask(mask);
}
@Override
public boolean isPublicClient() {
return entity.isPublicClient();
}
@Override
public void setPublicClient(boolean flag) {
entity.setPublicClient(flag);
}
@Override
public Set<String> getWebOrigins() {
Set<String> result = new HashSet<String>();
result.addAll(entity.getWebOrigins());
return result;
}
@Override
public void setWebOrigins(Set<String> webOrigins) {
entity.setWebOrigins(webOrigins);
}
@Override
public void addWebOrigin(String webOrigin) {
entity.getWebOrigins().add(webOrigin);
}
@Override
public void removeWebOrigin(String webOrigin) {
entity.getWebOrigins().remove(webOrigin);
}
@Override
public Set<String> getRedirectUris() {
Set<String> result = new HashSet<String>();
result.addAll(entity.getRedirectUris());
return result;
}
@Override
public void setRedirectUris(Set<String> redirectUris) {
entity.setRedirectUris(redirectUris);
}
@Override
public void addRedirectUri(String redirectUri) {
entity.getRedirectUris().add(redirectUri);
}
@Override
public void removeRedirectUri(String redirectUri) {
entity.getRedirectUris().remove(redirectUri);
}
@Override
public String getSecret() {
return entity.getSecret();
}
@Override
public void setSecret(String secret) {
entity.setSecret(secret);
}
@Override
public boolean validateSecret(String secret) {
return secret.equals(entity.getSecret());
}
@Override
public int getNotBefore() {
return entity.getNotBefore();
}
@Override
public void setNotBefore(int notBefore) {
entity.setNotBefore(notBefore);
}
@Override
public int getActiveUserSessions() {
Query query = em.createNamedQuery("getActiveClientSessions");
query.setParameter("clientId", getId());
Object count = query.getSingleResult();
return ((Number)count).intValue();
}
@Override
public Set<UserSessionModel> getUserSessions() {
Set<UserSessionModel> list = new HashSet<UserSessionModel>();
TypedQuery<ClientUserSessionAssociationEntity> query = em.createNamedQuery("getClientUserSessionByClient", ClientUserSessionAssociationEntity.class);
String id = getId();
query.setParameter("clientId", id);
List<ClientUserSessionAssociationEntity> results = query.getResultList();
for (ClientUserSessionAssociationEntity entity : results) {
list.add(new UserSessionAdapter(em, realm, entity.getSession()));
}
return list;
}
public void deleteUserSessionAssociation() {
em.createNamedQuery("removeClientUserSessionByClient").setParameter("clientId", getId()).executeUpdate();
}
@Override
public Set<RoleModel> getRealmScopeMappings() {
Set<RoleModel> roleMappings = getScopeMappings();
Set<RoleModel> appRoles = new HashSet<RoleModel>();
for (RoleModel role : roleMappings) {
RoleContainerModel container = role.getContainer();
if (container instanceof RealmModel) {
if (((RealmModel) container).getId().equals(realm.getId())) {
appRoles.add(role);
}
}
}
return appRoles;
}
@Override
public Set<RoleModel> getScopeMappings() {
TypedQuery<String> query = em.createNamedQuery("clientScopeMappingIds", String.class);
query.setParameter("client", getEntity());
List<String> ids = query.getResultList();
Set<RoleModel> roles = new HashSet<RoleModel>();
for (String roleId : ids) {
RoleModel role = realm.getRoleById(roleId);
if (role == null) continue;
roles.add(role);
}
return roles;
}
@Override
public void addScopeMapping(RoleModel role) {
if (hasScope(role)) return;
ScopeMappingEntity entity = new ScopeMappingEntity();
entity.setClient(getEntity());
RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
entity.setRole(roleEntity);
em.persist(entity);
em.flush();
em.detach(entity);
}
@Override
public void deleteScopeMapping(RoleModel role) {
TypedQuery<ScopeMappingEntity> query = getRealmScopeMappingQuery(role);
List<ScopeMappingEntity> results = query.getResultList();
if (results.size() == 0) return;
for (ScopeMappingEntity entity : results) {
em.remove(entity);
}
}
protected TypedQuery<ScopeMappingEntity> getRealmScopeMappingQuery(RoleModel role) {
TypedQuery<ScopeMappingEntity> query = em.createNamedQuery("hasScope", ScopeMappingEntity.class);
query.setParameter("client", getEntity());
RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
query.setParameter("role", roleEntity);
return query;
}
@Override
public boolean hasScope(RoleModel role) {
Set<RoleModel> roles = getScopeMappings();
if (roles.contains(role)) return true;
for (RoleModel mapping : roles) {
if (mapping.hasRole(role)) return true;
}
return false;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!this.getClass().equals(o.getClass())) return false;
ClientAdapter that = (ClientAdapter) o;
return that.getId().equals(getId());
}
@Override
public int hashCode() {
return entity.getId().hashCode();
}
}

View file

@ -0,0 +1,53 @@
package org.keycloak.models.jpa;
import org.keycloak.models.KeycloakTransaction;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceException;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class JpaKeycloakTransaction implements KeycloakTransaction {
protected EntityManager em;
public JpaKeycloakTransaction(EntityManager em) {
this.em = em;
}
@Override
public void begin() {
em.getTransaction().begin();
}
@Override
public void commit() {
try {
em.getTransaction().commit();
} catch (PersistenceException e) {
throw PersistenceExceptionConverter.convert(e.getCause() != null ? e.getCause() : e);
}
}
@Override
public void rollback() {
em.getTransaction().rollback();
}
@Override
public void setRollbackOnly() {
em.getTransaction().setRollbackOnly();
}
@Override
public boolean getRollbackOnly() {
return em.getTransaction().getRollbackOnly();
}
@Override
public boolean isActive() {
return em.getTransaction().isActive();
}
}

View file

@ -0,0 +1,400 @@
package org.keycloak.models.jpa;
import org.keycloak.models.*;
import org.keycloak.models.jpa.entities.*;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.util.Time;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class JpaModelProvider implements ModelProvider {
private final KeycloakSession session;
protected EntityManager em;
public JpaModelProvider(KeycloakSession session, EntityManager em) {
this.session = session;
this.em = em;
this.em = PersistenceExceptionConverter.create(em);
}
@Override
public KeycloakTransaction getTransaction() {
return new JpaKeycloakTransaction(em);
}
@Override
public RealmModel createRealm(String name) {
return createRealm(KeycloakModelUtils.generateId(), name);
}
@Override
public RealmModel createRealm(String id, String name) {
RealmEntity realm = new RealmEntity();
realm.setName(name);
realm.setId(id);
em.persist(realm);
em.flush();
return new RealmAdapter(session, em, realm);
}
@Override
public RealmModel getRealm(String id) {
RealmEntity realm = em.find(RealmEntity.class, id);
if (realm == null) return null;
return new RealmAdapter(session, em, realm);
}
@Override
public List<RealmModel> getRealms() {
TypedQuery<RealmEntity> query = em.createNamedQuery("getAllRealms", RealmEntity.class);
List<RealmEntity> entities = query.getResultList();
List<RealmModel> realms = new ArrayList<RealmModel>();
for (RealmEntity entity : entities) {
realms.add(new RealmAdapter(session, em, entity));
}
return realms;
}
@Override
public RealmModel getRealmByName(String name) {
TypedQuery<RealmEntity> query = em.createNamedQuery("getRealmByName", RealmEntity.class);
query.setParameter("name", name);
List<RealmEntity> entities = query.getResultList();
if (entities.size() == 0) return null;
if (entities.size() > 1) throw new IllegalStateException("Should not be more than one realm with same name");
RealmEntity realm = query.getResultList().get(0);
if (realm == null) return null;
return new RealmAdapter(session, em, realm);
}
@Override
public UserModel getUserById(String id, RealmModel realmModel) {
TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserById", UserEntity.class);
query.setParameter("id", id);
RealmEntity realm = em.getReference(RealmEntity.class, realmModel.getId());
query.setParameter("realm", realm);
List<UserEntity> entities = query.getResultList();
if (entities.size() == 0) return null;
return new UserAdapter(realmModel, em, entities.get(0));
}
@Override
public UserModel getUserByUsername(String username, RealmModel realmModel) {
TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserByUsername", UserEntity.class);
query.setParameter("username", username);
RealmEntity realm = em.getReference(RealmEntity.class, realmModel.getId());
query.setParameter("realm", realm);
List<UserEntity> results = query.getResultList();
if (results.size() == 0) return null;
return new UserAdapter(realmModel, em, results.get(0));
}
@Override
public UserModel getUserByEmail(String email, RealmModel realmModel) {
TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserByEmail", UserEntity.class);
query.setParameter("email", email);
RealmEntity realm = em.getReference(RealmEntity.class, realmModel.getId());
query.setParameter("realm", realm);
List<UserEntity> results = query.getResultList();
return results.isEmpty() ? null : new UserAdapter(realmModel, em, results.get(0));
}
@Override
public boolean removeRealm(String id) {
RealmEntity realm = em.find(RealmEntity.class, id);
if (realm == null) {
return false;
}
RealmAdapter adapter = new RealmAdapter(session, em, realm);
adapter.removeUserSessions();
for (ApplicationEntity a : new LinkedList<ApplicationEntity>(realm.getApplications())) {
adapter.removeApplication(a.getId());
}
for (OAuthClientModel oauth : adapter.getOAuthClients()) {
adapter.removeOAuthClient(oauth.getId());
}
for (UserEntity u : em.createQuery("from UserEntity u where u.realm = :realm", UserEntity.class).setParameter("realm", realm).getResultList()) {
adapter.removeUser(u.getUsername());
}
em.remove(realm);
return true;
}
@Override
public void close() {
if (em.getTransaction().isActive()) em.getTransaction().rollback();
if (em.isOpen()) em.close();
}
@Override
public void removeAllData() {
// Should be sufficient to delete all realms. Rest data should be removed in cascade
List<RealmModel> realms = getRealms();
for (RealmModel realm : realms) {
removeRealm(realm.getId());
}
}
@Override
public UserModel getUserBySocialLink(SocialLinkModel socialLink, RealmModel realm) {
TypedQuery<UserEntity> query = em.createNamedQuery("findUserByLinkAndRealm", UserEntity.class);
RealmEntity realmEntity = em.getReference(RealmEntity.class, realm.getId());
query.setParameter("realm", realmEntity);
query.setParameter("socialProvider", socialLink.getSocialProvider());
query.setParameter("socialUserId", socialLink.getSocialUserId());
List<UserEntity> results = query.getResultList();
if (results.isEmpty()) {
return null;
} else if (results.size() > 1) {
throw new IllegalStateException("More results found for socialProvider=" + socialLink.getSocialProvider() +
", socialUserId=" + socialLink.getSocialUserId() + ", results=" + results);
} else {
UserEntity user = results.get(0);
return new UserAdapter(realm, em, user);
}
}
@Override
public List<UserModel> getUsers(RealmModel realm) {
TypedQuery<UserEntity> query = em.createQuery("select u from UserEntity u where u.realm = :realm", UserEntity.class);
RealmEntity realmEntity = em.getReference(RealmEntity.class, realm.getId());
query.setParameter("realm", realmEntity);
List<UserEntity> results = query.getResultList();
List<UserModel> users = new ArrayList<UserModel>();
for (UserEntity entity : results) users.add(new UserAdapter(realm, em, entity));
return users;
}
@Override
public List<UserModel> searchForUser(String search, RealmModel realm) {
TypedQuery<UserEntity> query = em.createQuery("select u from UserEntity u where u.realm = :realm and ( lower(u.username) like :search or lower(concat(u.firstName, ' ', u.lastName)) like :search or u.email like :search )", UserEntity.class);
RealmEntity realmEntity = em.getReference(RealmEntity.class, realm.getId());
query.setParameter("realm", realmEntity);
query.setParameter("search", "%" + search.toLowerCase() + "%");
List<UserEntity> results = query.getResultList();
List<UserModel> users = new ArrayList<UserModel>();
for (UserEntity entity : results) users.add(new UserAdapter(realm, em, entity));
return users;
}
@Override
public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm) {
StringBuilder builder = new StringBuilder("select u from UserEntity u");
boolean first = true;
for (Map.Entry<String, String> entry : attributes.entrySet()) {
String attribute = null;
if (entry.getKey().equals(UserModel.LOGIN_NAME)) {
attribute = "lower(username)";
} else if (entry.getKey().equalsIgnoreCase(UserModel.FIRST_NAME)) {
attribute = "lower(firstName)";
} else if (entry.getKey().equalsIgnoreCase(UserModel.LAST_NAME)) {
attribute = "lower(lastName)";
} else if (entry.getKey().equalsIgnoreCase(UserModel.EMAIL)) {
attribute = "lower(email)";
}
if (attribute == null) continue;
if (first) {
first = false;
builder.append(" where realm = :realm");
} else {
builder.append(" and ");
}
builder.append(attribute).append(" like '%").append(entry.getValue().toLowerCase()).append("%'");
}
String q = builder.toString();
TypedQuery<UserEntity> query = em.createQuery(q, UserEntity.class);
RealmEntity realmEntity = em.getReference(RealmEntity.class, realm.getId());
query.setParameter("realm", realmEntity);
List<UserEntity> results = query.getResultList();
List<UserModel> users = new ArrayList<UserModel>();
for (UserEntity entity : results) users.add(new UserAdapter(realm, em, entity));
return users;
}
private SocialLinkEntity findSocialLink(UserModel user, String socialProvider) {
TypedQuery<SocialLinkEntity> query = em.createNamedQuery("findSocialLinkByUserAndProvider", SocialLinkEntity.class);
UserEntity userEntity = em.getReference(UserEntity.class, user.getId());
query.setParameter("user", userEntity);
query.setParameter("socialProvider", socialProvider);
List<SocialLinkEntity> results = query.getResultList();
return results.size() > 0 ? results.get(0) : null;
}
@Override
public Set<SocialLinkModel> getSocialLinks(UserModel user, RealmModel realm) {
TypedQuery<SocialLinkEntity> query = em.createNamedQuery("findSocialLinkByUser", SocialLinkEntity.class);
UserEntity userEntity = em.getReference(UserEntity.class, user.getId());
query.setParameter("user", userEntity);
List<SocialLinkEntity> results = query.getResultList();
Set<SocialLinkModel> set = new HashSet<SocialLinkModel>();
for (SocialLinkEntity entity : results) {
set.add(new SocialLinkModel(entity.getSocialProvider(), entity.getSocialUserId(), entity.getSocialUsername()));
}
return set;
}
@Override
public SocialLinkModel getSocialLink(UserModel user, String socialProvider, RealmModel realm) {
SocialLinkEntity entity = findSocialLink(user, socialProvider);
return (entity != null) ? new SocialLinkModel(entity.getSocialProvider(), entity.getSocialUserId(), entity.getSocialUsername()) : null;
}
@Override
public RoleModel getRoleById(String id, RealmModel realm) {
RoleEntity entity = em.find(RoleEntity.class, id);
if (entity == null) return null;
if (!realm.getId().equals(entity.getRealmId())) return null;
return new RoleAdapter(realm, em, entity);
}
@Override
public ApplicationModel getApplicationById(String id, RealmModel realm) {
ApplicationEntity app = em.find(ApplicationEntity.class, id);
// Check if application belongs to this realm
if (app == null || !realm.getId().equals(app.getRealm().getId())) return null;
return new ApplicationAdapter(realm, em, app);
}
@Override
public OAuthClientModel getOAuthClientById(String id, RealmModel realm) {
OAuthClientEntity client = em.find(OAuthClientEntity.class, id);
// Check if client belongs to this realm
if (client == null || !realm.getId().equals(client.getRealm().getId())) return null;
return new OAuthClientAdapter(realm, client, em);
}
@Override
public UsernameLoginFailureModel getUserLoginFailure(String username, RealmModel realm) {
String id = username + "-" + realm.getId();
UsernameLoginFailureEntity entity = em.find(UsernameLoginFailureEntity.class, id);
if (entity == null) return null;
return new UsernameLoginFailureAdapter(entity);
}
@Override
public UsernameLoginFailureModel addUserLoginFailure(String username, RealmModel realm) {
UsernameLoginFailureModel model = getUserLoginFailure(username, realm);
if (model != null) return model;
String id = username + "-" + realm.getId();
UsernameLoginFailureEntity entity = new UsernameLoginFailureEntity();
entity.setId(id);
entity.setUsername(username);
RealmEntity realmEntity = em.getReference(RealmEntity.class, realm.getId());
entity.setRealm(realmEntity);
em.persist(entity);
return new UsernameLoginFailureAdapter(entity);
}
@Override
public List<UsernameLoginFailureModel> getAllUserLoginFailures(RealmModel realm) {
TypedQuery<UsernameLoginFailureEntity> query = em.createNamedQuery("getAllFailures", UsernameLoginFailureEntity.class);
List<UsernameLoginFailureEntity> entities = query.getResultList();
List<UsernameLoginFailureModel> models = new ArrayList<UsernameLoginFailureModel>();
for (UsernameLoginFailureEntity entity : entities) {
models.add(new UsernameLoginFailureAdapter(entity));
}
return models;
}
@Override
public UserSessionModel createUserSession(RealmModel realm, UserModel user, String ipAddress) {
UserSessionEntity entity = new UserSessionEntity();
entity.setRealmId(realm.getId());
entity.setUserId(user.getId());
entity.setIpAddress(ipAddress);
int currentTime = Time.currentTime();
entity.setStarted(currentTime);
entity.setLastSessionRefresh(currentTime);
em.persist(entity);
return new UserSessionAdapter(em, realm, entity);
}
@Override
public UserSessionModel getUserSession(String id, RealmModel realm) {
UserSessionEntity entity = em.find(UserSessionEntity.class, id);
return entity != null ? new UserSessionAdapter(em, realm, entity) : null;
}
@Override
public List<UserSessionModel> getUserSessions(UserModel user, RealmModel realm) {
List<UserSessionModel> sessions = new LinkedList<UserSessionModel>();
for (UserSessionEntity e : em.createNamedQuery("getUserSessionByUser", UserSessionEntity.class)
.setParameter("userId", user.getId()).getResultList()) {
sessions.add(new UserSessionAdapter(em, realm, e));
}
return sessions;
}
@Override
public Set<UserSessionModel> getUserSessions(RealmModel realm, ClientModel client) {
Set<UserSessionModel> list = new HashSet<UserSessionModel>();
TypedQuery<ClientUserSessionAssociationEntity> query = em.createNamedQuery("getClientUserSessionByClient", ClientUserSessionAssociationEntity.class);
String id = client.getId();
query.setParameter("clientId", id);
List<ClientUserSessionAssociationEntity> results = query.getResultList();
for (ClientUserSessionAssociationEntity entity : results) {
list.add(new UserSessionAdapter(em, realm, entity.getSession()));
}
return list;
}
@Override
public int getActiveUserSessions(RealmModel realm, ClientModel client) {
Query query = em.createNamedQuery("getActiveClientSessions");
query.setParameter("clientId", client.getId());
Object count = query.getSingleResult();
return ((Number)count).intValue();
}
@Override
public void removeUserSession(UserSessionModel session) {
em.remove(((UserSessionAdapter) session).getEntity());
}
@Override
public void removeUserSessions(RealmModel realm, UserModel user) {
em.createNamedQuery("removeClientUserSessionByUser").setParameter("userId", user.getId()).executeUpdate();
em.createNamedQuery("removeUserSessionByUser").setParameter("userId", user.getId()).executeUpdate();
}
@Override
public void removeExpiredUserSessions(RealmModel realm) {
TypedQuery<UserSessionEntity> query = em.createNamedQuery("getUserSessionExpired", UserSessionEntity.class)
.setParameter("maxTime", Time.currentTime() - realm.getSsoSessionMaxLifespan())
.setParameter("idleTime", Time.currentTime() - realm.getSsoSessionIdleTimeout());
List<UserSessionEntity> results = query.getResultList();
for (UserSessionEntity entity : results) {
em.remove(entity);
}
}
@Override
public void removeUserSessions(RealmModel realm) {
em.createNamedQuery("removeClientUserSessionByRealm").setParameter("realmId", realm.getId()).executeUpdate();
em.createNamedQuery("removeRealmUserSessions").setParameter("realmId", realm.getId()).executeUpdate();
}
}

View file

@ -0,0 +1,40 @@
package org.keycloak.models.jpa;
import org.keycloak.Config;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelProvider;
import org.keycloak.models.ModelProviderFactory;
import org.keycloak.util.JpaUtils;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class JpaModelProviderFactory implements ModelProviderFactory {
protected EntityManagerFactory emf;
@Override
public void init(Config.Scope config) {
emf = Persistence.createEntityManagerFactory("jpa-keycloak-identity-store", JpaUtils.getHibernateProperties());
}
@Override
public String getId() {
return "jpa";
}
@Override
public ModelProvider create(KeycloakSession session) {
return new JpaModelProvider(session, emf.createEntityManager());
}
@Override
public void close() {
emf.close();
}
}

View file

@ -0,0 +1,56 @@
package org.keycloak.models.jpa;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.OAuthClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.jpa.entities.OAuthClientEntity;
import javax.persistence.EntityManager;
import java.util.HashSet;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class OAuthClientAdapter extends ClientAdapter implements OAuthClientModel {
protected final OAuthClientEntity oAuthClientEntity;
public OAuthClientAdapter(RealmModel realm, OAuthClientEntity entity, EntityManager em) {
super(realm, entity, em);
oAuthClientEntity = entity;
}
@Override
public void setClientId(String id) {
entity.setName(id);
}
@Override
public boolean isDirectGrantsOnly() {
return oAuthClientEntity.isDirectGrantsOnly();
}
@Override
public void setDirectGrantsOnly(boolean flag) {
oAuthClientEntity.setDirectGrantsOnly(flag);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || !(o instanceof OAuthClientModel)) return false;
OAuthClientModel that = (OAuthClientModel) o;
return that.getId().equals(getId());
}
@Override
public int hashCode() {
return getId().hashCode();
}
}

View file

@ -0,0 +1,49 @@
package org.keycloak.models.jpa;
import org.hibernate.exception.ConstraintViolationException;
import org.keycloak.models.ModelException;
import org.keycloak.models.ModelDuplicateException;
import javax.persistence.EntityExistsException;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class PersistenceExceptionConverter implements InvocationHandler {
private EntityManager em;
public static EntityManager create(EntityManager em) {
return (EntityManager) Proxy.newProxyInstance(EntityManager.class.getClassLoader(), new Class[]{EntityManager.class}, new PersistenceExceptionConverter(em));
}
private PersistenceExceptionConverter(EntityManager em) {
this.em = em;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
return method.invoke(em, args);
} catch (InvocationTargetException e) {
throw convert(e.getCause());
}
}
public static ModelException convert(Throwable t) {
if (t.getCause() != null && t.getCause() instanceof ConstraintViolationException) {
throw new ModelDuplicateException(t);
} if (t instanceof EntityExistsException) {
throw new ModelDuplicateException(t);
} else {
throw new ModelException(t);
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,135 @@
package org.keycloak.models.jpa;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.jpa.entities.RoleEntity;
import org.keycloak.models.utils.KeycloakModelUtils;
import javax.persistence.EntityManager;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class RoleAdapter implements RoleModel {
protected RoleEntity role;
protected EntityManager em;
protected RealmModel realm;
public RoleAdapter(RealmModel realm, EntityManager em, RoleEntity role) {
this.em = em;
this.realm = realm;
this.role = role;
}
public RoleEntity getRole() {
return role;
}
public void setRole(RoleEntity role) {
this.role = role;
}
@Override
public String getName() {
return role.getName();
}
@Override
public String getDescription() {
return role.getDescription();
}
@Override
public void setDescription(String description) {
role.setDescription(description);
}
@Override
public String getId() {
return role.getId();
}
@Override
public void setName(String name) {
role.setName(name);
}
@Override
public boolean isComposite() {
return getComposites().size() > 0;
}
@Override
public void addCompositeRole(RoleModel role) {
RoleEntity entity = RoleAdapter.toRoleEntity(role, em);
for (RoleEntity composite : getRole().getCompositeRoles()) {
if (composite.equals(entity)) return;
}
getRole().getCompositeRoles().add(entity);
em.flush();
}
@Override
public void removeCompositeRole(RoleModel role) {
RoleEntity entity = RoleAdapter.toRoleEntity(role, em);
Iterator<RoleEntity> it = getRole().getCompositeRoles().iterator();
while (it.hasNext()) {
if (it.next().equals(entity)) it.remove();
}
}
@Override
public Set<RoleModel> getComposites() {
Set<RoleModel> set = new HashSet<RoleModel>();
for (RoleEntity composite : getRole().getCompositeRoles()) {
set.add(new RoleAdapter(realm, em, composite));
}
return set;
}
@Override
public boolean hasRole(RoleModel role) {
if (this.equals(role)) return true;
if (!isComposite()) return false;
Set<RoleModel> visited = new HashSet<RoleModel>();
return KeycloakModelUtils.searchFor(role, this, visited);
}
@Override
public RoleContainerModel getContainer() {
if (role.isApplicationRole()) {
return realm.getApplicationById(role.getApplication().getId());
} else {
return realm;
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || !(o instanceof RoleModel)) return false;
RoleModel that = (RoleModel) o;
return that.getId().equals(getId());
}
@Override
public int hashCode() {
return getId().hashCode();
}
public static RoleEntity toRoleEntity(RoleModel model, EntityManager em) {
if (model instanceof RoleAdapter) {
return ((RoleAdapter)model).getRole();
}
return em.getReference(RoleEntity.class, model.getId());
}
}

View file

@ -0,0 +1,384 @@
package org.keycloak.models.jpa;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.AuthenticationLinkModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.PasswordPolicy;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserCredentialValueModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.jpa.entities.AuthenticationLinkEntity;
import org.keycloak.models.jpa.entities.CredentialEntity;
import org.keycloak.models.jpa.entities.RoleEntity;
import org.keycloak.models.jpa.entities.UserEntity;
import org.keycloak.models.jpa.entities.UserRoleMappingEntity;
import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.keycloak.models.utils.Pbkdf2PasswordEncoder.getSalt;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UserAdapter implements UserModel {
protected UserEntity user;
protected EntityManager em;
protected RealmModel realm;
public UserAdapter(RealmModel realm, EntityManager em, UserEntity user) {
this.em = em;
this.user = user;
this.realm = realm;
}
public UserEntity getUser() {
return user;
}
@Override
public String getId() {
return user.getId();
}
@Override
public String getUsername() {
return user.getUsername();
}
@Override
public void setUsername(String username) {
user.setUsername(username);
}
@Override
public boolean isEnabled() {
return user.isEnabled();
}
@Override
public boolean isTotp() {
return user.isTotp();
}
@Override
public void setEnabled(boolean enabled) {
user.setEnabled(enabled);
}
@Override
public void setAttribute(String name, String value) {
Map<String, String> attributes = user.getAttributes();
if (attributes == null) {
attributes = new HashMap<String, String>();
}
attributes.put(name, value);
user.setAttributes(attributes);
}
@Override
public void removeAttribute(String name) {
Map<String, String> attributes = user.getAttributes();
if (attributes == null) {
attributes = new HashMap<String, String>();
}
attributes.remove(name);
user.setAttributes(attributes);
}
@Override
public String getAttribute(String name) {
if (user.getAttributes() == null) return null;
return user.getAttributes().get(name);
}
@Override
public Map<String, String> getAttributes() {
Map<String, String> result = new HashMap<String, String>();
result.putAll(user.getAttributes());
return result;
}
@Override
public Set<RequiredAction> getRequiredActions() {
Set<RequiredAction> result = new HashSet<RequiredAction>();
result.addAll(user.getRequiredActions());
return result;
}
@Override
public void addRequiredAction(RequiredAction action) {
user.getRequiredActions().add(action);
}
@Override
public void removeRequiredAction(RequiredAction action) {
user.getRequiredActions().remove(action);
}
@Override
public String getFirstName() {
return user.getFirstName();
}
@Override
public void setFirstName(String firstName) {
user.setFirstName(firstName);
}
@Override
public String getLastName() {
return user.getLastName();
}
@Override
public void setLastName(String lastName) {
user.setLastName(lastName);
}
@Override
public String getEmail() {
return user.getEmail();
}
@Override
public void setEmail(String email) {
user.setEmail(email);
}
@Override
public boolean isEmailVerified() {
return user.isEmailVerified();
}
@Override
public void setEmailVerified(boolean verified) {
user.setEmailVerified(verified);
}
@Override
public void setTotp(boolean totp) {
user.setTotp(totp);
}
@Override
public void updateCredential(UserCredentialModel cred) {
CredentialEntity credentialEntity = getCredentialEntity(user, cred.getType());
if (credentialEntity == null) {
credentialEntity = new CredentialEntity();
credentialEntity.setType(cred.getType());
credentialEntity.setDevice(cred.getDevice());
credentialEntity.setUser(user);
em.persist(credentialEntity);
user.getCredentials().add(credentialEntity);
}
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
byte[] salt = getSalt();
int hashIterations = 1;
PasswordPolicy policy = realm.getPasswordPolicy();
if (policy != null) {
hashIterations = policy.getHashIterations();
if (hashIterations == -1) hashIterations = 1;
}
credentialEntity.setValue(new Pbkdf2PasswordEncoder(salt).encode(cred.getValue(), hashIterations));
credentialEntity.setSalt(salt);
credentialEntity.setHashIterations(hashIterations);
} else {
credentialEntity.setValue(cred.getValue());
}
credentialEntity.setDevice(cred.getDevice());
em.flush();
}
private CredentialEntity getCredentialEntity(UserEntity userEntity, String credType) {
for (CredentialEntity entity : userEntity.getCredentials()) {
if (entity.getType().equals(credType)) {
return entity;
}
}
return null;
}
@Override
public List<UserCredentialValueModel> getCredentialsDirectly() {
List<CredentialEntity> credentials = new ArrayList<CredentialEntity>(user.getCredentials());
List<UserCredentialValueModel> result = new ArrayList<UserCredentialValueModel>();
if (credentials != null) {
for (CredentialEntity credEntity : credentials) {
UserCredentialValueModel credModel = new UserCredentialValueModel();
credModel.setType(credEntity.getType());
credModel.setDevice(credEntity.getDevice());
credModel.setValue(credEntity.getValue());
credModel.setSalt(credEntity.getSalt());
credModel.setHashIterations(credEntity.getHashIterations());
result.add(credModel);
}
}
return result;
}
@Override
public void updateCredentialDirectly(UserCredentialValueModel credModel) {
CredentialEntity credentialEntity = getCredentialEntity(user, credModel.getType());
if (credentialEntity == null) {
credentialEntity = new CredentialEntity();
credentialEntity.setType(credModel.getType());
credentialEntity.setUser(user);
em.persist(credentialEntity);
user.getCredentials().add(credentialEntity);
}
credentialEntity.setValue(credModel.getValue());
credentialEntity.setSalt(credModel.getSalt());
credentialEntity.setDevice(credModel.getDevice());
credentialEntity.setHashIterations(credModel.getHashIterations());
em.flush();
}
@Override
public boolean hasRole(RoleModel role) {
Set<RoleModel> roles = getRoleMappings();
if (roles.contains(role)) return true;
for (RoleModel mapping : roles) {
if (mapping.hasRole(role)) return true;
}
return false;
}
protected TypedQuery<UserRoleMappingEntity> getUserRoleMappingEntityTypedQuery(RoleModel role) {
TypedQuery<UserRoleMappingEntity> query = em.createNamedQuery("userHasRole", UserRoleMappingEntity.class);
query.setParameter("user", getUser());
RoleEntity roleEntity = em.getReference(RoleEntity.class, role.getId());
query.setParameter("role", roleEntity);
return query;
}
@Override
public void grantRole(RoleModel role) {
if (hasRole(role)) return;
UserRoleMappingEntity entity = new UserRoleMappingEntity();
entity.setUser(getUser());
RoleEntity roleEntity = em.getReference(RoleEntity.class, role.getId());
entity.setRole(roleEntity);
em.persist(entity);
em.flush();
em.detach(entity);
}
@Override
public Set<RoleModel> getRealmRoleMappings() {
Set<RoleModel> roleMappings = getRoleMappings();
Set<RoleModel> realmRoles = new HashSet<RoleModel>();
for (RoleModel role : roleMappings) {
RoleContainerModel container = role.getContainer();
if (container instanceof RealmModel) {
realmRoles.add(role);
}
}
return realmRoles;
}
@Override
public Set<RoleModel> getRoleMappings() {
// we query ids only as the role might be cached and following the @ManyToOne will result in a load
// even if we're getting just the id.
TypedQuery<String> query = em.createNamedQuery("userRoleMappingIds", String.class);
query.setParameter("user", getUser());
List<String> ids = query.getResultList();
Set<RoleModel> roles = new HashSet<RoleModel>();
for (String roleId : ids) {
RoleModel roleById = realm.getRoleById(roleId);
if (roleById == null) continue;
roles.add(roleById);
}
return roles;
}
@Override
public void deleteRoleMapping(RoleModel role) {
if (user == null || role == null) return;
TypedQuery<UserRoleMappingEntity> query = getUserRoleMappingEntityTypedQuery(role);
List<UserRoleMappingEntity> results = query.getResultList();
if (results.size() == 0) return;
for (UserRoleMappingEntity entity : results) {
em.remove(entity);
}
em.flush();
}
@Override
public Set<RoleModel> getApplicationRoleMappings(ApplicationModel app) {
Set<RoleModel> roleMappings = getRoleMappings();
Set<RoleModel> roles = new HashSet<RoleModel>();
for (RoleModel role : roleMappings) {
RoleContainerModel container = role.getContainer();
if (container instanceof ApplicationModel) {
ApplicationModel appModel = (ApplicationModel)container;
if (appModel.getId().equals(app.getId())) {
roles.add(role);
}
}
}
return roles;
}
@Override
public AuthenticationLinkModel getAuthenticationLink() {
AuthenticationLinkEntity authLinkEntity = user.getAuthenticationLink();
return authLinkEntity == null ? null : new AuthenticationLinkModel(authLinkEntity.getAuthProvider(), authLinkEntity.getAuthUserId());
}
@Override
public void setAuthenticationLink(AuthenticationLinkModel authenticationLink) {
AuthenticationLinkEntity entity = new AuthenticationLinkEntity();
entity.setAuthProvider(authenticationLink.getAuthProvider());
entity.setAuthUserId(authenticationLink.getAuthUserId());
user.setAuthenticationLink(entity);
em.persist(entity);
em.persist(user);
em.flush();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || !(o instanceof UserModel)) return false;
UserModel that = (UserModel) o;
return that.getId().equals(getId());
}
@Override
public int hashCode() {
return getId().hashCode();
}
}

View file

@ -0,0 +1,130 @@
package org.keycloak.models.jpa;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ModelException;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.jpa.entities.ClientUserSessionAssociationEntity;
import org.keycloak.models.jpa.entities.UserSessionEntity;
import javax.persistence.EntityManager;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class UserSessionAdapter implements UserSessionModel {
private RealmModel realm;
private UserSessionEntity entity;
private EntityManager em;
public UserSessionAdapter(EntityManager em, RealmModel realm, UserSessionEntity entity) {
this.entity = entity;
this.em = em;
this.realm = realm;
}
public UserSessionEntity getEntity() {
return entity;
}
@Override
public String getId() {
return entity.getId();
}
@Override
public void setId(String id) {
entity.setId(id);
}
@Override
public UserModel getUser() {
return realm.getUserById(entity.getUserId());
}
@Override
public void setUser(UserModel user) {
entity.setUserId(user.getId());
}
@Override
public String getIpAddress() {
return entity.getIpAddress();
}
@Override
public void setIpAddress(String ipAddress) {
entity.setIpAddress(ipAddress);
}
@Override
public int getStarted() {
return entity.getStarted();
}
@Override
public void setStarted(int started) {
entity.setStarted(started);
}
@Override
public int getLastSessionRefresh() {
return entity.getLastSessionRefresh();
}
@Override
public void setLastSessionRefresh(int seconds) {
entity.setLastSessionRefresh(seconds);
}
@Override
public void associateClient(ClientModel client) {
for (ClientUserSessionAssociationEntity ass : entity.getClients()) {
if (ass.getClientId().equals(client.getId())) return;
}
ClientUserSessionAssociationEntity association = new ClientUserSessionAssociationEntity();
association.setClientId(client.getId());
association.setSession(entity);
association.setUserId(entity.getUserId());
association.setRealmId(realm.getId());
em.persist(association);
entity.getClients().add(association);
}
@Override
public void removeAssociatedClient(ClientModel client) {
em.createNamedQuery("removeClientUserSessionByClient").setParameter("clientId", client.getId()).executeUpdate();
}
@Override
public List<ClientModel> getClientAssociations() {
List<ClientModel> clients = new ArrayList<ClientModel>();
for (ClientUserSessionAssociationEntity association : entity.getClients()) {
ClientModel client = realm.findClientById(association.getClientId());
if (client == null) {
throw new ModelException("couldnt find client");
}
clients.add(client);
}
return clients;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || !(o instanceof UserSessionModel)) return false;
UserSessionModel that = (UserSessionModel) o;
return that.getId().equals(getId());
}
@Override
public int hashCode() {
return getId().hashCode();
}
}

View file

@ -0,0 +1,70 @@
package org.keycloak.models.jpa;
import org.keycloak.models.UsernameLoginFailureModel;
import org.keycloak.models.jpa.entities.UsernameLoginFailureEntity;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UsernameLoginFailureAdapter implements UsernameLoginFailureModel
{
protected UsernameLoginFailureEntity user;
public UsernameLoginFailureAdapter(UsernameLoginFailureEntity user)
{
this.user = user;
}
@Override
public String getUsername()
{
return user.getUsername();
}
@Override
public int getFailedLoginNotBefore() {
return user.getFailedLoginNotBefore();
}
@Override
public void setFailedLoginNotBefore(int notBefore) {
user.setFailedLoginNotBefore(notBefore);
}
@Override
public int getNumFailures() {
return user.getNumFailures();
}
@Override
public void incrementFailures() {
user.setNumFailures(getNumFailures() + 1);
}
@Override
public void clearFailures() {
user.setNumFailures(0);
}
@Override
public long getLastFailure() {
return user.getLastFailure();
}
@Override
public void setLastFailure(long lastFailure) {
user.setLastFailure(lastFailure);
}
@Override
public String getLastIPFailure() {
return user.getLastIPFailure();
}
@Override
public void setLastIPFailure(String ip) {
user.setLastIPFailure(ip);
}
}

View file

@ -0,0 +1,52 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.MappedSuperclass;
import org.hibernate.annotations.GenericGenerator;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@MappedSuperclass
public class AbstractRoleMappingEntity {
@Id
@GenericGenerator(name="keycloak_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
@GeneratedValue(generator = "keycloak_generator")
protected String id;
@ManyToOne(fetch= FetchType.LAZY)
protected UserEntity user;
@ManyToOne(fetch= FetchType.LAZY)
@JoinColumn(name="roleId")
protected RoleEntity role;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public UserEntity getUser() {
return user;
}
public void setUser(UserEntity user) {
this.user = user;
}
public RoleEntity getRole() {
return role;
}
public void setRole(RoleEntity role) {
this.role = role;
}
}

View file

@ -0,0 +1,90 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.CascadeType;
import javax.persistence.CollectionTable;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.annotations.GenericGenerator;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Entity
public class ApplicationEntity extends ClientEntity {
private boolean surrogateAuthRequired;
private String baseUrl;
private String managementUrl;
private boolean bearerOnly;
@OneToMany(fetch = FetchType.EAGER, cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "application")
Collection<RoleEntity> roles = new ArrayList<RoleEntity>();
@OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
@JoinTable(name="ApplicationDefaultRoles")
Collection<RoleEntity> defaultRoles = new ArrayList<RoleEntity>();
public boolean isSurrogateAuthRequired() {
return surrogateAuthRequired;
}
public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
this.surrogateAuthRequired = surrogateAuthRequired;
}
public String getBaseUrl() {
return baseUrl;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
public String getManagementUrl() {
return managementUrl;
}
public void setManagementUrl(String managementUrl) {
this.managementUrl = managementUrl;
}
public Collection<RoleEntity> getRoles() {
return roles;
}
public void setRoles(Collection<RoleEntity> roles) {
this.roles = roles;
}
public Collection<RoleEntity> getDefaultRoles() {
return defaultRoles;
}
public void setDefaultRoles(Collection<RoleEntity> defaultRoles) {
this.defaultRoles = defaultRoles;
}
public boolean isBearerOnly() {
return bearerOnly;
}
public void setBearerOnly(boolean bearerOnly) {
this.bearerOnly = bearerOnly;
}
}

View file

@ -0,0 +1,50 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToOne;
import org.hibernate.annotations.GenericGenerator;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@Entity
public class AuthenticationLinkEntity {
@Id
@GenericGenerator(name="keycloak_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
@GeneratedValue(generator = "keycloak_generator")
private String id;
protected String authProvider;
protected String authUserId;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getAuthProvider() {
return authProvider;
}
public void setAuthProvider(String authProvider) {
this.authProvider = authProvider;
}
public String getAuthUserId() {
return authUserId;
}
public void setAuthUserId(String authUserId) {
this.authUserId = authUserId;
}
}

View file

@ -0,0 +1,80 @@
package org.keycloak.models.jpa.entities;
import java.util.Map;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.MapKeyColumn;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@Entity
@Table(name="AuthProviderEntity")
public class AuthenticationProviderEntity {
@Id
@GenericGenerator(name="keycloak_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
@GeneratedValue(generator = "keycloak_generator")
protected String id;
private String providerName;
private boolean passwordUpdateSupported;
private int priority;
@ElementCollection
@MapKeyColumn(name="name")
@Column(name="value")
@CollectionTable(name="AuthProviderEntity_cfg", joinColumns = {
@JoinColumn(name = "AuthProviderEntity_id")
})
private Map<String, String> config;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getProviderName() {
return providerName;
}
public void setProviderName(String providerName) {
this.providerName = providerName;
}
public boolean isPasswordUpdateSupported() {
return passwordUpdateSupported;
}
public void setPasswordUpdateSupported(boolean passwordUpdateSupported) {
this.passwordUpdateSupported = passwordUpdateSupported;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
public Map<String, String> getConfig() {
return config;
}
public void setConfig(Map<String, String> config) {
this.config = config;
}
}

View file

@ -0,0 +1,131 @@
package org.keycloak.models.jpa.entities;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.CascadeType;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import java.util.HashSet;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Table(uniqueConstraints = {@UniqueConstraint(columnNames = {"realm", "name"})})
public abstract class ClientEntity {
@Id
private String id;
@Column(name = "name")
private String name;
private boolean enabled;
private String secret;
private long allowedClaimsMask;
private int notBefore;
private boolean publicClient;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "realm")
protected RealmEntity realm;
@ElementCollection
@CollectionTable
protected Set<String> webOrigins = new HashSet<String>();
@ElementCollection
@CollectionTable
protected Set<String> redirectUris = new HashSet<String>();
public RealmEntity getRealm() {
return realm;
}
public void setRealm(RealmEntity realm) {
this.realm = realm;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getAllowedClaimsMask() {
return allowedClaimsMask;
}
public void setAllowedClaimsMask(long allowedClaimsMask) {
this.allowedClaimsMask = allowedClaimsMask;
}
public Set<String> getWebOrigins() {
return webOrigins;
}
public void setWebOrigins(Set<String> webOrigins) {
this.webOrigins = webOrigins;
}
public Set<String> getRedirectUris() {
return redirectUris;
}
public void setRedirectUris(Set<String> redirectUris) {
this.redirectUris = redirectUris;
}
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
public int getNotBefore() {
return notBefore;
}
public void setNotBefore(int notBefore) {
this.notBefore = notBefore;
}
public boolean isPublicClient() {
return publicClient;
}
public void setPublicClient(boolean publicClient) {
this.publicClient = publicClient;
}
}

View file

@ -0,0 +1,84 @@
package org.keycloak.models.jpa.entities;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Entity
@Table(name = "ClientUserSessionAscEntity")
@NamedQueries({
@NamedQuery(name = "getAllClientUserSessions", query = "select s from ClientUserSessionAssociationEntity s"),
@NamedQuery(name = "getClientUserSessionBySession", query = "select s from ClientUserSessionAssociationEntity s where s.session = :session"),
@NamedQuery(name = "getClientUserSessionByClient", query = "select s from ClientUserSessionAssociationEntity s where s.clientId = :clientId"),
@NamedQuery(name = "getActiveClientSessions", query = "select COUNT(s) from ClientUserSessionAssociationEntity s where s.clientId = :clientId"),
@NamedQuery(name = "removeClientUserSessionByClient", query = "delete from ClientUserSessionAssociationEntity s where s.clientId = :clientId"),
@NamedQuery(name = "removeClientUserSessionByUser", query = "delete from ClientUserSessionAssociationEntity s where s.userId = :userId"),
@NamedQuery(name = "removeClientUserSessionByRealm", query = "delete from ClientUserSessionAssociationEntity s where s.realmId = :realmId")})
public class ClientUserSessionAssociationEntity {
@Id
@GenericGenerator(name="uuid_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
@GeneratedValue(generator = "uuid_generator")
private String id;
// we use ids to avoid select for update contention
private String userId;
private String realmId;
@ManyToOne(fetch= FetchType.LAZY)
private UserSessionEntity session;
private String clientId;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public UserSessionEntity getSession() {
return session;
}
public void setSession(UserSessionEntity session) {
this.session = session;
}
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getRealmId() {
return realmId;
}
public void setRealmId(String realmId) {
this.realmId = realmId;
}
}

View file

@ -0,0 +1,91 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import org.hibernate.annotations.GenericGenerator;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@NamedQueries({
@NamedQuery(name="credentialByUserAndType", query="select cred from CredentialEntity cred where cred.user = :user and cred.type = :type")
})
@Entity
public class CredentialEntity {
@Id
@GenericGenerator(name="keycloak_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
@GeneratedValue(generator = "keycloak_generator")
protected String id;
protected String type;
protected String value;
protected String device;
protected byte[] salt;
protected int hashIterations;
@ManyToOne(fetch = FetchType.LAZY)
protected UserEntity user;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDevice() {
return device;
}
public void setDevice(String device) {
this.device = device;
}
public UserEntity getUser() {
return user;
}
public void setUser(UserEntity user) {
this.user = user;
}
public byte[] getSalt() {
return salt;
}
public void setSalt(byte[] salt) {
this.salt = salt;
}
public int getHashIterations() {
return hashIterations;
}
public void setHashIterations(int hashIterations) {
this.hashIterations = hashIterations;
}
}

View file

@ -0,0 +1,27 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.Entity;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@NamedQueries({
@NamedQuery(name="findOAuthClientByName", query="select o from OAuthClientEntity o where o.name=:name and o.realm = :realm"),
@NamedQuery(name="findOAuthClientByRealm", query="select o from OAuthClientEntity o where o.realm = :realm")
})
@Entity
public class OAuthClientEntity extends ClientEntity {
protected boolean directGrantsOnly;
public boolean isDirectGrantsOnly() {
return directGrantsOnly;
}
public void setDirectGrantsOnly(boolean directGrantsOnly) {
this.directGrantsOnly = directGrantsOnly;
}
}

View file

@ -0,0 +1,479 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.CascadeType;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinTable;
import javax.persistence.MapKeyColumn;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Entity
@NamedQueries({
@NamedQuery(name="getAllRealms", query="select realm from RealmEntity realm"),
@NamedQuery(name="getRealmByName", query="select realm from RealmEntity realm where realm.name = :name"),
})
public class RealmEntity {
@Id
protected String id;
@Column(unique = true)
protected String name;
protected boolean enabled;
protected boolean sslNotRequired;
protected boolean registrationAllowed;
protected boolean passwordCredentialGrantAllowed;
protected boolean verifyEmail;
protected boolean resetPasswordAllowed;
protected boolean social;
protected boolean rememberMe;
//--- brute force settings
protected boolean bruteForceProtected;
protected int maxFailureWaitSeconds;
protected int minimumQuickLoginWaitSeconds;
protected int waitIncrementSeconds;
protected long quickLoginCheckMilliSeconds;
protected int maxDeltaTimeSeconds;
protected int failureFactor;
//--- end brute force settings
@Column(name="updateProfileOnInitSocLogin")
protected boolean updateProfileOnInitialSocialLogin;
protected String passwordPolicy;
private int ssoSessionIdleTimeout;
private int ssoSessionMaxLifespan;
protected int accessTokenLifespan;
protected int accessCodeLifespan;
protected int accessCodeLifespanUserAction;
protected int notBefore;
@Column(length = 2048)
protected String publicKeyPem;
@Column(length = 2048)
protected String privateKeyPem;
protected String loginTheme;
protected String accountTheme;
protected String adminTheme;
protected String emailTheme;
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true)
@JoinTable(name="User_RequiredCreds")
Collection<RequiredCredentialEntity> requiredCredentials = new ArrayList<RequiredCredentialEntity>();
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true)
@JoinTable(name="AuthProviders")
List<AuthenticationProviderEntity> authenticationProviders = new ArrayList<AuthenticationProviderEntity>();
@OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
Collection<ApplicationEntity> applications = new ArrayList<ApplicationEntity>();
@OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
Collection<RoleEntity> roles = new ArrayList<RoleEntity>();
@ElementCollection
@MapKeyColumn(name="name")
@Column(name="value")
@CollectionTable
protected Map<String, String> smtpConfig = new HashMap<String, String>();
@ElementCollection
@MapKeyColumn(name="name")
@Column(name="value")
@CollectionTable
protected Map<String, String> socialConfig = new HashMap<String, String>();
@ElementCollection
@MapKeyColumn(name="name")
@Column(name="value")
@CollectionTable
protected Map<String, String> ldapServerConfig = new HashMap<String, String>();
@OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
@JoinTable(name="RealmDefaultRoles")
protected Collection<RoleEntity> defaultRoles = new ArrayList<RoleEntity>();
protected boolean auditEnabled;
protected long auditExpiration;
@ElementCollection
protected Set<String> auditListeners= new HashSet<String>();
@OneToOne
protected ApplicationEntity masterAdminApp;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean isSslNotRequired() {
return sslNotRequired;
}
public void setSslNotRequired(boolean sslNotRequired) {
this.sslNotRequired = sslNotRequired;
}
public boolean isPasswordCredentialGrantAllowed() {
return passwordCredentialGrantAllowed;
}
public void setPasswordCredentialGrantAllowed(boolean passwordCredentialGrantAllowed) {
this.passwordCredentialGrantAllowed = passwordCredentialGrantAllowed;
}
public boolean isRegistrationAllowed() {
return registrationAllowed;
}
public void setRegistrationAllowed(boolean registrationAllowed) {
this.registrationAllowed = registrationAllowed;
}
public boolean isRememberMe() {
return rememberMe;
}
public void setRememberMe(boolean rememberMe) {
this.rememberMe = rememberMe;
}
public boolean isVerifyEmail() {
return verifyEmail;
}
public void setVerifyEmail(boolean verifyEmail) {
this.verifyEmail = verifyEmail;
}
public boolean isResetPasswordAllowed() {
return resetPasswordAllowed;
}
public void setResetPasswordAllowed(boolean resetPasswordAllowed) {
this.resetPasswordAllowed = resetPasswordAllowed;
}
public boolean isSocial() {
return social;
}
public void setSocial(boolean social) {
this.social = social;
}
public boolean isUpdateProfileOnInitialSocialLogin() {
return updateProfileOnInitialSocialLogin;
}
public void setUpdateProfileOnInitialSocialLogin(boolean updateProfileOnInitialSocialLogin) {
this.updateProfileOnInitialSocialLogin = updateProfileOnInitialSocialLogin;
}
public int getSsoSessionIdleTimeout() {
return ssoSessionIdleTimeout;
}
public void setSsoSessionIdleTimeout(int ssoSessionIdleTimeout) {
this.ssoSessionIdleTimeout = ssoSessionIdleTimeout;
}
public int getSsoSessionMaxLifespan() {
return ssoSessionMaxLifespan;
}
public void setSsoSessionMaxLifespan(int ssoSessionMaxLifespan) {
this.ssoSessionMaxLifespan = ssoSessionMaxLifespan;
}
public int getAccessTokenLifespan() {
return accessTokenLifespan;
}
public void setAccessTokenLifespan(int accessTokenLifespan) {
this.accessTokenLifespan = accessTokenLifespan;
}
public int getAccessCodeLifespan() {
return accessCodeLifespan;
}
public void setAccessCodeLifespan(int accessCodeLifespan) {
this.accessCodeLifespan = accessCodeLifespan;
}
public int getAccessCodeLifespanUserAction() {
return accessCodeLifespanUserAction;
}
public void setAccessCodeLifespanUserAction(int accessCodeLifespanUserAction) {
this.accessCodeLifespanUserAction = accessCodeLifespanUserAction;
}
public String getPublicKeyPem() {
return publicKeyPem;
}
public void setPublicKeyPem(String publicKeyPem) {
this.publicKeyPem = publicKeyPem;
}
public String getPrivateKeyPem() {
return privateKeyPem;
}
public void setPrivateKeyPem(String privateKeyPem) {
this.privateKeyPem = privateKeyPem;
}
public Collection<RequiredCredentialEntity> getRequiredCredentials() {
return requiredCredentials;
}
public void setRequiredCredentials(Collection<RequiredCredentialEntity> requiredCredentials) {
this.requiredCredentials = requiredCredentials;
}
public List<AuthenticationProviderEntity> getAuthenticationProviders() {
return authenticationProviders;
}
public void setAuthenticationProviders(List<AuthenticationProviderEntity> authenticationProviders) {
this.authenticationProviders = authenticationProviders;
}
public Collection<ApplicationEntity> getApplications() {
return applications;
}
public void setApplications(Collection<ApplicationEntity> applications) {
this.applications = applications;
}
public Collection<RoleEntity> getRoles() {
return roles;
}
public void setRoles(Collection<RoleEntity> roles) {
this.roles = roles;
}
public void addRole(RoleEntity role) {
if (roles == null) {
roles = new ArrayList<RoleEntity>();
}
roles.add(role);
}
public Map<String, String> getSmtpConfig() {
return smtpConfig;
}
public void setSmtpConfig(Map<String, String> smtpConfig) {
this.smtpConfig = smtpConfig;
}
public Map<String, String> getSocialConfig() {
return socialConfig;
}
public void setSocialConfig(Map<String, String> socialConfig) {
this.socialConfig = socialConfig;
}
public Map<String, String> getLdapServerConfig() {
return ldapServerConfig;
}
public void setLdapServerConfig(Map<String, String> ldapServerConfig) {
this.ldapServerConfig = ldapServerConfig;
}
public Collection<RoleEntity> getDefaultRoles() {
return defaultRoles;
}
public void setDefaultRoles(Collection<RoleEntity> defaultRoles) {
this.defaultRoles = defaultRoles;
}
public String getPasswordPolicy() {
return passwordPolicy;
}
public void setPasswordPolicy(String passwordPolicy) {
this.passwordPolicy = passwordPolicy;
}
public String getLoginTheme() {
return loginTheme;
}
public void setLoginTheme(String theme) {
this.loginTheme = theme;
}
public String getAccountTheme() {
return accountTheme;
}
public void setAccountTheme(String theme) {
this.accountTheme = theme;
}
public String getAdminTheme() {
return adminTheme;
}
public void setAdminTheme(String adminTheme) {
this.adminTheme = adminTheme;
}
public String getEmailTheme() {
return emailTheme;
}
public void setEmailTheme(String emailTheme) {
this.emailTheme = emailTheme;
}
public int getNotBefore() {
return notBefore;
}
public void setNotBefore(int notBefore) {
this.notBefore = notBefore;
}
public boolean isBruteForceProtected() {
return bruteForceProtected;
}
public void setBruteForceProtected(boolean bruteForceProtected) {
this.bruteForceProtected = bruteForceProtected;
}
public int getMaxFailureWaitSeconds() {
return maxFailureWaitSeconds;
}
public void setMaxFailureWaitSeconds(int maxFailureWaitSeconds) {
this.maxFailureWaitSeconds = maxFailureWaitSeconds;
}
public int getMinimumQuickLoginWaitSeconds() {
return minimumQuickLoginWaitSeconds;
}
public void setMinimumQuickLoginWaitSeconds(int minimumQuickLoginWaitSeconds) {
this.minimumQuickLoginWaitSeconds = minimumQuickLoginWaitSeconds;
}
public int getWaitIncrementSeconds() {
return waitIncrementSeconds;
}
public void setWaitIncrementSeconds(int waitIncrementSeconds) {
this.waitIncrementSeconds = waitIncrementSeconds;
}
public long getQuickLoginCheckMilliSeconds() {
return quickLoginCheckMilliSeconds;
}
public void setQuickLoginCheckMilliSeconds(long quickLoginCheckMilliSeconds) {
this.quickLoginCheckMilliSeconds = quickLoginCheckMilliSeconds;
}
public int getMaxDeltaTimeSeconds() {
return maxDeltaTimeSeconds;
}
public void setMaxDeltaTimeSeconds(int maxDeltaTimeSeconds) {
this.maxDeltaTimeSeconds = maxDeltaTimeSeconds;
}
public int getFailureFactor() {
return failureFactor;
}
public void setFailureFactor(int failureFactor) {
this.failureFactor = failureFactor;
}
public boolean isAuditEnabled() {
return auditEnabled;
}
public void setAuditEnabled(boolean auditEnabled) {
this.auditEnabled = auditEnabled;
}
public long getAuditExpiration() {
return auditExpiration;
}
public void setAuditExpiration(long auditExpiration) {
this.auditExpiration = auditExpiration;
}
public Set<String> getAuditListeners() {
return auditListeners;
}
public void setAuditListeners(Set<String> auditListeners) {
this.auditListeners = auditListeners;
}
public ApplicationEntity getMasterAdminApp() {
return masterAdminApp;
}
public void setMasterAdminApp(ApplicationEntity masterAdminApp) {
this.masterAdminApp = masterAdminApp;
}
}

View file

@ -0,0 +1,64 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.annotations.GenericGenerator;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Entity
public class RequiredCredentialEntity {
@Id
@GenericGenerator(name="keycloak_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
@GeneratedValue(generator = "keycloak_generator")
protected String id;
protected String type;
protected boolean input;
protected boolean secret;
protected String formLabel;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public boolean isInput() {
return input;
}
public void setInput(boolean input) {
this.input = input;
}
public boolean isSecret() {
return secret;
}
public void setSecret(boolean secret) {
this.secret = secret;
}
public String getFormLabel() {
return formLabel;
}
public void setFormLabel(String formLabel) {
this.formLabel = formLabel;
}
}

View file

@ -0,0 +1,157 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import java.util.ArrayList;
import java.util.Collection;
import org.hibernate.annotations.GenericGenerator;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Entity
@Table(uniqueConstraints = {
@UniqueConstraint(columnNames = { "name", "appRealmConstraint" })
})
@NamedQueries({
@NamedQuery(name="getAppRoleByName", query="select role from RoleEntity role where role.name = :name and role.application = :application"),
@NamedQuery(name="getRealmRoleByName", query="select role from RoleEntity role where role.applicationRole = false and role.name = :name and role.realm = :realm")
})
public class RoleEntity {
@Id
@Column(name="id")
private String id;
private String name;
private String description;
// hax! couldn't get constraint to work properly
private String realmId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "realm")
private RealmEntity realm;
@Column(name="applicationRole")
private boolean applicationRole;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "application")
private ApplicationEntity application;
// Hack to ensure that either name+application or name+realm are unique. Needed due to MS-SQL as it don't allow multiple NULL values in the column, which is part of constraint
private String appRealmConstraint;
@ManyToMany(fetch = FetchType.LAZY, cascade = {})
@JoinTable(name = "CompositeRole", joinColumns = @JoinColumn(name = "composite"), inverseJoinColumns = @JoinColumn(name = "childRole"))
private Collection<RoleEntity> compositeRoles = new ArrayList<RoleEntity>();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getRealmId() {
return realmId;
}
public void setRealmId(String realmId) {
this.realmId = realmId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Collection<RoleEntity> getCompositeRoles() {
return compositeRoles;
}
public void setCompositeRoles(Collection<RoleEntity> compositeRoles) {
this.compositeRoles = compositeRoles;
}
public boolean isApplicationRole() {
return applicationRole;
}
public void setApplicationRole(boolean applicationRole) {
this.applicationRole = applicationRole;
}
public RealmEntity getRealm() {
return realm;
}
public void setRealm(RealmEntity realm) {
this.realm = realm;
this.appRealmConstraint = realm.getId();
}
public ApplicationEntity getApplication() {
return application;
}
public void setApplication(ApplicationEntity application) {
this.application = application;
if (application != null) {
this.appRealmConstraint = application.getId();
}
}
public String getAppRealmConstraint() {
return appRealmConstraint;
}
public void setAppRealmConstraint(String appRealmConstraint) {
this.appRealmConstraint = appRealmConstraint;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RoleEntity that = (RoleEntity) o;
if (!id.equals(that.id)) return false;
return true;
}
@Override
public int hashCode() {
return id.hashCode();
}
}

View file

@ -0,0 +1,60 @@
package org.keycloak.models.jpa.entities;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@NamedQueries({
@NamedQuery(name="hasScope", query="select m from ScopeMappingEntity m where m.client = :client and m.role = :role"),
@NamedQuery(name="clientScopeMappings", query="select m from ScopeMappingEntity m where m.client = :client"),
@NamedQuery(name="clientScopeMappingIds", query="select m.role.id from ScopeMappingEntity m where m.client = :client")
})
@Entity
public class ScopeMappingEntity {
@Id
@GenericGenerator(name="keycloak_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
@GeneratedValue(generator = "keycloak_generator")
protected String id;
@ManyToOne(fetch= FetchType.LAZY)
protected ClientEntity client;
@ManyToOne(fetch= FetchType.LAZY)
@JoinColumn(name="roleId")
protected RoleEntity role;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public ClientEntity getClient() {
return client;
}
public void setClient(ClientEntity client) {
this.client = client;
}
public RoleEntity getRole() {
return role;
}
public void setRole(RoleEntity role) {
this.role = role;
}
}

View file

@ -0,0 +1,86 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import org.hibernate.annotations.GenericGenerator;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@NamedQueries({
@NamedQuery(name="findSocialLinkByUser", query="select link from SocialLinkEntity link where link.user = :user"),
@NamedQuery(name="findSocialLinkByUserAndProvider", query="select link from SocialLinkEntity link where link.user = :user and link.socialProvider = :socialProvider"),
@NamedQuery(name="findUserByLinkAndRealm", query="select link.user from SocialLinkEntity link where link.realm = :realm and link.socialProvider = :socialProvider and link.socialUserId = :socialUserId")
})
@Entity
public class SocialLinkEntity {
@Id
@GenericGenerator(name="keycloak_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
@GeneratedValue(generator = "keycloak_generator")
private String id;
@ManyToOne(fetch = FetchType.LAZY)
private UserEntity user;
@ManyToOne(fetch = FetchType.LAZY)
protected RealmEntity realm;
protected String socialProvider;
protected String socialUserId;
protected String socialUsername;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public UserEntity getUser() {
return user;
}
public void setUser(UserEntity user) {
this.user = user;
}
public String getSocialProvider() {
return socialProvider;
}
public void setSocialProvider(String socialProvider) {
this.socialProvider = socialProvider;
}
public String getSocialUserId() {
return socialUserId;
}
public void setSocialUserId(String socialUserId) {
this.socialUserId = socialUserId;
}
public String getSocialUsername() {
return socialUsername;
}
public void setSocialUsername(String socialUsername) {
this.socialUsername = socialUsername;
}
public RealmEntity getRealm() {
return realm;
}
public void setRealm(RealmEntity realm) {
this.realm = realm;
}
}

View file

@ -0,0 +1,196 @@
package org.keycloak.models.jpa.entities;
import org.hibernate.annotations.GenericGenerator;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import javax.persistence.CascadeType;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.MapKeyColumn;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@NamedQueries({
@NamedQuery(name="getRealmUserById", query="select u from UserEntity u where u.id = :id and u.realm = :realm"),
@NamedQuery(name="getRealmUserByUsername", query="select u from UserEntity u where u.username = :username and u.realm = :realm"),
@NamedQuery(name="getRealmUserByEmail", query="select u from UserEntity u where u.email = :email and u.realm = :realm"),
@NamedQuery(name="getRealmUserByLastName", query="select u from UserEntity u where u.lastName = :lastName and u.realm = :realm"),
@NamedQuery(name="getRealmUserByFirstLastName", query="select u from UserEntity u where u.firstName = :first and u.lastName = :last and u.realm = :realm")
})
@Entity
@Table(uniqueConstraints = {
@UniqueConstraint(columnNames = { "realm", "username" }),
@UniqueConstraint(columnNames = { "realm", "emailConstraint" })
})
public class UserEntity {
@Id
protected String id;
protected String username;
protected String firstName;
protected String lastName;
protected String email;
protected boolean enabled;
protected boolean totp;
protected boolean emailVerified;
// Hack just to workaround the fact that on MS-SQL you can't have unique constraint with multiple NULL values TODO: Find better solution (like unique index with 'where' but that's proprietary)
protected String emailConstraint = KeycloakModelUtils.generateId();
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "realm")
protected RealmEntity realm;
@ElementCollection
@MapKeyColumn(name="name")
@Column(name="value")
@CollectionTable
protected Map<String, String> attributes = new HashMap<String, String>();
@ElementCollection
@CollectionTable
protected Set<UserModel.RequiredAction> requiredActions = new HashSet<UserModel.RequiredAction>();
@OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true)
protected Collection<CredentialEntity> credentials = new ArrayList<CredentialEntity>();
@OneToOne(cascade = CascadeType.REMOVE, orphanRemoval = true)
protected AuthenticationLinkEntity authenticationLink;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
this.emailConstraint = email != null ? email : KeycloakModelUtils.generateId();
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String getEmailConstraint() {
return emailConstraint;
}
public void setEmailConstraint(String emailConstraint) {
this.emailConstraint = emailConstraint;
}
public boolean isTotp() {
return totp;
}
public void setTotp(boolean totp) {
this.totp = totp;
}
public boolean isEmailVerified() {
return emailVerified;
}
public void setEmailVerified(boolean emailVerified) {
this.emailVerified = emailVerified;
}
public Map<String, String> getAttributes() {
return attributes;
}
public void setAttributes(Map<String, String> attributes) {
this.attributes = attributes;
}
public Set<UserModel.RequiredAction> getRequiredActions() {
return requiredActions;
}
public void setRequiredActions(Set<UserModel.RequiredAction> requiredActions) {
this.requiredActions = requiredActions;
}
public RealmEntity getRealm() {
return realm;
}
public void setRealm(RealmEntity realm) {
this.realm = realm;
}
public Collection<CredentialEntity> getCredentials() {
return credentials;
}
public void setCredentials(Collection<CredentialEntity> credentials) {
this.credentials = credentials;
}
public AuthenticationLinkEntity getAuthenticationLink() {
return authenticationLink;
}
public void setAuthenticationLink(AuthenticationLinkEntity authenticationLink) {
this.authenticationLink = authenticationLink;
}
}

View file

@ -0,0 +1,19 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.Entity;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@NamedQueries({
@NamedQuery(name="userHasRole", query="select m from UserRoleMappingEntity m where m.user = :user and m.role = :role"),
@NamedQuery(name="userRoleMappings", query="select m from UserRoleMappingEntity m where m.user = :user"),
@NamedQuery(name="userRoleMappingIds", query="select m.role.id from UserRoleMappingEntity m where m.user = :user")
})
@Entity
public class UserRoleMappingEntity extends AbstractRoleMappingEntity {
}

View file

@ -0,0 +1,107 @@
package org.keycloak.models.jpa.entities;
import org.hibernate.annotations.GenericGenerator;
import org.keycloak.models.UserModel;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import java.util.ArrayList;
import java.util.Collection;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
@Entity
@NamedQueries({
@NamedQuery(name = "getUserSessionByUser", query = "select s from UserSessionEntity s where s.userId = :userId"),
@NamedQuery(name = "removeRealmUserSessions", query = "delete from UserSessionEntity s where s.realmId = :realmId"),
@NamedQuery(name = "removeUserSessionByUser", query = "delete from UserSessionEntity s where s.userId = :userId"),
@NamedQuery(name = "getUserSessionExpired", query = "select s from UserSessionEntity s where s.started < :maxTime or s.lastSessionRefresh < :idleTime"),
@NamedQuery(name = "removeUserSessionExpired", query = "delete from UserSessionEntity s where s.started < :maxTime or s.lastSessionRefresh < :idleTime")
})
public class UserSessionEntity {
@Id
@GenericGenerator(name="uuid_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
@GeneratedValue(generator = "uuid_generator")
private String id;
// we use ids to avoid select for update contention
private String userId;
private String realmId;
private String ipAddress;
private int started;
private int lastSessionRefresh;
@OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy="session")
private Collection<ClientUserSessionAssociationEntity> clients = new ArrayList<ClientUserSessionAssociationEntity>();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getRealmId() {
return realmId;
}
public void setRealmId(String realmId) {
this.realmId = realmId;
}
public String getIpAddress() {
return ipAddress;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public int getStarted() {
return started;
}
public void setStarted(int started) {
this.started = started;
}
public int getLastSessionRefresh() {
return lastSessionRefresh;
}
public void setLastSessionRefresh(int lastSessionRefresh) {
this.lastSessionRefresh = lastSessionRefresh;
}
public Collection<ClientUserSessionAssociationEntity> getClients() {
return clients;
}
public void setClients(Collection<ClientUserSessionAssociationEntity> clients) {
this.clients = clients;
}
}

View file

@ -0,0 +1,88 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Entity
@NamedQueries({
@NamedQuery(name="getAllFailures", query="select failure from UsernameLoginFailureEntity failure"),
})
public class UsernameLoginFailureEntity {
// we manually set the id to be username-realmid
// we may have a concurrent creation of the same login failure entry that we want to avoid
@Id
protected String id;
protected String username;
protected int failedLoginNotBefore;
protected int numFailures;
protected long lastFailure;
protected String lastIPFailure;
@ManyToOne(fetch = FetchType.LAZY)
protected RealmEntity realm;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getFailedLoginNotBefore() {
return failedLoginNotBefore;
}
public void setFailedLoginNotBefore(int failedLoginNotBefore) {
this.failedLoginNotBefore = failedLoginNotBefore;
}
public int getNumFailures() {
return numFailures;
}
public void setNumFailures(int numFailures) {
this.numFailures = numFailures;
}
public long getLastFailure() {
return lastFailure;
}
public void setLastFailure(long lastFailure) {
this.lastFailure = lastFailure;
}
public String getLastIPFailure() {
return lastIPFailure;
}
public void setLastIPFailure(String lastIPFailure) {
this.lastIPFailure = lastIPFailure;
}
public RealmEntity getRealm() {
return realm;
}
public void setRealm(RealmEntity realm) {
this.realm = realm;
}
}

View file

@ -0,0 +1,19 @@
package org.keycloak.models.jpa.utils;
import java.io.Serializable;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.IdentifierGenerator;
import org.keycloak.models.utils.KeycloakModelUtils;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class JpaIdGenerator implements IdentifierGenerator {
@Override
public Serializable generate(SessionImplementor session, Object object) throws HibernateException {
return KeycloakModelUtils.generateId();
}
}

View file

@ -0,0 +1 @@
org.keycloak.models.jpa.JpaModelProviderFactory

View file

@ -0,0 +1,70 @@
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="jpa-keycloak-identity-store" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>org.keycloak.models.jpa.entities.ApplicationEntity</class>
<class>org.keycloak.models.jpa.entities.CredentialEntity</class>
<class>org.keycloak.models.jpa.entities.OAuthClientEntity</class>
<class>org.keycloak.models.jpa.entities.RealmEntity</class>
<class>org.keycloak.models.jpa.entities.RequiredCredentialEntity</class>
<class>org.keycloak.models.jpa.entities.AuthenticationProviderEntity</class>
<class>org.keycloak.models.jpa.entities.RoleEntity</class>
<class>org.keycloak.models.jpa.entities.SocialLinkEntity</class>
<class>org.keycloak.models.jpa.entities.AuthenticationLinkEntity</class>
<class>org.keycloak.models.jpa.entities.UserEntity</class>
<class>org.keycloak.models.jpa.entities.UserSessionEntity</class>
<class>org.keycloak.models.jpa.entities.ClientUserSessionAssociationEntity</class>
<class>org.keycloak.models.jpa.entities.UserRoleMappingEntity</class>
<class>org.keycloak.models.jpa.entities.UsernameLoginFailureEntity</class>
<class>org.keycloak.models.jpa.entities.ScopeMappingEntity</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="hibernate.connection.url" value="jdbc:h2:mem:test"/>
<property name="hibernate.connection.driver_class" value="org.h2.Driver"/>
<property name="hibernate.connection.username" value="sa"/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="true" />
</properties>
</persistence-unit>
<!--
<persistence-unit name="picketlink-keycloak-identity-store" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>org.picketlink.idm.jpa.model.sample.simple.AttributedTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.AccountTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.RoleTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.GroupTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.IdentityTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.RelationshipTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.RelationshipIdentityTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.PartitionTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.PasswordCredentialTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.DigestCredentialTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.X509CredentialTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.OTPCredentialTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.AttributeTypeEntity</class>
<class>org.keycloak.models.picketlink.mappings.RealmEntity</class>
<class>org.keycloak.models.picketlink.mappings.ApplicationEntity</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="hibernate.connection.url" value="jdbc:h2:mem:test"/>
<property name="hibernate.connection.driver_class" value="org.h2.Driver"/>
<property name="hibernate.connection.username" value="sa"/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="true" />
</properties>
</persistence-unit>
-->
</persistence>

View file

@ -49,27 +49,7 @@
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-hybrid</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-realms-jpa</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-users-jpa</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-sessions-mem</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-sessions-jpa</artifactId>
<artifactId>keycloak-model-jpa</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>

View file

@ -11,25 +11,13 @@
},
"model": {
"provider": "hybrid"
"provider": "jpa"
},
"modelCache": {
"provider": "${keycloak.model.cache.provider:}"
},
"modelRealms": {
"provider": "jpa"
},
"modelUsers": {
"provider": "jpa"
},
"modelSessions": {
"provider": "mem"
},
"timer": {
"provider": "basic"
},

View file

@ -4,23 +4,21 @@
version="1.0">
<persistence-unit name="jpa-keycloak-identity-store" transaction-type="RESOURCE_LOCAL">
<jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
<class>org.keycloak.models.realms.jpa.entities.ApplicationEntity</class>
<class>org.keycloak.models.realms.jpa.entities.OAuthClientEntity</class>
<class>org.keycloak.models.realms.jpa.entities.RealmEntity</class>
<class>org.keycloak.models.realms.jpa.entities.RequiredCredentialEntity</class>
<class>org.keycloak.models.realms.jpa.entities.AuthenticationProviderEntity</class>
<class>org.keycloak.models.realms.jpa.entities.RoleEntity</class>
<class>org.keycloak.models.realms.jpa.entities.ScopeMappingEntity</class>
<class>org.keycloak.models.users.jpa.entities.UserAttributeEntity</class>
<class>org.keycloak.models.users.jpa.entities.UserCredentialEntity</class>
<class>org.keycloak.models.users.jpa.entities.UserRoleMappingEntity</class>
<class>org.keycloak.models.users.jpa.entities.UserEntity</class>
<class>org.keycloak.models.sessions.jpa.entities.ClientUserSessionAssociationEntity</class>
<class>org.keycloak.models.sessions.jpa.entities.UsernameLoginFailureEntity</class>
<class>org.keycloak.models.sessions.jpa.entities.UserSessionEntity</class>
<class>org.keycloak.models.jpa.entities.ApplicationEntity</class>
<class>org.keycloak.models.jpa.entities.CredentialEntity</class>
<class>org.keycloak.models.jpa.entities.OAuthClientEntity</class>
<class>org.keycloak.models.jpa.entities.RealmEntity</class>
<class>org.keycloak.models.jpa.entities.RequiredCredentialEntity</class>
<class>org.keycloak.models.jpa.entities.AuthenticationProviderEntity</class>
<class>org.keycloak.models.jpa.entities.RoleEntity</class>
<class>org.keycloak.models.jpa.entities.SocialLinkEntity</class>
<class>org.keycloak.models.jpa.entities.AuthenticationLinkEntity</class>
<class>org.keycloak.models.jpa.entities.UserEntity</class>
<class>org.keycloak.models.jpa.entities.UserSessionEntity</class>
<class>org.keycloak.models.jpa.entities.ClientUserSessionAssociationEntity</class>
<class>org.keycloak.models.jpa.entities.UsernameLoginFailureEntity</class>
<class>org.keycloak.models.jpa.entities.UserRoleMappingEntity</class>
<class>org.keycloak.models.jpa.entities.ScopeMappingEntity</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
@ -28,7 +26,7 @@
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
<persistence-unit name="jpa-keycloak-audit-store" transaction-type="RESOURCE_LOCAL">
<jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
<class>org.keycloak.audit.jpa.EventEntity</class>
@ -39,4 +37,5 @@
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
</persistence>

View file

@ -122,27 +122,7 @@
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-hybrid</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-realms-jpa</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-users-jpa</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-sessions-mem</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-sessions-jpa</artifactId>
<artifactId>keycloak-model-jpa</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>

View file

@ -14,7 +14,7 @@
},
"model": {
"provider": "${keycloak.model.provider:hybrid}",
"provider": "${keycloak.model.provider:jpa}",
"mongo": {
"host": "${keycloak.model.mongo.host:127.0.0.1}",
"port": "${keycloak.model.mongo.port:27017}",
@ -27,18 +27,6 @@
"provider": "${keycloak.model.cache.provider:simple}"
},
"modelRealms": {
"provider": "jpa"
},
"modelUsers": {
"provider": "jpa"
},
"modelSessions": {
"provider": "mem"
},
"timer": {
"provider": "basic"
},

View file

@ -5,22 +5,21 @@
<persistence-unit name="jpa-keycloak-identity-store" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>org.keycloak.models.realms.jpa.entities.ApplicationEntity</class>
<class>org.keycloak.models.realms.jpa.entities.OAuthClientEntity</class>
<class>org.keycloak.models.realms.jpa.entities.RealmEntity</class>
<class>org.keycloak.models.realms.jpa.entities.RequiredCredentialEntity</class>
<class>org.keycloak.models.realms.jpa.entities.AuthenticationProviderEntity</class>
<class>org.keycloak.models.realms.jpa.entities.RoleEntity</class>
<class>org.keycloak.models.realms.jpa.entities.ScopeMappingEntity</class>
<class>org.keycloak.models.users.jpa.entities.UserAttributeEntity</class>
<class>org.keycloak.models.users.jpa.entities.UserCredentialEntity</class>
<class>org.keycloak.models.users.jpa.entities.UserRoleMappingEntity</class>
<class>org.keycloak.models.users.jpa.entities.UserEntity</class>
<class>org.keycloak.models.sessions.jpa.entities.ClientUserSessionAssociationEntity</class>
<class>org.keycloak.models.sessions.jpa.entities.UsernameLoginFailureEntity</class>
<class>org.keycloak.models.sessions.jpa.entities.UserSessionEntity</class>
<class>org.keycloak.models.jpa.entities.ApplicationEntity</class>
<class>org.keycloak.models.jpa.entities.CredentialEntity</class>
<class>org.keycloak.models.jpa.entities.OAuthClientEntity</class>
<class>org.keycloak.models.jpa.entities.RealmEntity</class>
<class>org.keycloak.models.jpa.entities.RequiredCredentialEntity</class>
<class>org.keycloak.models.jpa.entities.AuthenticationProviderEntity</class>
<class>org.keycloak.models.jpa.entities.RoleEntity</class>
<class>org.keycloak.models.jpa.entities.SocialLinkEntity</class>
<class>org.keycloak.models.jpa.entities.AuthenticationLinkEntity</class>
<class>org.keycloak.models.jpa.entities.UserEntity</class>
<class>org.keycloak.models.jpa.entities.ClientUserSessionAssociationEntity</class>
<class>org.keycloak.models.jpa.entities.UserSessionEntity</class>
<class>org.keycloak.models.jpa.entities.UsernameLoginFailureEntity</class>
<class>org.keycloak.models.jpa.entities.UserRoleMappingEntity</class>
<class>org.keycloak.models.jpa.entities.ScopeMappingEntity</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
@ -52,4 +51,38 @@
<property name="hibernate.format_sql" value="true" />
</properties>
</persistence-unit>
<!--
<persistence-unit name="picketlink-keycloak-identity-store" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>org.picketlink.idm.jpa.model.sample.simple.AttributedTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.AccountTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.RoleTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.GroupTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.IdentityTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.RelationshipTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.RelationshipIdentityTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.PartitionTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.PasswordCredentialTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.DigestCredentialTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.X509CredentialTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.OTPCredentialTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.AttributeTypeEntity</class>
<class>org.keycloak.models.picketlink.mappings.RealmEntity</class>
<class>org.keycloak.models.picketlink.mappings.ApplicationEntity</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="hibernate.connection.url" value="jdbc:h2:mem:test"/>
<property name="hibernate.connection.driver_class" value="org.h2.Driver"/>
<property name="hibernate.connection.username" value="sa"/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="true" />
</properties>
</persistence-unit>
-->
</persistence>

View file

@ -40,31 +40,6 @@
<artifactId>keycloak-model-jpa</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-hybrid</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-realms-jpa</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-users-jpa</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-sessions-mem</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-sessions-jpa</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-mongo</artifactId>

View file

@ -66,26 +66,6 @@
<artifactId>keycloak-model-jpa</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-hybrid</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-realms-jpa</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-users-jpa</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-sessions-mem</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-audit-api</artifactId>