Merge pull request #532 from patriot1burke/master

jpa schema changes
This commit is contained in:
Bill Burke 2014-07-16 19:38:01 -04:00
commit 08b0aebe03
18 changed files with 289 additions and 89 deletions

View file

@ -8,6 +8,7 @@ import org.keycloak.models.SocialLinkModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserProvider;
import org.keycloak.models.jpa.entities.CredentialEntity;
import org.keycloak.models.jpa.entities.RealmEntity;
import org.keycloak.models.jpa.entities.RoleEntity;
import org.keycloak.models.jpa.entities.SocialLinkEntity;
@ -124,9 +125,18 @@ public class JpaUserProvider implements UserProvider {
@Override
public void preRemove(RealmModel realm) {
RealmEntity realmEntity = em.getReference(RealmEntity.class, realm.getId());
for (UserEntity u : em.createQuery("from UserEntity u where u.realm = :realm", UserEntity.class).setParameter("realm", realmEntity).getResultList()) {
removeUser(realm, u.getUsername());
}
int num = em.createNamedQuery("deleteUserRoleMappingsByRealm")
.setParameter("realm", realmEntity).executeUpdate();
num = em.createNamedQuery("deleteSocialLinkByRealm")
.setParameter("realm", realmEntity).executeUpdate();
num = em.createNamedQuery("deleteCredentialsByRealm")
.setParameter("realm", realmEntity).executeUpdate();
num = em.createNamedQuery("deleteUserAttributesByRealm")
.setParameter("realm", realmEntity).executeUpdate();
num = em.createNamedQuery("deleteAuthenticationLinksByRealm")
.setParameter("realm", realmEntity).executeUpdate();
num = em.createNamedQuery("deleteUsersByRealm")
.setParameter("realm", realmEntity).executeUpdate();
}
@Override

View file

@ -12,7 +12,9 @@ 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.UserAttributeEntity;
import org.keycloak.models.jpa.entities.UserEntity;
import org.keycloak.models.jpa.entities.UserRequiredActionEntity;
import org.keycloak.models.jpa.entities.UserRoleMappingEntity;
import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
@ -21,6 +23,7 @@ import javax.persistence.TypedQuery;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -79,52 +82,84 @@ public class UserAdapter implements UserModel {
@Override
public void setAttribute(String name, String value) {
Map<String, String> attributes = user.getAttributes();
if (attributes == null) {
attributes = new HashMap<String, String>();
for (UserAttributeEntity attr : user.getAttributes()) {
if (attr.getName().equals(name)) {
attr.setValue(value);
return;
}
}
attributes.put(name, value);
user.setAttributes(attributes);
UserAttributeEntity attr = new UserAttributeEntity();
attr.setName(name);
attr.setValue(value);
attr.setUser(user);
em.persist(attr);
user.getAttributes().add(attr);
}
@Override
public void removeAttribute(String name) {
Map<String, String> attributes = user.getAttributes();
if (attributes == null) {
attributes = new HashMap<String, String>();
Iterator<UserAttributeEntity> it = user.getAttributes().iterator();
while (it.hasNext()) {
UserAttributeEntity attr = it.next();
if (attr.getName().equals(name)) {
it.remove();
em.remove(attr);
}
}
attributes.remove(name);
user.setAttributes(attributes);
}
@Override
public String getAttribute(String name) {
if (user.getAttributes() == null) return null;
return user.getAttributes().get(name);
for (UserAttributeEntity attr : user.getAttributes()) {
if (attr.getName().equals(name)) {
return attr.getValue();
}
}
return null;
}
@Override
public Map<String, String> getAttributes() {
Map<String, String> result = new HashMap<String, String>();
result.putAll(user.getAttributes());
for (UserAttributeEntity attr : user.getAttributes()) {
result.put(attr.getName(), attr.getValue());
}
return result;
}
@Override
public Set<RequiredAction> getRequiredActions() {
Set<RequiredAction> result = new HashSet<RequiredAction>();
result.addAll(user.getRequiredActions());
for (UserRequiredActionEntity attr : user.getRequiredActions()) {
result.add(attr.getAction());
}
return result;
}
@Override
public void addRequiredAction(RequiredAction action) {
user.getRequiredActions().add(action);
for (UserRequiredActionEntity attr : user.getRequiredActions()) {
if (attr.getAction().equals(action)) {
return;
}
}
UserRequiredActionEntity attr = new UserRequiredActionEntity();
attr.setAction(action);
attr.setUser(user);
em.persist(attr);
user.getRequiredActions().add(attr);
}
@Override
public void removeRequiredAction(RequiredAction action) {
user.getRequiredActions().remove(action);
Iterator<UserRequiredActionEntity> it = user.getRequiredActions().iterator();
while (it.hasNext()) {
UserRequiredActionEntity attr = it.next();
if (attr.getAction().equals(action)) {
it.remove();
em.remove(attr);
}
}
}
@ -357,10 +392,17 @@ public class UserAdapter implements UserModel {
AuthenticationLinkEntity entity = new AuthenticationLinkEntity();
entity.setAuthProvider(authenticationLink.getAuthProvider());
entity.setAuthUserId(authenticationLink.getAuthUserId());
entity.setUser(user);
user.setAuthenticationLink(entity);
if (user.getAuthenticationLink() != null) {
AuthenticationLinkEntity old = user.getAuthenticationLink();
old.setUser(null);
em.remove(old);
user.setAuthenticationLink(null);
em.flush();
}
em.persist(entity);
em.persist(user);
user.setAuthenticationLink(entity);
em.flush();
}

View file

@ -2,31 +2,46 @@ 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.JoinColumn;
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>
*/
@NamedQueries({
@NamedQuery(name="deleteAuthenticationLinksByRealm", query="delete from AuthenticationLinkEntity authLink where authLink.user IN (select u from UserEntity u where realm=:realm)")
})
@Entity
public class AuthenticationLinkEntity {
@Id
@Column(length = 36)
@GenericGenerator(name="keycloak_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
@GeneratedValue(generator = "keycloak_generator")
private String id;
@GeneratedValue
protected long id;
protected String authProvider;
protected String authUserId;
public String getId() {
// NOTE: @OnetoOne creates a constraint race condition if the join column is on AuthenticationLinkEntity.
// The race is that user gets loaded concurrently, creates link concurrently, and sets it. Therefore, we have
// a @ManyToOne on both sides. Broken yes, but, I think we're going to replace AuthenticationLinkEntity anyways.
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="userId")
protected UserEntity user;
public long getId() {
return id;
}
public void setId(String id) {
public void setId(long id) {
this.id = id;
}
@ -45,4 +60,12 @@ public class AuthenticationLinkEntity {
public void setAuthUserId(String authUserId) {
this.authUserId = authUserId;
}
public UserEntity getUser() {
return user;
}
public void setUser(UserEntity user) {
this.user = user;
}
}

View file

@ -21,10 +21,8 @@ import java.util.Map;
public class AuthenticationProviderEntity {
@Id
@Column(length = 36)
@GenericGenerator(name="keycloak_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
@GeneratedValue(generator = "keycloak_generator")
protected String id;
@GeneratedValue
protected long id;
private String providerName;
private boolean passwordUpdateSupported;
@ -38,11 +36,11 @@ public class AuthenticationProviderEntity {
})
private Map<String, String> config;
public String getId() {
public long getId() {
return id;
}
public void setId(String id) {
public void setId(long id) {
this.id = id;
}

View file

@ -5,6 +5,7 @@ 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;
@ -16,15 +17,15 @@ import org.hibernate.annotations.GenericGenerator;
* @version $Revision: 1 $
*/
@NamedQueries({
@NamedQuery(name="credentialByUserAndType", query="select cred from CredentialEntity cred where cred.user = :user and cred.type = :type")
@NamedQuery(name="credentialByUserAndType", query="select cred from CredentialEntity cred where cred.user = :user and cred.type = :type"),
@NamedQuery(name="deleteCredentialsByRealm", query="delete from CredentialEntity cred where cred.user IN (select u from UserEntity u where realm=:realm)")
})
@Entity
public class CredentialEntity {
@Id
@Column(length = 36)
@GenericGenerator(name="keycloak_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
@GeneratedValue(generator = "keycloak_generator")
protected String id;
@GeneratedValue
protected long id;
protected String type;
protected String value;
@ -33,10 +34,16 @@ public class CredentialEntity {
protected int hashIterations;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="userId")
protected UserEntity user;
@ManyToOne(fetch = FetchType.LAZY)
protected RealmEntity realm;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getValue() {
return value;
@ -54,14 +61,6 @@ public class CredentialEntity {
this.type = type;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDevice() {
return device;
}

View file

@ -14,21 +14,19 @@ import org.hibernate.annotations.GenericGenerator;
@Entity
public class RequiredCredentialEntity {
@Id
@Column(length = 36)
@GenericGenerator(name="keycloak_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
@GeneratedValue(generator = "keycloak_generator")
protected String id;
@GeneratedValue
protected long id;
protected String type;
protected boolean input;
protected boolean secret;
protected String formLabel;
public String getId() {
public long getId() {
return id;
}
public void setId(String id) {
public void setId(long id) {
this.id = id;
}

View file

@ -24,10 +24,9 @@ import javax.persistence.NamedQuery;
@Entity
public class ScopeMappingEntity {
@Id
@Column(length = 36)
@GenericGenerator(name="keycloak_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
@GeneratedValue(generator = "keycloak_generator")
protected String id;
@GeneratedValue
protected long id;
@ManyToOne(fetch= FetchType.LAZY)
protected ClientEntity client;
@ -35,11 +34,11 @@ public class ScopeMappingEntity {
@JoinColumn(name="roleId")
protected RoleEntity role;
public String getId() {
public long getId() {
return id;
}
public void setId(String id) {
public void setId(long id) {
this.id = id;
}

View file

@ -5,6 +5,7 @@ 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;
@ -18,15 +19,14 @@ import org.hibernate.annotations.GenericGenerator;
@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")
@NamedQuery(name="findUserByLinkAndRealm", query="select link.user from SocialLinkEntity link where link.realm = :realm and link.socialProvider = :socialProvider and link.socialUserId = :socialUserId"),
@NamedQuery(name="deleteSocialLinkByRealm", query="delete from SocialLinkEntity social where social.user IN (select u from UserEntity u where realm=:realm)")
})
@Entity
public class SocialLinkEntity {
@Id
@Column(length = 36)
@GenericGenerator(name="keycloak_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
@GeneratedValue(generator = "keycloak_generator")
private String id;
@GeneratedValue
protected long id;
@ManyToOne(fetch = FetchType.LAZY)
private UserEntity user;
@ -38,11 +38,11 @@ public class SocialLinkEntity {
protected String socialUserId;
protected String socialUsername;
public String getId() {
public long getId() {
return id;
}
public void setId(String id) {
public void setId(long id) {
this.id = id;
}

View file

@ -0,0 +1,66 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.EmbeddedId;
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.MapsId;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import java.io.Serializable;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@NamedQueries({
@NamedQuery(name="deleteUserAttributesByRealm", query="delete from UserAttributeEntity attr where attr.user IN (select u from UserEntity u where realm=:realm)")
})
@Entity
public class UserAttributeEntity {
@Id
@GeneratedValue
protected long id;
@ManyToOne(fetch= FetchType.LAZY)
protected UserEntity user;
protected String name;
protected String value;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public UserEntity getUser() {
return user;
}
public void setUser(UserEntity user) {
this.user = user;
}
}

View file

@ -35,7 +35,8 @@ import java.util.Set;
@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")
@NamedQuery(name="getRealmUserByFirstLastName", query="select u from UserEntity u where u.firstName = :first and u.lastName = :last and u.realm = :realm"),
@NamedQuery(name="deleteUsersByRealm", query="delete from UserEntity u where u.realm = :realm")
})
@Entity
@Table(uniqueConstraints = {
@ -62,20 +63,17 @@ public class UserEntity {
@JoinColumn(name = "realm")
protected RealmEntity realm;
@ElementCollection
@MapKeyColumn(name="name")
@Column(name="value")
@CollectionTable
protected Map<String, String> attributes = new HashMap<String, String>();
@OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="user")
protected Collection<UserAttributeEntity> attributes = new ArrayList<UserAttributeEntity>();
@ElementCollection
@CollectionTable
protected Set<UserModel.RequiredAction> requiredActions = new HashSet<UserModel.RequiredAction>();
@OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="user")
protected Collection<UserRequiredActionEntity> requiredActions = new ArrayList<UserRequiredActionEntity>();
@OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true)
@OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="user")
protected Collection<CredentialEntity> credentials = new ArrayList<CredentialEntity>();
@OneToOne(cascade = CascadeType.REMOVE, orphanRemoval = true)
@ManyToOne
@JoinColumn(name="link_id")
protected AuthenticationLinkEntity authenticationLink;
public String getId() {
@ -151,19 +149,19 @@ public class UserEntity {
this.emailVerified = emailVerified;
}
public Map<String, String> getAttributes() {
public Collection<UserAttributeEntity> getAttributes() {
return attributes;
}
public void setAttributes(Map<String, String> attributes) {
public void setAttributes(Collection<UserAttributeEntity> attributes) {
this.attributes = attributes;
}
public Set<UserModel.RequiredAction> getRequiredActions() {
public Collection<UserRequiredActionEntity> getRequiredActions() {
return requiredActions;
}
public void setRequiredActions(Set<UserModel.RequiredAction> requiredActions) {
public void setRequiredActions(Collection<UserRequiredActionEntity> requiredActions) {
this.requiredActions = requiredActions;
}

View file

@ -0,0 +1,53 @@
package org.keycloak.models.jpa.entities;
import org.keycloak.models.UserModel;
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="deleteUserRequiredActionsByRealm", query="delete from UserRequiredActionEntity action where action.user IN (select u from UserEntity u where realm=:realm)")
})
@Entity
public class UserRequiredActionEntity {
@Id
@GeneratedValue
protected long id;
@ManyToOne(fetch= FetchType.LAZY)
@JoinColumn(name="userId")
protected UserEntity user;
protected UserModel.RequiredAction action;
public long getId() {
return id;
}
public UserModel.RequiredAction getAction() {
return action;
}
public void setAction(UserModel.RequiredAction action) {
this.action = action;
}
public UserEntity getUser() {
return user;
}
public void setUser(UserEntity user) {
this.user = user;
}
}

View file

@ -19,27 +19,29 @@ import org.hibernate.annotations.GenericGenerator;
@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")
@NamedQuery(name="userRoleMappingIds", query="select m.role.id from UserRoleMappingEntity m where m.user = :user"),
@NamedQuery(name="deleteUserRoleMappingsByRealm", query="delete from UserRoleMappingEntity mapping where mapping.user IN (select u from UserEntity u where realm=:realm)")
})
@Entity
public class UserRoleMappingEntity {
@Id
@Column(length = 36)
@GenericGenerator(name="keycloak_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
@GeneratedValue(generator = "keycloak_generator")
protected String id;
@GeneratedValue
protected long id;
@ManyToOne(fetch= FetchType.LAZY)
@JoinColumn(name="userId")
protected UserEntity user;
@ManyToOne(fetch= FetchType.LAZY)
@JoinColumn(name="roleId")
protected RoleEntity role;
public String getId() {
public long getId() {
return id;
}
public void setId(String id) {
public void setId(long id) {
this.id = id;
}

View file

@ -15,6 +15,8 @@
<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.UserAttributeEntity</class>
<class>org.keycloak.models.jpa.entities.UserRequiredActionEntity</class>
<class>org.keycloak.models.jpa.entities.UserRoleMappingEntity</class>
<class>org.keycloak.models.jpa.entities.ScopeMappingEntity</class>

View file

@ -14,6 +14,8 @@
<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.UserAttributeEntity</class>
<class>org.keycloak.models.jpa.entities.UserRequiredActionEntity</class>
<class>org.keycloak.models.jpa.entities.UserRoleMappingEntity</class>
<class>org.keycloak.models.jpa.entities.ScopeMappingEntity</class>

View file

@ -14,6 +14,8 @@
<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.UserRequiredActionEntity</class>
<class>org.keycloak.models.jpa.entities.UserAttributeEntity</class>
<class>org.keycloak.models.jpa.entities.UserRoleMappingEntity</class>
<class>org.keycloak.models.jpa.entities.ScopeMappingEntity</class>

View file

@ -15,6 +15,8 @@
<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.UserAttributeEntity</class>
<class>org.keycloak.models.jpa.entities.UserRequiredActionEntity</class>
<class>org.keycloak.models.jpa.entities.UserRoleMappingEntity</class>
<class>org.keycloak.models.jpa.entities.ScopeMappingEntity</class>

View file

@ -15,6 +15,8 @@
<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.UserAttributeEntity</class>
<class>org.keycloak.models.jpa.entities.UserRequiredActionEntity</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>

View file

@ -14,6 +14,8 @@
<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.UserAttributeEntity</class>
<class>org.keycloak.models.jpa.entities.UserRequiredActionEntity</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>