diff --git a/model/api/src/main/java/org/keycloak/models/KeycloakSession.java b/model/api/src/main/java/org/keycloak/models/KeycloakSession.java index 8a708a3a7b..2fbb9bd33b 100755 --- a/model/api/src/main/java/org/keycloak/models/KeycloakSession.java +++ b/model/api/src/main/java/org/keycloak/models/KeycloakSession.java @@ -11,6 +11,8 @@ import java.util.Set; * @version $Revision: 1 $ */ public interface KeycloakSession extends Provider { + // Note: The reason there are so many query methods here is for layering a cache on top of an persistent KeycloakSession + KeycloakTransaction getTransaction(); RealmModel createRealm(String name); @@ -25,11 +27,9 @@ public interface KeycloakSession extends Provider { List getUsers(RealmModel realm); List searchForUser(String search, RealmModel realm); List searchForUserByAttributes(Map attributes, RealmModel realm); - Set getRealmRoleMappings(UserModel user, RealmModel realm); Set getSocialLinks(UserModel user, RealmModel realm); SocialLinkModel getSocialLink(UserModel user, String socialProvider, RealmModel realm); - AuthenticationLinkModel getAuthenticationLink(UserModel user, RealmModel realm); RoleModel getRoleById(String id, RealmModel realm); diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheKeycloakSession.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheKeycloakSession.java index 24fe250ef9..7d909ecdbb 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheKeycloakSession.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheKeycloakSession.java @@ -204,11 +204,6 @@ public class CacheKeycloakSession implements KeycloakSession { return null; //To change body of implemented methods use File | Settings | File Templates. } - @Override - public Set getRealmRoleMappings(UserModel user, RealmModel realm) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - @Override public Set getSocialLinks(UserModel user, RealmModel realm) { return null; //To change body of implemented methods use File | Settings | File Templates. @@ -219,11 +214,6 @@ public class CacheKeycloakSession implements KeycloakSession { return null; //To change body of implemented methods use File | Settings | File Templates. } - @Override - public AuthenticationLinkModel getAuthenticationLink(UserModel user, RealmModel realm) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - @Override public RoleModel getRoleById(String id, RealmModel realm) { return null; //To change body of implemented methods use File | Settings | File Templates. diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSession.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSession.java index 5ee0b47ae3..b7dad7d13a 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSession.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSession.java @@ -3,8 +3,10 @@ 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; @@ -169,22 +171,59 @@ public class JpaKeycloakSession implements KeycloakSession { @Override public List getUsers(RealmModel realm) { - return null; //To change body of implemented methods use File | Settings | File Templates. + TypedQuery 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 results = query.getResultList(); + List users = new ArrayList(); + for (UserEntity entity : results) users.add(new UserAdapter(realm, em, entity)); + return users; } @Override public List searchForUser(String search, RealmModel realm) { - return null; //To change body of implemented methods use File | Settings | File Templates. + TypedQuery query = em.createQuery("select u from UserEntity u where u.realm = :realm and ( lower(u.loginName) 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 results = query.getResultList(); + List users = new ArrayList(); + for (UserEntity entity : results) users.add(new UserAdapter(realm, em, entity)); + return users; } @Override public List searchForUserByAttributes(Map attributes, RealmModel realm) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - public Set getRealmRoleMappings(UserModel user, RealmModel realm) { - return null; //To change body of implemented methods use File | Settings | File Templates. + StringBuilder builder = new StringBuilder("select u from UserEntity u"); + boolean first = true; + for (Map.Entry entry : attributes.entrySet()) { + String attribute = null; + if (entry.getKey().equals(UserModel.LOGIN_NAME)) { + attribute = "lower(loginName)"; + } 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 query = em.createQuery(q, UserEntity.class); + RealmEntity realmEntity = em.getReference(RealmEntity.class, realm.getId()); + query.setParameter("realm", realmEntity); + List results = query.getResultList(); + List users = new ArrayList(); + for (UserEntity entity : results) users.add(new UserAdapter(realm, em, entity)); + return users; } private SocialLinkEntity findSocialLink(UserModel user, String socialProvider) { @@ -216,14 +255,12 @@ public class JpaKeycloakSession implements KeycloakSession { return (entity != null) ? new SocialLinkModel(entity.getSocialProvider(), entity.getSocialUserId(), entity.getSocialUsername()) : null; } - @Override - public AuthenticationLinkModel getAuthenticationLink(UserModel user, RealmModel realm) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - @Override public RoleModel getRoleById(String id, RealmModel realm) { - return null; //To change body of implemented methods use File | Settings | File Templates. + 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 @@ -237,7 +274,11 @@ public class JpaKeycloakSession implements KeycloakSession { @Override public OAuthClientModel getOAuthClientById(String id, RealmModel realm) { - return null; //To change body of implemented methods use File | Settings | File Templates. + 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 @@ -275,46 +316,82 @@ public class JpaKeycloakSession implements KeycloakSession { @Override public UserSessionModel createUserSession(RealmModel realm, UserModel user, String ipAddress) { - return null; //To change body of implemented methods use File | Settings | File Templates. + 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) { - return null; //To change body of implemented methods use File | Settings | File Templates. + UserSessionEntity entity = em.find(UserSessionEntity.class, id); + return entity != null ? new UserSessionAdapter(em, realm, entity) : null; } @Override public List getUserSessions(UserModel user, RealmModel realm) { - return null; //To change body of implemented methods use File | Settings | File Templates. + List sessions = new LinkedList(); + 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 getUserSessions(RealmModel realm, ClientModel client) { - return null; //To change body of implemented methods use File | Settings | File Templates. + Set list = new HashSet(); + TypedQuery query = em.createNamedQuery("getClientUserSessionByClient", ClientUserSessionAssociationEntity.class); + String id = client.getId(); + query.setParameter("clientId", id); + List 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) { - return 0; //To change body of implemented methods use File | Settings | File Templates. + Query query = em.createNamedQuery("getActiveClientSessions"); + query.setParameter("clientId", client.getId()); + Object count = query.getSingleResult(); + return ((Number)count).intValue(); } @Override public void removeUserSession(UserSessionModel session) { - //To change body of implemented methods use File | Settings | File Templates. + em.remove(((UserSessionAdapter) session).getEntity()); } @Override public void removeUserSessions(RealmModel realm, UserModel user) { - //To change body of implemented methods use File | Settings | File Templates. + em.createNamedQuery("removeClientUserSessionByUser").setParameter("userId", user.getId()).executeUpdate(); + em.createNamedQuery("removeUserSessionByUser").setParameter("userId", user.getId()).executeUpdate(); } @Override public void removeExpiredUserSessions(RealmModel realm) { - //To change body of implemented methods use File | Settings | File Templates. + TypedQuery query = em.createNamedQuery("getUserSessionExpired", UserSessionEntity.class) + .setParameter("maxTime", Time.currentTime() - realm.getSsoSessionMaxLifespan()) + .setParameter("idleTime", Time.currentTime() - realm.getSsoSessionIdleTimeout()); + List results = query.getResultList(); + for (UserSessionEntity entity : results) { + em.remove(entity); + } } @Override public void removeUserSessions(RealmModel realm) { - //To change body of implemented methods use File | Settings | File Templates. + em.createNamedQuery("removeClientUserSessionByRealm").setParameter("realmId", realm.getId()).executeUpdate(); + em.createNamedQuery("removeRealmUserSessions").setParameter("realmId", realm.getId()).executeUpdate(); } } diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java index 9d319a6064..f972463806 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java @@ -493,7 +493,8 @@ public class RealmAdapter implements RealmModel { } private void removeUser(UserEntity user) { - removeUserSessions(user); + em.createNamedQuery("removeClientUserSessionByUser").setParameter("userId", user.getId()).executeUpdate(); + em.createNamedQuery("removeUserSessionByUser").setParameter("userId", user.getId()).executeUpdate(); em.createQuery("delete from " + UserRoleMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", user).executeUpdate(); em.createQuery("delete from " + SocialLinkEntity.class.getSimpleName() + " where user = :user").setParameter("user", user).executeUpdate(); @@ -733,55 +734,17 @@ public class RealmAdapter implements RealmModel { @Override public List getUsers() { - TypedQuery query = em.createQuery("select u from UserEntity u where u.realm = :realm", UserEntity.class); - query.setParameter("realm", realm); - List results = query.getResultList(); - List users = new ArrayList(); - for (UserEntity entity : results) users.add(new UserAdapter(this, em, entity)); - return users; + return session.getUsers(this); } @Override public List searchForUser(String search) { - TypedQuery query = em.createQuery("select u from UserEntity u where u.realm = :realm and ( lower(u.loginName) like :search or lower(concat(u.firstName, ' ', u.lastName)) like :search or u.email like :search )", UserEntity.class); - query.setParameter("realm", realm); - query.setParameter("search", "%" + search.toLowerCase() + "%"); - List results = query.getResultList(); - List users = new ArrayList(); - for (UserEntity entity : results) users.add(new UserAdapter(this, em, entity)); - return users; + return session.searchForUser(search, this); } @Override public List searchForUserByAttributes(Map attributes) { - StringBuilder builder = new StringBuilder("select u from UserEntity u"); - boolean first = true; - for (Map.Entry entry : attributes.entrySet()) { - String attribute = null; - if (entry.getKey().equals(UserModel.LOGIN_NAME)) { - attribute = "lower(loginName)"; - } 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 "); - } else { - builder.append(" and "); - } - builder.append(attribute).append(" like '%").append(entry.getValue().toLowerCase()).append("%'"); - } - String q = builder.toString(); - TypedQuery query = em.createQuery(q, UserEntity.class); - List results = query.getResultList(); - List users = new ArrayList(); - for (UserEntity entity : results) users.add(new UserAdapter(this, em, entity)); - return users; + return session.searchForUserByAttributes(attributes, this); } @Override @@ -825,11 +788,7 @@ public class RealmAdapter implements RealmModel { @Override public OAuthClientModel getOAuthClientById(String id) { - OAuthClientEntity client = em.find(OAuthClientEntity.class, id); - - // Check if client belongs to this realm - if (client == null || !this.realm.getId().equals(client.getRealm().getId())) return null; - return new OAuthClientAdapter(this, client, em); + return session.getOAuthClientById(id, this); } @@ -991,11 +950,7 @@ public class RealmAdapter implements RealmModel { @Override public RoleModel getRoleById(String id) { - RoleEntity entity = null; - entity = em.find(RoleEntity.class, id); - if (entity == null) return null; - if (!getId().equals(entity.getRealmId())) return null; - return new RoleAdapter(this, em, entity); + return session.getRoleById(id, this); } @Override @@ -1143,66 +1098,38 @@ public class RealmAdapter implements RealmModel { @Override public UserSessionModel createUserSession(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, this, entity); + return session.createUserSession(this, user, ipAddress); } @Override public UserSessionModel getUserSession(String id) { - UserSessionEntity entity = em.find(UserSessionEntity.class, id); - return entity != null ? new UserSessionAdapter(em, this, entity) : null; + return session.getUserSession(id, this); } @Override public List getUserSessions(UserModel user) { - List sessions = new LinkedList(); - for (UserSessionEntity e : em.createNamedQuery("getUserSessionByUser", UserSessionEntity.class).setParameter("userId", user.getId()).getResultList()) { - sessions.add(new UserSessionAdapter(em, this, e)); - } - return sessions; + return session.getUserSessions(user, this); } @Override public void removeUserSession(UserSessionModel session) { - em.remove(((UserSessionAdapter) session).getEntity()); + this.session.removeUserSession(session); } @Override public void removeUserSessions() { - em.createNamedQuery("removeClientUserSessionByRealm").setParameter("realmId", realm.getId()).executeUpdate(); - em.createNamedQuery("removeRealmUserSessions").setParameter("realmId", realm.getId()).executeUpdate(); + session.removeUserSessions(this); } @Override public void removeUserSessions(UserModel user) { - removeUserSessions(((UserAdapter) user).getUser()); - } - - private void removeUserSessions(UserEntity user) { - em.createNamedQuery("removeClientUserSessionByUser").setParameter("userId", user.getId()).executeUpdate(); - em.createNamedQuery("removeUserSessionByUser").setParameter("userId", user.getId()).executeUpdate(); + session.removeUserSessions(this, user); } @Override public void removeExpiredUserSessions() { - TypedQuery query = em.createNamedQuery("getUserSessionExpired", UserSessionEntity.class) - .setParameter("maxTime", Time.currentTime() - getSsoSessionMaxLifespan()) - .setParameter("idleTime", Time.currentTime() - getSsoSessionIdleTimeout()); - List results = query.getResultList(); - for (UserSessionEntity entity : results) { - em.remove(entity); - } + session.removeExpiredUserSessions(this); } } diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSession.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSession.java index 4078453e33..db58dae1d2 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSession.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSession.java @@ -172,11 +172,6 @@ public class MongoKeycloakSession implements KeycloakSession { return null; //To change body of implemented methods use File | Settings | File Templates. } - @Override - public Set getRealmRoleMappings(UserModel user, RealmModel realm) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - @Override public Set getSocialLinks(UserModel user, RealmModel realm) { return null; //To change body of implemented methods use File | Settings | File Templates. @@ -187,11 +182,6 @@ public class MongoKeycloakSession implements KeycloakSession { return null; //To change body of implemented methods use File | Settings | File Templates. } - @Override - public AuthenticationLinkModel getAuthenticationLink(UserModel user, RealmModel realm) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - @Override public RoleModel getRoleById(String id, RealmModel realm) { return null; //To change body of implemented methods use File | Settings | File Templates.