commit
8bcb01fadb
12 changed files with 522 additions and 26 deletions
|
@ -16,4 +16,6 @@ public interface CacheKeycloakSession extends KeycloakSession {
|
|||
void registerRoleInvalidation(String id);
|
||||
|
||||
void registerOAuthClientInvalidation(String id);
|
||||
|
||||
void registerUserInvalidation(String id);
|
||||
}
|
||||
|
|
|
@ -174,8 +174,9 @@ public abstract class ClientAdapter implements ClientModel {
|
|||
|
||||
public boolean hasScope(RoleModel role) {
|
||||
if (updatedClient != null) return updatedClient.hasScope(role);
|
||||
if (cachedClient.getScope().contains(role.getId())) return true;
|
||||
|
||||
Set<RoleModel> roles = getScopeMappings();
|
||||
if (roles.contains(role)) return true;
|
||||
|
||||
for (RoleModel mapping : roles) {
|
||||
if (mapping.hasRole(role)) return true;
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.keycloak.models.cache.entities.CachedOAuthClient;
|
|||
import org.keycloak.models.cache.entities.CachedRealm;
|
||||
import org.keycloak.models.cache.entities.CachedRealmRole;
|
||||
import org.keycloak.models.cache.entities.CachedRole;
|
||||
import org.keycloak.models.cache.entities.CachedUser;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@ -41,10 +42,12 @@ public class DefaultCacheKeycloakSession implements CacheKeycloakSession {
|
|||
protected Set<String> appInvalidations = new HashSet<String>();
|
||||
protected Set<String> roleInvalidations = new HashSet<String>();
|
||||
protected Set<String> clientInvalidations = new HashSet<String>();
|
||||
protected Set<String> userInvalidations = new HashSet<String>();
|
||||
protected Map<String, RealmModel> managedRealms = new HashMap<String, RealmModel>();
|
||||
protected Map<String, ApplicationModel> managedApplications = new HashMap<String, ApplicationModel>();
|
||||
protected Map<String, OAuthClientModel> managedClients = new HashMap<String, OAuthClientModel>();
|
||||
protected Map<String, RoleModel> managedRoles = new HashMap<String, RoleModel>();
|
||||
protected Map<String, UserModel> managedUsers = new HashMap<String, UserModel>();
|
||||
|
||||
protected boolean clearAll;
|
||||
|
||||
|
@ -88,6 +91,11 @@ public class DefaultCacheKeycloakSession implements CacheKeycloakSession {
|
|||
clientInvalidations.add(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerUserInvalidation(String id) {
|
||||
userInvalidations.add(id);
|
||||
}
|
||||
|
||||
protected void runInvalidations() {
|
||||
for (String id : realmInvalidations) {
|
||||
cache.invalidateCachedRealmById(id);
|
||||
|
@ -101,6 +109,9 @@ public class DefaultCacheKeycloakSession implements CacheKeycloakSession {
|
|||
for (String id : clientInvalidations) {
|
||||
cache.invalidateCachedOAuthClientById(id);
|
||||
}
|
||||
for (String id : userInvalidations) {
|
||||
cache.invalidateCachedUserById(id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -210,17 +221,59 @@ public class DefaultCacheKeycloakSession implements CacheKeycloakSession {
|
|||
|
||||
@Override
|
||||
public UserModel getUserById(String id, RealmModel realm) {
|
||||
return getDelegate().getUserById(id, realm);
|
||||
CachedUser cached = cache.getCachedUser(id);
|
||||
if (cached == null) {
|
||||
UserModel model = getDelegate().getUserById(id, realm);
|
||||
if (model == null) return null;
|
||||
if (userInvalidations.contains(id)) return model;
|
||||
cached = new CachedUser(realm, model);
|
||||
cache.addCachedUser(cached);
|
||||
} else if (userInvalidations.contains(id)) {
|
||||
return getDelegate().getUserById(id, realm);
|
||||
} else if (managedUsers.containsKey(id)) {
|
||||
return managedUsers.get(id);
|
||||
}
|
||||
UserAdapter adapter = new UserAdapter(cached, cache, this, realm);
|
||||
managedUsers.put(id, adapter);
|
||||
return adapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserByUsername(String username, RealmModel realm) {
|
||||
return getDelegate().getUserByUsername(username, realm);
|
||||
CachedUser cached = cache.getCachedUserByUsername(username, realm);
|
||||
if (cached == null) {
|
||||
UserModel model = getDelegate().getUserByUsername(username, realm);
|
||||
if (model == null) return null;
|
||||
if (userInvalidations.contains(model.getId())) return model;
|
||||
cached = new CachedUser(realm, model);
|
||||
cache.addCachedUser(cached);
|
||||
} else if (userInvalidations.contains(cached.getId())) {
|
||||
return getDelegate().getUserById(cached.getId(), realm);
|
||||
} else if (managedUsers.containsKey(cached.getId())) {
|
||||
return managedUsers.get(cached.getId());
|
||||
}
|
||||
UserAdapter adapter = new UserAdapter(cached, cache, this, realm);
|
||||
managedUsers.put(cached.getId(), adapter);
|
||||
return adapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserByEmail(String email, RealmModel realm) {
|
||||
return getDelegate().getUserByEmail(email, realm);
|
||||
CachedUser cached = cache.getCachedUserByEmail(email, realm);
|
||||
if (cached == null) {
|
||||
UserModel model = getDelegate().getUserByEmail(email, realm);
|
||||
if (model == null) return null;
|
||||
if (userInvalidations.contains(model.getId())) return model;
|
||||
cached = new CachedUser(realm, model);
|
||||
cache.addCachedUser(cached);
|
||||
} else if (userInvalidations.contains(cached.getId())) {
|
||||
return getDelegate().getUserByEmail(email, realm);
|
||||
} else if (managedUsers.containsKey(cached.getId())) {
|
||||
return managedUsers.get(cached.getId());
|
||||
}
|
||||
UserAdapter adapter = new UserAdapter(cached, cache, this, realm);
|
||||
managedUsers.put(cached.getId(), adapter);
|
||||
return adapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package org.keycloak.models.cache;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.cache.entities.CachedApplication;
|
||||
import org.keycloak.models.cache.entities.CachedOAuthClient;
|
||||
import org.keycloak.models.cache.entities.CachedRealm;
|
||||
import org.keycloak.models.cache.entities.CachedRole;
|
||||
import org.keycloak.models.cache.entities.CachedUser;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
@ -48,4 +50,17 @@ public interface KeycloakCache {
|
|||
|
||||
|
||||
void invalidateRoleById(String id);
|
||||
|
||||
CachedUser getCachedUser(String id);
|
||||
|
||||
void invalidateCachedUser(CachedUser user);
|
||||
|
||||
void addCachedUser(CachedUser user);
|
||||
|
||||
CachedUser getCachedUserByUsername(String name, RealmModel realm);
|
||||
CachedUser getCachedUserByEmail(String name, RealmModel realm);
|
||||
|
||||
void invalidedCachedUserById(String id);
|
||||
|
||||
void invalidateCachedUserById(String id);
|
||||
}
|
||||
|
|
|
@ -278,4 +278,9 @@ public class NoCacheKeycloakSession implements CacheKeycloakSession {
|
|||
public void removeUserSessions(RealmModel realm) {
|
||||
getDelegate().removeUserSessions(realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerUserInvalidation(String id) {
|
||||
//To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,15 @@
|
|||
package org.keycloak.models.cache;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.models.KeycloakTransaction;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.cache.entities.CachedApplication;
|
||||
import org.keycloak.models.cache.entities.CachedOAuthClient;
|
||||
import org.keycloak.models.cache.entities.CachedRealm;
|
||||
import org.keycloak.models.cache.entities.CachedRole;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.provider.ProviderSessionFactory;
|
||||
import org.keycloak.models.cache.entities.CachedUser;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
|
@ -27,6 +24,121 @@ public class SimpleCache implements KeycloakCache {
|
|||
protected ConcurrentHashMap<String, CachedOAuthClient> clientCache = new ConcurrentHashMap<String, CachedOAuthClient>();
|
||||
protected ConcurrentHashMap<String, CachedRole> roleCache = new ConcurrentHashMap<String, CachedRole>();
|
||||
|
||||
protected int maxUserCacheSize = 10000;
|
||||
protected boolean userCacheEnabled = true;
|
||||
|
||||
protected Map<String, CachedUser> usersById = Collections.synchronizedMap(new LRUCache());
|
||||
protected Map<String, CachedUser> usersByUsername = new ConcurrentHashMap<String, CachedUser>();
|
||||
protected Map<String, CachedUser> usersByEmail = new ConcurrentHashMap<String, CachedUser>();
|
||||
|
||||
protected class LRUCache extends LinkedHashMap<String, CachedUser> {
|
||||
public LRUCache() {
|
||||
super(1000, 1.1F, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CachedUser put(String key, CachedUser value) {
|
||||
usersByUsername.put(value.getUsernameKey(), value);
|
||||
if (value.getEmail() != null) {
|
||||
usersByEmail.put(value.getEmailKey(), value);
|
||||
}
|
||||
return super.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CachedUser remove(Object key) {
|
||||
CachedUser user = super.remove(key);
|
||||
if (user == null) return null;
|
||||
removeUser(user);
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
usersByUsername.clear();
|
||||
usersByEmail.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<String, CachedUser> eldest) {
|
||||
boolean evict = size() > maxUserCacheSize;
|
||||
if (evict) {
|
||||
removeUser(eldest.getValue());
|
||||
}
|
||||
return evict;
|
||||
}
|
||||
|
||||
private void removeUser(CachedUser value) {
|
||||
usersByUsername.remove(value.getUsernameKey());
|
||||
if (value.getEmail() != null) usersByEmail.remove(value.getEmailKey());
|
||||
}
|
||||
}
|
||||
|
||||
public int getMaxUserCacheSize() {
|
||||
return maxUserCacheSize;
|
||||
}
|
||||
|
||||
public void setMaxUserCacheSize(int maxUserCacheSize) {
|
||||
this.maxUserCacheSize = maxUserCacheSize;
|
||||
}
|
||||
|
||||
public boolean isUserCacheEnabled() {
|
||||
return userCacheEnabled;
|
||||
}
|
||||
|
||||
public void setUserCacheEnabled(boolean userCacheEnabled) {
|
||||
this.userCacheEnabled = userCacheEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CachedUser getCachedUser(String id) {
|
||||
if (!userCacheEnabled) return null;
|
||||
return usersById.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateCachedUser(CachedUser user) {
|
||||
if (!userCacheEnabled) return;
|
||||
usersById.remove(user.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateCachedUserById(String id) {
|
||||
if (!userCacheEnabled) return;
|
||||
usersById.remove(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCachedUser(CachedUser user) {
|
||||
if (!userCacheEnabled) return;
|
||||
usersById.put(user.getId(), user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CachedUser getCachedUserByUsername(String name, RealmModel realm) {
|
||||
if (!userCacheEnabled) return null;
|
||||
CachedUser user = usersByUsername.get(realm.getId() + "." +name);
|
||||
if (user == null) return null;
|
||||
usersById.get(user.getId()); // refresh cache entry age
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CachedUser getCachedUserByEmail(String name, RealmModel realm) {
|
||||
if (!userCacheEnabled) return null;
|
||||
CachedUser user = usersByEmail.get(realm.getId() + "." +name);
|
||||
if (user == null) return null;
|
||||
usersById.get(user.getId()); // refresh cache entry age
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidedCachedUserById(String id) {
|
||||
if (!userCacheEnabled) return;
|
||||
usersById.remove(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
realmCache.clear();
|
||||
|
@ -34,6 +146,7 @@ public class SimpleCache implements KeycloakCache {
|
|||
applicationCache.clear();
|
||||
clientCache.clear();
|
||||
roleCache.clear();
|
||||
usersById.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
283
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java
vendored
Executable file
283
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java
vendored
Executable file
|
@ -0,0 +1,283 @@
|
|||
package org.keycloak.models.cache;
|
||||
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.AuthenticationLinkModel;
|
||||
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.cache.entities.CachedUser;
|
||||
|
||||
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 $
|
||||
*/
|
||||
public class UserAdapter implements UserModel {
|
||||
protected UserModel updated;
|
||||
protected CachedUser cached;
|
||||
protected KeycloakCache cache;
|
||||
protected CacheKeycloakSession cacheSession;
|
||||
protected RealmModel realm;
|
||||
|
||||
public UserAdapter(CachedUser cached, KeycloakCache cache, CacheKeycloakSession session, RealmModel realm) {
|
||||
this.cached = cached;
|
||||
this.cache = cache;
|
||||
this.cacheSession = session;
|
||||
this.realm = realm;
|
||||
}
|
||||
|
||||
protected void getDelegateForUpdate() {
|
||||
if (updated == null) {
|
||||
cacheSession.registerUserInvalidation(getId());
|
||||
updated = cacheSession.getDelegate().getUserById(getId(), realm);
|
||||
if (updated == null) throw new IllegalStateException("Not found in database");
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public String getId() {
|
||||
if (updated != null) return updated.getId();
|
||||
return cached.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLoginName() {
|
||||
if (updated != null) return updated.getLoginName();
|
||||
return cached.getLoginName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoginName(String loginName) {
|
||||
getDelegateForUpdate();
|
||||
updated.setLoginName(loginName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
if (updated != null) return updated.isEnabled();
|
||||
return cached.isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTotp() {
|
||||
if (updated != null) return updated.isTotp();
|
||||
return cached.isTotp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled) {
|
||||
getDelegateForUpdate();
|
||||
updated.setEnabled(enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String name, String value) {
|
||||
getDelegateForUpdate();
|
||||
updated.setAttribute(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(String name) {
|
||||
getDelegateForUpdate();
|
||||
updated.removeAttribute(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAttribute(String name) {
|
||||
if (updated != null) return updated.getAttribute(name);
|
||||
return cached.getAttributes().get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getAttributes() {
|
||||
if (updated != null) return updated.getAttributes();
|
||||
return cached.getAttributes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RequiredAction> getRequiredActions() {
|
||||
if (updated != null) return updated.getRequiredActions();
|
||||
return cached.getRequiredActions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRequiredAction(RequiredAction action) {
|
||||
getDelegateForUpdate();
|
||||
updated.addRequiredAction(action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRequiredAction(RequiredAction action) {
|
||||
getDelegateForUpdate();
|
||||
updated.removeRequiredAction(action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFirstName() {
|
||||
if (updated != null) return updated.getFirstName();
|
||||
return cached.getFirstName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFirstName(String firstName) {
|
||||
getDelegateForUpdate();
|
||||
updated.setFirstName(firstName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLastName() {
|
||||
if (updated != null) return updated.getLastName();
|
||||
return cached.getLastName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastName(String lastName) {
|
||||
getDelegateForUpdate();
|
||||
updated.setLastName(lastName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEmail() {
|
||||
if (updated != null) return updated.getEmail();
|
||||
return cached.getEmail();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmail(String email) {
|
||||
getDelegateForUpdate();
|
||||
updated.setEmail(email);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmailVerified() {
|
||||
if (updated != null) return updated.isEmailVerified();
|
||||
return cached.isEmailVerified();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmailVerified(boolean verified) {
|
||||
getDelegateForUpdate();
|
||||
updated.setEmailVerified(verified);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTotp(boolean totp) {
|
||||
getDelegateForUpdate();
|
||||
updated.setTotp(totp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNotBefore() {
|
||||
if (updated != null) return updated.getNotBefore();
|
||||
return cached.getNotBefore();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNotBefore(int notBefore) {
|
||||
getDelegateForUpdate();
|
||||
updated.setNotBefore(notBefore);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCredential(UserCredentialModel cred) {
|
||||
getDelegateForUpdate();
|
||||
updated.updateCredential(cred);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserCredentialValueModel> getCredentialsDirectly() {
|
||||
if (updated != null) return updated.getCredentialsDirectly();
|
||||
return cached.getCredentials();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCredentialDirectly(UserCredentialValueModel cred) {
|
||||
getDelegateForUpdate();
|
||||
updated.updateCredentialDirectly(cred);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthenticationLinkModel getAuthenticationLink() {
|
||||
if (updated != null) return updated.getAuthenticationLink();
|
||||
return cached.getAuthenticationLink();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAuthenticationLink(AuthenticationLinkModel authenticationLink) {
|
||||
getDelegateForUpdate();
|
||||
updated.setAuthenticationLink(authenticationLink);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRealmRoleMappings() {
|
||||
if (updated != null) return updated.getRealmRoleMappings();
|
||||
Set<RoleModel> roleMappings = getRoleMappings();
|
||||
Set<RoleModel> realmMappings = new HashSet<RoleModel>();
|
||||
for (RoleModel role : roleMappings) {
|
||||
RoleContainerModel container = role.getContainer();
|
||||
if (container instanceof RealmModel) {
|
||||
if (((RealmModel) container).getId().equals(realm.getId())) {
|
||||
realmMappings.add(role);
|
||||
}
|
||||
}
|
||||
}
|
||||
return realmMappings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getApplicationRoleMappings(ApplicationModel app) {
|
||||
if (updated != null) return updated.getApplicationRoleMappings(app);
|
||||
Set<RoleModel> roleMappings = getRoleMappings();
|
||||
Set<RoleModel> appMappings = new HashSet<RoleModel>();
|
||||
for (RoleModel role : roleMappings) {
|
||||
RoleContainerModel container = role.getContainer();
|
||||
if (container instanceof ApplicationModel) {
|
||||
if (((ApplicationModel) container).getId().equals(app.getId())) {
|
||||
appMappings.add(role);
|
||||
}
|
||||
}
|
||||
}
|
||||
return appMappings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRole(RoleModel role) {
|
||||
if (updated != null) return updated.hasRole(role);
|
||||
if (cached.getRoleMappings().contains(role.getId())) return true;
|
||||
|
||||
Set<RoleModel> mappings = getRoleMappings();
|
||||
for (RoleModel mapping: mappings) {
|
||||
if (mapping.hasRole(role)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void grantRole(RoleModel role) {
|
||||
getDelegateForUpdate();
|
||||
updated.grantRole(role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRoleMappings() {
|
||||
if (updated != null) return updated.getRoleMappings();
|
||||
Set<RoleModel> roles = new HashSet<RoleModel>();
|
||||
for (String id : cached.getRoleMappings()) {
|
||||
roles.add(cacheSession.getRoleById(id, realm));
|
||||
|
||||
}
|
||||
return roles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteRoleMapping(RoleModel role) {
|
||||
getDelegateForUpdate();
|
||||
updated.deleteRoleMapping(role);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package org.keycloak.models.cache.entities;
|
||||
|
||||
import org.keycloak.models.AuthenticationLinkModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserCredentialValueModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
@ -18,32 +20,40 @@ import java.util.Set;
|
|||
public class CachedUser {
|
||||
private String id;
|
||||
private String loginName;
|
||||
private String usernameKey;
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
private String email;
|
||||
private String emailKey;
|
||||
private boolean emailVerified;
|
||||
private int notBefore;
|
||||
private List<UserCredentialValueModel> credentials = new LinkedList<UserCredentialValueModel>();
|
||||
private boolean enabled;
|
||||
private boolean totp;
|
||||
private AuthenticationLinkModel authenticationLink;
|
||||
private Map<String, String> attributes = new HashMap<String, String>();
|
||||
private Set<UserModel.RequiredAction> requiredActions = new HashSet<UserModel.RequiredAction>();
|
||||
private Set<String> roleMappings = new HashSet<String>();
|
||||
|
||||
|
||||
public CachedUser(UserModel user) {
|
||||
public CachedUser(RealmModel realm, UserModel user) {
|
||||
this.id = user.getId();
|
||||
this.loginName = user.getLoginName();
|
||||
this.usernameKey = realm.getId() + "." + this.loginName;
|
||||
this.firstName = user.getFirstName();
|
||||
this.lastName = user.getLastName();
|
||||
this.attributes.putAll(user.getAttributes());
|
||||
this.email = user.getEmail();
|
||||
if (this.email != null) {
|
||||
this.emailKey = realm.getId() + "." + this.email;
|
||||
}
|
||||
this.emailVerified = user.isEmailVerified();
|
||||
this.notBefore = user.getNotBefore();
|
||||
this.credentials.addAll(user.getCredentialsDirectly());
|
||||
this.enabled = user.isEnabled();
|
||||
this.totp = user.isTotp();
|
||||
this.requiredActions.addAll(user.getRequiredActions());
|
||||
this.authenticationLink = user.getAuthenticationLink();
|
||||
for (RoleModel role : user.getRoleMappings()) {
|
||||
roleMappings.add(role.getId());
|
||||
}
|
||||
|
@ -57,6 +67,14 @@ public class CachedUser {
|
|||
return loginName;
|
||||
}
|
||||
|
||||
public String getUsernameKey() {
|
||||
return usernameKey;
|
||||
}
|
||||
|
||||
public String getEmailKey() {
|
||||
return emailKey;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
@ -100,4 +118,8 @@ public class CachedUser {
|
|||
public Set<String> getRoleMappings() {
|
||||
return roleMappings;
|
||||
}
|
||||
|
||||
public AuthenticationLinkModel getAuthenticationLink() {
|
||||
return authenticationLink;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -254,7 +254,8 @@ public class MongoKeycloakSession implements KeycloakSession {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<SocialLinkModel> getSocialLinks(UserModel user, RealmModel realm) {
|
||||
public Set<SocialLinkModel> getSocialLinks(UserModel userModel, RealmModel realm) {
|
||||
UserModel user = getUserById(userModel.getId(), realm);
|
||||
MongoUserEntity userEntity = ((UserAdapter) user).getUser();
|
||||
List<SocialLinkEntity> linkEntities = userEntity.getSocialLinks();
|
||||
|
||||
|
@ -271,7 +272,8 @@ public class MongoKeycloakSession implements KeycloakSession {
|
|||
return result;
|
||||
}
|
||||
|
||||
private SocialLinkEntity findSocialLink(UserModel user, String socialProvider) {
|
||||
private SocialLinkEntity findSocialLink(UserModel userModel, String socialProvider, RealmModel realm) {
|
||||
UserModel user = getUserById(userModel.getId(), realm);
|
||||
MongoUserEntity userEntity = ((UserAdapter) user).getUser();
|
||||
List<SocialLinkEntity> linkEntities = userEntity.getSocialLinks();
|
||||
if (linkEntities == null) {
|
||||
|
@ -289,7 +291,7 @@ public class MongoKeycloakSession implements KeycloakSession {
|
|||
|
||||
@Override
|
||||
public SocialLinkModel getSocialLink(UserModel user, String socialProvider, RealmModel realm) {
|
||||
SocialLinkEntity socialLinkEntity = findSocialLink(user, socialProvider);
|
||||
SocialLinkEntity socialLinkEntity = findSocialLink(user, socialProvider, realm);
|
||||
return socialLinkEntity != null ? new SocialLinkModel(socialLinkEntity.getSocialProvider(), socialLinkEntity.getSocialUserId(), socialLinkEntity.getSocialUsername()) : null;
|
||||
}
|
||||
|
||||
|
|
|
@ -857,18 +857,17 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean removeSocialLink(UserModel user, String socialProvider) {
|
||||
SocialLinkEntity socialLinkEntity = findSocialLink(user, socialProvider);
|
||||
public boolean removeSocialLink(UserModel userModel, String socialProvider) {
|
||||
UserModel user = getUserById(userModel.getId());
|
||||
MongoUserEntity userEntity = ((UserAdapter) user).getUser();
|
||||
SocialLinkEntity socialLinkEntity = findSocialLink(userEntity, socialProvider);
|
||||
if (socialLinkEntity == null) {
|
||||
return false;
|
||||
}
|
||||
MongoUserEntity userEntity = ((UserAdapter) user).getUser();
|
||||
|
||||
return getMongoStore().pullItemFromList(userEntity, "socialLinks", socialLinkEntity, invocationContext);
|
||||
}
|
||||
|
||||
private SocialLinkEntity findSocialLink(UserModel user, String socialProvider) {
|
||||
MongoUserEntity userEntity = ((UserAdapter) user).getUser();
|
||||
private SocialLinkEntity findSocialLink(MongoUserEntity userEntity, String socialProvider) {
|
||||
List<SocialLinkEntity> linkEntities = userEntity.getSocialLinks();
|
||||
if (linkEntities == null) {
|
||||
return null;
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
},
|
||||
|
||||
"modelCache": {
|
||||
"provider": "${keycloak.model.cache.provider:none}"
|
||||
"provider": "${keycloak.model.cache.provider:simple}"
|
||||
},
|
||||
|
||||
"timer": {
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.keycloak.models.ApplicationModel;
|
|||
import org.keycloak.models.PasswordPolicy;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserCredentialValueModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.utils.TimeBasedOTP;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
|
@ -144,7 +145,7 @@ public class AccountTest {
|
|||
|
||||
@After
|
||||
public void after() {
|
||||
keycloakRule.configure(new KeycloakSetup() {
|
||||
keycloakRule.update(new KeycloakSetup() {
|
||||
@Override
|
||||
public void config(RealmManager manager, RealmModel defaultRealm, RealmModel appRealm) {
|
||||
UserModel user = appRealm.getUser("test-user@localhost");
|
||||
|
@ -239,7 +240,7 @@ public class AccountTest {
|
|||
|
||||
@Test
|
||||
public void changePasswordWithPasswordPolicy() {
|
||||
keycloakRule.configure(new KeycloakRule.KeycloakSetup() {
|
||||
keycloakRule.update(new KeycloakRule.KeycloakSetup() {
|
||||
@Override
|
||||
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
|
||||
appRealm.setPasswordPolicy(new PasswordPolicy("length"));
|
||||
|
@ -263,11 +264,11 @@ public class AccountTest {
|
|||
|
||||
events.expectAccount(EventType.UPDATE_PASSWORD).assertEvent();
|
||||
} finally {
|
||||
keycloakRule.configure(new KeycloakRule.KeycloakSetup() {
|
||||
keycloakRule.update(new KeycloakRule.KeycloakSetup() {
|
||||
@Override
|
||||
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
|
||||
appRealm.setPasswordPolicy(new PasswordPolicy(null));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue