Merge pull request #472 from mposolda/db-fixes
KEYCLOAK-534 Fix MS-SQL, Oracle and Sybase
This commit is contained in:
commit
d1c890db18
14 changed files with 72 additions and 52 deletions
|
@ -5,6 +5,7 @@ import org.keycloak.audit.AuditProvider;
|
||||||
import org.keycloak.audit.AuditProviderFactory;
|
import org.keycloak.audit.AuditProviderFactory;
|
||||||
import org.keycloak.audit.EventType;
|
import org.keycloak.audit.EventType;
|
||||||
import org.keycloak.provider.ProviderSession;
|
import org.keycloak.provider.ProviderSession;
|
||||||
|
import org.keycloak.util.JpaUtils;
|
||||||
|
|
||||||
import javax.persistence.EntityManagerFactory;
|
import javax.persistence.EntityManagerFactory;
|
||||||
import javax.persistence.Persistence;
|
import javax.persistence.Persistence;
|
||||||
|
@ -28,7 +29,7 @@ public class JpaAuditProviderFactory implements AuditProviderFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(Config.Scope config) {
|
public void init(Config.Scope config) {
|
||||||
emf = Persistence.createEntityManagerFactory("jpa-keycloak-audit-store");
|
emf = Persistence.createEntityManagerFactory("jpa-keycloak-audit-store", JpaUtils.getHibernateProperties());
|
||||||
|
|
||||||
String[] include = config.getArray("include-events");
|
String[] include = config.getArray("include-events");
|
||||||
if (include != null) {
|
if (include != null) {
|
||||||
|
|
22
core/src/main/java/org/keycloak/util/JpaUtils.java
Normal file
22
core/src/main/java/org/keycloak/util/JpaUtils.java
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
package org.keycloak.util;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public class JpaUtils {
|
||||||
|
|
||||||
|
// Allows to override some properties in persistence.xml by system properties
|
||||||
|
public static Properties getHibernateProperties() {
|
||||||
|
Properties result = new Properties();
|
||||||
|
|
||||||
|
for (Object property : System.getProperties().keySet()) {
|
||||||
|
if (property.toString().startsWith("hibernate.")) {
|
||||||
|
String propValue = System.getProperty(property.toString());
|
||||||
|
result.put(property, propValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,11 +23,6 @@
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>org.jboss.spec.javax.servlet</groupId>
|
|
||||||
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jboss.spec.javax.servlet</groupId>
|
<groupId>org.jboss.spec.javax.servlet</groupId>
|
||||||
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
||||||
|
|
|
@ -142,7 +142,7 @@ public class ApplicationAdapter extends ClientAdapter implements ApplicationMode
|
||||||
|
|
||||||
applicationEntity.getRoles().remove(role);
|
applicationEntity.getRoles().remove(role);
|
||||||
applicationEntity.getDefaultRoles().remove(role);
|
applicationEntity.getDefaultRoles().remove(role);
|
||||||
em.createNativeQuery("delete from CompositeRole where role = :role").setParameter("role", role).executeUpdate();
|
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 " + ScopeMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", role).executeUpdate();
|
||||||
em.createQuery("delete from " + UserRoleMappingEntity.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);
|
role.setApplication(null);
|
||||||
|
|
|
@ -4,6 +4,7 @@ import org.keycloak.Config;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
import org.keycloak.provider.ProviderSession;
|
import org.keycloak.provider.ProviderSession;
|
||||||
|
import org.keycloak.util.JpaUtils;
|
||||||
|
|
||||||
import javax.persistence.EntityManagerFactory;
|
import javax.persistence.EntityManagerFactory;
|
||||||
import javax.persistence.Persistence;
|
import javax.persistence.Persistence;
|
||||||
|
@ -19,7 +20,7 @@ public class JpaKeycloakSessionFactory implements KeycloakSessionFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(Config.Scope config) {
|
public void init(Config.Scope config) {
|
||||||
emf = Persistence.createEntityManagerFactory("jpa-keycloak-identity-store", getHibernateProperties());
|
emf = Persistence.createEntityManagerFactory("jpa-keycloak-identity-store", JpaUtils.getHibernateProperties());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -36,18 +37,4 @@ public class JpaKeycloakSessionFactory implements KeycloakSessionFactory {
|
||||||
public void close() {
|
public void close() {
|
||||||
emf.close();
|
emf.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allows to override some properties in persistence.xml by system properties
|
|
||||||
protected Properties getHibernateProperties() {
|
|
||||||
Properties result = new Properties();
|
|
||||||
|
|
||||||
for (Object property : System.getProperties().keySet()) {
|
|
||||||
if (property.toString().startsWith("hibernate.")) {
|
|
||||||
String propValue = System.getProperty(property.toString());
|
|
||||||
result.put(property, propValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -928,7 +928,7 @@ public class RealmAdapter implements RealmModel {
|
||||||
realm.getRoles().remove(role);
|
realm.getRoles().remove(role);
|
||||||
realm.getDefaultRoles().remove(role);
|
realm.getDefaultRoles().remove(role);
|
||||||
|
|
||||||
em.createNativeQuery("delete from CompositeRole where role = :role").setParameter("role", roleEntity).executeUpdate();
|
em.createNativeQuery("delete from CompositeRole where childRole = :role").setParameter("role", roleEntity).executeUpdate();
|
||||||
em.createQuery("delete from " + UserRoleMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", roleEntity).executeUpdate();
|
em.createQuery("delete from " + UserRoleMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", roleEntity).executeUpdate();
|
||||||
em.createQuery("delete from " + ScopeMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", roleEntity).executeUpdate();
|
em.createQuery("delete from " + ScopeMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", roleEntity).executeUpdate();
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.keycloak.models.jpa.entities;
|
||||||
import javax.persistence.FetchType;
|
import javax.persistence.FetchType;
|
||||||
import javax.persistence.GeneratedValue;
|
import javax.persistence.GeneratedValue;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
import javax.persistence.ManyToOne;
|
import javax.persistence.ManyToOne;
|
||||||
import javax.persistence.MappedSuperclass;
|
import javax.persistence.MappedSuperclass;
|
||||||
|
|
||||||
|
@ -20,7 +21,9 @@ public class AbstractRoleMappingEntity {
|
||||||
protected String id;
|
protected String id;
|
||||||
@ManyToOne(fetch= FetchType.LAZY)
|
@ManyToOne(fetch= FetchType.LAZY)
|
||||||
protected UserEntity user;
|
protected UserEntity user;
|
||||||
|
|
||||||
@ManyToOne(fetch= FetchType.LAZY)
|
@ManyToOne(fetch= FetchType.LAZY)
|
||||||
|
@JoinColumn(name="roleId")
|
||||||
protected RoleEntity role;
|
protected RoleEntity role;
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
|
|
|
@ -8,7 +8,9 @@ import javax.persistence.ElementCollection;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.GeneratedValue;
|
import javax.persistence.GeneratedValue;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
import javax.persistence.MapKeyColumn;
|
import javax.persistence.MapKeyColumn;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
import org.hibernate.annotations.GenericGenerator;
|
import org.hibernate.annotations.GenericGenerator;
|
||||||
|
|
||||||
|
@ -16,6 +18,7 @@ import org.hibernate.annotations.GenericGenerator;
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
|
@Table(name="AuthProviderEntity")
|
||||||
public class AuthenticationProviderEntity {
|
public class AuthenticationProviderEntity {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
|
@ -30,7 +33,9 @@ public class AuthenticationProviderEntity {
|
||||||
@ElementCollection
|
@ElementCollection
|
||||||
@MapKeyColumn(name="name")
|
@MapKeyColumn(name="name")
|
||||||
@Column(name="value")
|
@Column(name="value")
|
||||||
@CollectionTable
|
@CollectionTable(name="AuthProviderEntity_cfg", joinColumns = {
|
||||||
|
@JoinColumn(name = "AuthProviderEntity_id")
|
||||||
|
})
|
||||||
private Map<String, String> config;
|
private Map<String, String> config;
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
|
|
|
@ -9,12 +9,14 @@ import javax.persistence.Id;
|
||||||
import javax.persistence.ManyToOne;
|
import javax.persistence.ManyToOne;
|
||||||
import javax.persistence.NamedQueries;
|
import javax.persistence.NamedQueries;
|
||||||
import javax.persistence.NamedQuery;
|
import javax.persistence.NamedQuery;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
|
@Table(name = "ClientUserSessionAscEntity")
|
||||||
@NamedQueries({
|
@NamedQueries({
|
||||||
@NamedQuery(name = "getAllClientUserSessions", query = "select s from ClientUserSessionAssociationEntity s"),
|
@NamedQuery(name = "getAllClientUserSessions", query = "select s from ClientUserSessionAssociationEntity s"),
|
||||||
@NamedQuery(name = "getClientUserSessionBySession", query = "select s from ClientUserSessionAssociationEntity s where s.session = :session"),
|
@NamedQuery(name = "getClientUserSessionBySession", query = "select s from ClientUserSessionAssociationEntity s where s.session = :session"),
|
||||||
|
|
|
@ -26,9 +26,7 @@ import org.hibernate.annotations.GenericGenerator;
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
@Table(uniqueConstraints = {
|
@Table(uniqueConstraints = {
|
||||||
@UniqueConstraint(columnNames = { "name", "application"}),
|
@UniqueConstraint(columnNames = { "name", "appRealmConstraint" })
|
||||||
@UniqueConstraint(columnNames = { "name", "realm" })
|
|
||||||
|
|
||||||
})
|
})
|
||||||
@NamedQueries({
|
@NamedQueries({
|
||||||
@NamedQuery(name="getAppRoleByName", query="select role from RoleEntity role where role.name = :name and role.application = :application"),
|
@NamedQuery(name="getAppRoleByName", query="select role from RoleEntity role where role.name = :name and role.application = :application"),
|
||||||
|
@ -57,8 +55,11 @@ public class RoleEntity {
|
||||||
@JoinColumn(name = "application")
|
@JoinColumn(name = "application")
|
||||||
private ApplicationEntity 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 = {})
|
@ManyToMany(fetch = FetchType.LAZY, cascade = {})
|
||||||
@JoinTable(name = "CompositeRole", joinColumns = @JoinColumn(name = "composite"), inverseJoinColumns = @JoinColumn(name = "role"))
|
@JoinTable(name = "CompositeRole", joinColumns = @JoinColumn(name = "composite"), inverseJoinColumns = @JoinColumn(name = "childRole"))
|
||||||
private Collection<RoleEntity> compositeRoles = new ArrayList<RoleEntity>();
|
private Collection<RoleEntity> compositeRoles = new ArrayList<RoleEntity>();
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
|
@ -115,6 +116,7 @@ public class RoleEntity {
|
||||||
|
|
||||||
public void setRealm(RealmEntity realm) {
|
public void setRealm(RealmEntity realm) {
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
|
this.appRealmConstraint = realm.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ApplicationEntity getApplication() {
|
public ApplicationEntity getApplication() {
|
||||||
|
@ -123,6 +125,17 @@ public class RoleEntity {
|
||||||
|
|
||||||
public void setApplication(ApplicationEntity application) {
|
public void setApplication(ApplicationEntity application) {
|
||||||
this.application = 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
|
@Override
|
||||||
|
|
|
@ -6,6 +6,7 @@ import javax.persistence.Entity;
|
||||||
import javax.persistence.FetchType;
|
import javax.persistence.FetchType;
|
||||||
import javax.persistence.GeneratedValue;
|
import javax.persistence.GeneratedValue;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
import javax.persistence.ManyToOne;
|
import javax.persistence.ManyToOne;
|
||||||
import javax.persistence.NamedQueries;
|
import javax.persistence.NamedQueries;
|
||||||
import javax.persistence.NamedQuery;
|
import javax.persistence.NamedQuery;
|
||||||
|
@ -27,7 +28,9 @@ public class ScopeMappingEntity {
|
||||||
protected String id;
|
protected String id;
|
||||||
@ManyToOne(fetch= FetchType.LAZY)
|
@ManyToOne(fetch= FetchType.LAZY)
|
||||||
protected ClientEntity client;
|
protected ClientEntity client;
|
||||||
|
|
||||||
@ManyToOne(fetch= FetchType.LAZY)
|
@ManyToOne(fetch= FetchType.LAZY)
|
||||||
|
@JoinColumn(name="roleId")
|
||||||
protected RoleEntity role;
|
protected RoleEntity role;
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.keycloak.models.jpa.entities;
|
||||||
|
|
||||||
import org.hibernate.annotations.GenericGenerator;
|
import org.hibernate.annotations.GenericGenerator;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
|
|
||||||
import javax.persistence.CascadeType;
|
import javax.persistence.CascadeType;
|
||||||
import javax.persistence.CollectionTable;
|
import javax.persistence.CollectionTable;
|
||||||
|
@ -42,7 +43,7 @@ import java.util.Set;
|
||||||
@Entity
|
@Entity
|
||||||
@Table(uniqueConstraints = {
|
@Table(uniqueConstraints = {
|
||||||
@UniqueConstraint(columnNames = { "realm", "loginName" }),
|
@UniqueConstraint(columnNames = { "realm", "loginName" }),
|
||||||
@UniqueConstraint(columnNames = { "realm", "email" })
|
@UniqueConstraint(columnNames = { "realm", "emailConstraint" })
|
||||||
})
|
})
|
||||||
public class UserEntity {
|
public class UserEntity {
|
||||||
@Id
|
@Id
|
||||||
|
@ -57,6 +58,8 @@ public class UserEntity {
|
||||||
protected boolean emailVerified;
|
protected boolean emailVerified;
|
||||||
protected int notBefore;
|
protected int notBefore;
|
||||||
|
|
||||||
|
// 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)
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
@JoinColumn(name = "realm")
|
@JoinColumn(name = "realm")
|
||||||
|
@ -116,6 +119,7 @@ public class UserEntity {
|
||||||
|
|
||||||
public void setEmail(String email) {
|
public void setEmail(String email) {
|
||||||
this.email = email;
|
this.email = email;
|
||||||
|
this.emailConstraint = email != null ? email : KeycloakModelUtils.generateId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
|
@ -126,6 +130,14 @@ public class UserEntity {
|
||||||
this.enabled = enabled;
|
this.enabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getEmailConstraint() {
|
||||||
|
return emailConstraint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmailConstraint(String emailConstraint) {
|
||||||
|
this.emailConstraint = emailConstraint;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isTotp() {
|
public boolean isTotp() {
|
||||||
return totp;
|
return totp;
|
||||||
}
|
}
|
||||||
|
|
|
@ -260,23 +260,6 @@
|
||||||
<groupId>org.mongodb</groupId>
|
<groupId>org.mongodb</groupId>
|
||||||
<artifactId>mongo-java-driver</artifactId>
|
<artifactId>mongo-java-driver</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.picketlink</groupId>
|
|
||||||
<artifactId>picketlink-common</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.picketlink</groupId>
|
|
||||||
<artifactId>picketlink-idm-api</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.picketlink</groupId>
|
|
||||||
<artifactId>picketlink-idm-impl</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.picketlink</groupId>
|
|
||||||
<artifactId>picketlink-idm-simple-schema</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- export/import -->
|
<!-- export/import -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -97,12 +97,6 @@
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-authentication-api</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-export-import-api</artifactId>
|
<artifactId>keycloak-export-import-api</artifactId>
|
||||||
|
|
Loading…
Reference in a new issue