cache implement
This commit is contained in:
parent
30b95e0a57
commit
bb2ad656a3
5 changed files with 117 additions and 133 deletions
|
@ -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<UserModel> getUsers(RealmModel realm);
|
||||
List<UserModel> searchForUser(String search, RealmModel realm);
|
||||
List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm);
|
||||
Set<RoleModel> getRealmRoleMappings(UserModel user, RealmModel realm);
|
||||
|
||||
Set<SocialLinkModel> 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);
|
||||
|
|
|
@ -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<RoleModel> getRealmRoleMappings(UserModel user, RealmModel realm) {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SocialLinkModel> 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.
|
||||
|
|
|
@ -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<UserModel> getUsers(RealmModel realm) {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
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) {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
TypedQuery<UserEntity> 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<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) {
|
||||
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<String, String> 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)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRealmRoleMappings(UserModel user, RealmModel realm) {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
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) {
|
||||
|
@ -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<UserSessionModel> getUserSessions(UserModel user, RealmModel realm) {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
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) {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
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) {
|
||||
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<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) {
|
||||
//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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<UserModel> getUsers() {
|
||||
TypedQuery<UserEntity> query = em.createQuery("select u from UserEntity u where u.realm = :realm", UserEntity.class);
|
||||
query.setParameter("realm", realm);
|
||||
List<UserEntity> results = query.getResultList();
|
||||
List<UserModel> users = new ArrayList<UserModel>();
|
||||
for (UserEntity entity : results) users.add(new UserAdapter(this, em, entity));
|
||||
return users;
|
||||
return session.getUsers(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUser(String search) {
|
||||
TypedQuery<UserEntity> 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<UserEntity> results = query.getResultList();
|
||||
List<UserModel> users = new ArrayList<UserModel>();
|
||||
for (UserEntity entity : results) users.add(new UserAdapter(this, em, entity));
|
||||
return users;
|
||||
return session.searchForUser(search, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUserByAttributes(Map<String, String> attributes) {
|
||||
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(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<UserEntity> query = em.createQuery(q, UserEntity.class);
|
||||
List<UserEntity> results = query.getResultList();
|
||||
List<UserModel> users = new ArrayList<UserModel>();
|
||||
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<UserSessionModel> getUserSessions(UserModel user) {
|
||||
List<UserSessionModel> sessions = new LinkedList<UserSessionModel>();
|
||||
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<UserSessionEntity> query = em.createNamedQuery("getUserSessionExpired", UserSessionEntity.class)
|
||||
.setParameter("maxTime", Time.currentTime() - getSsoSessionMaxLifespan())
|
||||
.setParameter("idleTime", Time.currentTime() - getSsoSessionIdleTimeout());
|
||||
List<UserSessionEntity> results = query.getResultList();
|
||||
for (UserSessionEntity entity : results) {
|
||||
em.remove(entity);
|
||||
}
|
||||
session.removeExpiredUserSessions(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<RoleModel> getRealmRoleMappings(UserModel user, RealmModel realm) {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SocialLinkModel> 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.
|
||||
|
|
Loading…
Reference in a new issue