model refactor for caching

This commit is contained in:
Bill Burke committed 2014-06-10 18:50:08 -04:00
1 parent 2f3c8bf079
commit 0dd06e3343
65 files changed
+1508 -741

No files matched your search

@@ -1,14 +1,21 @@
package org.keycloak.models.cache;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.AuthenticationLinkModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakTransaction;
import org.keycloak.models.OAuthClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.SocialLinkModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.cache.entities.CachedRealm;
import org.keycloak.models.cache.entities.CachedRole;
import org.keycloak.provider.ProviderSession;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
@@ -116,7 +123,7 @@ public class CacheKeycloakSession implements KeycloakSession {
if (cached == null) {
RealmModel model = getDelegate().getRealm(id);
if (model == null) return null;
cached = new CachedRealm(model);
cached = new CachedRealm(cache, this, model);
}
return new RealmAdapter(cached, this);
}
@@ -127,23 +134,23 @@ public class CacheKeycloakSession implements KeycloakSession {
if (cached == null) {
RealmModel model = getDelegate().getRealmByName(name);
if (model == null) return null;
cached = new CachedRealm(model);
cached = new CachedRealm(cache, this, model);
}
return new RealmAdapter(cached, this);
}
@Override
public UserModel getUserById(String id, String realmId) {
public UserModel getUserById(String id, RealmModel realm) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public UserModel getUserByUsername(String username, String realmId) {
public UserModel getUserByUsername(String username, RealmModel realm) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public UserModel getUserByEmail(String email, String realmId) {
public UserModel getUserByEmail(String email, RealmModel realm) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@@ -173,4 +180,59 @@ public class CacheKeycloakSession implements KeycloakSession {
public void close() {
if (sessionDelegate != null) sessionDelegate.close();
}
@Override
public UserModel getUserBySocialLink(SocialLinkModel socialLink, RealmModel realm) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public List<UserModel> getUsers(RealmModel realm) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public List<UserModel> searchForUser(String search, RealmModel realm) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm) {
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.
}
@Override
public SocialLinkModel getSocialLink(UserModel user, String socialProvider, RealmModel realm) {
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.
}
@Override
public ApplicationModel getApplicationById(String id, RealmModel realm) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public OAuthClientModel getOAuthClientById(String id, RealmModel realm) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
}
@@ -1,12 +1,17 @@
package org.keycloak.models.cache;
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;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface KeycloakCache {
void clear();
CachedRealm getCachedRealm(String id);
void invalidateCachedRealm(CachedRealm realm);
@@ -15,7 +20,31 @@ public interface KeycloakCache {
CachedRealm getCachedRealmByName(String name);
void clear();
void invalidateCachedRealmById(String id);
CachedApplication getApplication(String id);
void invalidateApplication(CachedApplication app);
void addCachedApplication(CachedApplication app);
void invalidateCachedApplicationById(String id);
CachedOAuthClient getOAuthClient(String id);
void invalidateOAuthClient(CachedOAuthClient client);
void addCachedOAuthClient(CachedOAuthClient client);
void invalidateCachedOAuthClientById(String id);
CachedRole getRole(String id);
void invalidateRole(CachedRole role);
void addCachedRole(CachedRole role);
void invalidateCachedRoleById(String id);
}
@@ -15,12 +15,18 @@ import org.keycloak.models.UserCredentialValueModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.UsernameLoginFailureModel;
import org.keycloak.models.cache.entities.CachedApplicationRole;
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.utils.KeycloakModelUtils;
import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
import org.keycloak.models.utils.TimeBasedOTP;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -34,6 +40,7 @@ public class RealmAdapter implements RealmModel {
protected CachedRealm cached;
protected CacheKeycloakSession cacheSession;
protected RealmModel updated;
protected KeycloakCache cache;
protected volatile transient PublicKey publicKey;
protected volatile transient PrivateKey privateKey;
@@ -62,7 +69,7 @@ public class RealmAdapter implements RealmModel {
protected void getDelegateForUpdate() {
if (updated == null) {
updated = cacheSession.getRealm(getId());
updated = cacheSession.getDelegate().getRealm(getId());
if (updated == null) throw new IllegalStateException("Not found in database");
}
}
@@ -376,272 +383,352 @@ public class RealmAdapter implements RealmModel {
@Override
public boolean validatePassword(UserModel user, String password) {
return false; //To change body of implemented methods use File | Settings | File Templates.
for (UserCredentialValueModel cred : user.getCredentialsDirectly()) {
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
return new Pbkdf2PasswordEncoder(cred.getSalt()).verify(password, cred.getValue());
}
}
return false;
}
@Override
public boolean validateTOTP(UserModel user, String password, String token) {
return false; //To change body of implemented methods use File | Settings | File Templates.
if (!validatePassword(user, password)) return false;
for (UserCredentialValueModel cred : user.getCredentialsDirectly()) {
if (cred.getType().equals(UserCredentialModel.TOTP)) {
return new TimeBasedOTP().validate(token, cred.getValue().getBytes());
}
}
return false;
}
@Override
public UserModel getUser(String name) {
return null; //To change body of implemented methods use File | Settings | File Templates.
return cacheSession.getUserByUsername(name, this);
}
@Override
public UserModel getUserByEmail(String email) {
return null; //To change body of implemented methods use File | Settings | File Templates.
return cacheSession.getUserByEmail(email, this);
}
@Override
public UserModel getUserById(String name) {
return null; //To change body of implemented methods use File | Settings | File Templates.
public UserModel getUserById(String id) {
return cacheSession.getUserById(id, this);
}
@Override
public UserModel addUser(String id, String username) {
return null; //To change body of implemented methods use File | Settings | File Templates.
getDelegateForUpdate();
return updated.addUser(id, username);
}
@Override
public UserModel addUser(String username) {
return null; //To change body of implemented methods use File | Settings | File Templates.
getDelegateForUpdate();
return updated.addUser(username);
}
@Override
public boolean removeUser(String name) {
return false; //To change body of implemented methods use File | Settings | File Templates.
getDelegateForUpdate();
return updated.removeUser(name);
}
@Override
public RoleModel getRoleById(String id) {
return null; //To change body of implemented methods use File | Settings | File Templates.
if (updated != null) return updated.getRoleById(id);
if (!cached.getRolesById().contains(id)) return null;
CachedRole cachedRole = cache.getRole(id);
if (cachedRole == null) {
RoleModel roleModel = cacheSession.getDelegate().getRoleById(id, this);
if (roleModel == null) return null;
if (roleModel.getContainer() instanceof ApplicationModel) {
cachedRole = new CachedApplicationRole(((ApplicationModel) roleModel.getContainer()).getId(), roleModel);
cache.addCachedRole(cachedRole);
} else {
cachedRole = new CachedRealmRole(roleModel);
}
}
return new RoleAdapter(cachedRole, cache, cacheSession, this);
}
@Override
public List<String> getDefaultRoles() {
return null; //To change body of implemented methods use File | Settings | File Templates.
if (updated != null) return updated.getDefaultRoles();
return cached.getDefaultRoles();
}
@Override
public void addDefaultRole(String name) {
//To change body of implemented methods use File | Settings | File Templates.
getDelegateForUpdate();
updated.addDefaultRole(name);
}
@Override
public void updateDefaultRoles(String[] defaultRoles) {
//To change body of implemented methods use File | Settings | File Templates.
getDelegateForUpdate();
updated.updateDefaultRoles(defaultRoles);
}
@Override
public ClientModel findClient(String clientId) {
return null; //To change body of implemented methods use File | Settings | File Templates.
if (updated != null) return updated.findClient(clientId);
String appId = cached.getApplications().get(clientId);
if (appId != null) {
return cacheSession.getApplicationById(appId, this);
}
String oauth = cached.getClients().get(clientId);
if (oauth != null) {
return cacheSession.getOAuthClientById(oauth, this);
}
return null;
}
@Override
public Map<String, ApplicationModel> getApplicationNameMap() {
return null; //To change body of implemented methods use File | Settings | File Templates.
if (updated != null) return updated.getApplicationNameMap();
Map<String, ApplicationModel> map = new HashMap<String, ApplicationModel>();
for (String id : cached.getApplications().values()) {
ApplicationModel model = cacheSession.getApplicationById(id, this);
if (model == null) {
throw new IllegalStateException("Cached application not found: " + id);
}
map.put(model.getName(), model);
}
return map;
}
@Override
public List<ApplicationModel> getApplications() {
return null; //To change body of implemented methods use File | Settings | File Templates.
if (updated != null) return updated.getApplications();
List<ApplicationModel> apps = new LinkedList<ApplicationModel>();
for (String id : cached.getApplications().values()) {
ApplicationModel model = cacheSession.getApplicationById(id, this);
if (model == null) {
throw new IllegalStateException("Cached application not found: " + id);
}
apps.add(model);
}
return apps;
}
@Override
public ApplicationModel addApplication(String name) {
return null; //To change body of implemented methods use File | Settings | File Templates.
getDelegateForUpdate();
return updated.addApplication(name);
}
@Override
public ApplicationModel addApplication(String id, String name) {
return null; //To change body of implemented methods use File | Settings | File Templates.
getDelegateForUpdate();
return updated.addApplication(id, name);
}
@Override
public boolean removeApplication(String id) {
return false; //To change body of implemented methods use File | Settings | File Templates.
getDelegateForUpdate();
return updated.removeApplication(id);
}
@Override
public ApplicationModel getApplicationById(String id) {
return null; //To change body of implemented methods use File | Settings | File Templates.
if (updated != null) return updated.getApplicationById(id);
return cacheSession.getApplicationById(id, this);
}
@Override
public ApplicationModel getApplicationByName(String name) {
return null; //To change body of implemented methods use File | Settings | File Templates.
if (updated != null) return updated.getApplicationByName(name);
String id = cached.getApplications().get(name);
if (id == null) return null;
return getApplicationById(id);
}
@Override
public void updateRequiredCredentials(Set<String> creds) {
//To change body of implemented methods use File | Settings | File Templates.
getDelegateForUpdate();
updated.updateRequiredCredentials(creds);
}
@Override
public UserModel getUserBySocialLink(SocialLinkModel socialLink) {
return null; //To change body of implemented methods use File | Settings | File Templates.
if (updated != null) return updated.getUserBySocialLink(socialLink);
return cacheSession.getUserBySocialLink(socialLink, this);
}
@Override
public Set<SocialLinkModel> getSocialLinks(UserModel user) {
return null; //To change body of implemented methods use File | Settings | File Templates.
if (updated != null) return updated.getSocialLinks(user);
return cacheSession.getSocialLinks(user, this);
}
@Override
public SocialLinkModel getSocialLink(UserModel user, String socialProvider) {
return null; //To change body of implemented methods use File | Settings | File Templates.
if (updated != null) return updated.getSocialLink(user, socialProvider);
return cacheSession.getSocialLink(user, socialProvider, this);
}
@Override
public void addSocialLink(UserModel user, SocialLinkModel socialLink) {
//To change body of implemented methods use File | Settings | File Templates.
getDelegateForUpdate();
updated.addSocialLink(user, socialLink);
}
@Override
public boolean removeSocialLink(UserModel user, String socialProvider) {
return false; //To change body of implemented methods use File | Settings | File Templates.
getDelegateForUpdate();
return updated.removeSocialLink(user, socialProvider);
}
@Override
public AuthenticationLinkModel getAuthenticationLink(UserModel user) {
return null; //To change body of implemented methods use File | Settings | File Templates.
if (updated != null) return updated.getAuthenticationLink(user);
return cacheSession.getAuthenticationLink(user, this);
}
@Override
public void setAuthenticationLink(UserModel user, AuthenticationLinkModel authenticationLink) {
//To change body of implemented methods use File | Settings | File Templates.
getDelegateForUpdate();
updated.setAuthenticationLink(user, authenticationLink);
}
@Override
public boolean isSocial() {
return false; //To change body of implemented methods use File | Settings | File Templates.
if (updated != null) return updated.isSocial();
return cached.isSocial();
}
@Override
public void setSocial(boolean social) {
//To change body of implemented methods use File | Settings | File Templates.
getDelegateForUpdate();
updated.setSocial(social);
}
@Override
public boolean isUpdateProfileOnInitialSocialLogin() {
return false; //To change body of implemented methods use File | Settings | File Templates.
if (updated != null) return updated.isUpdateProfileOnInitialSocialLogin();
return cached.isUpdateProfileOnInitialSocialLogin();
}
@Override
public void setUpdateProfileOnInitialSocialLogin(boolean updateProfileOnInitialSocialLogin) {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public UsernameLoginFailureModel getUserLoginFailure(String username) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public UsernameLoginFailureModel addUserLoginFailure(String username) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public List<UsernameLoginFailureModel> getAllUserLoginFailures() {
return null; //To change body of implemented methods use File | Settings | File Templates.
getDelegateForUpdate();
updated.setUpdateProfileOnInitialSocialLogin(updateProfileOnInitialSocialLogin);
}
@Override
public List<UserModel> getUsers() {
return null; //To change body of implemented methods use File | Settings | File Templates.
if (updated != null) return updated.getUsers();
return cacheSession.getUsers(this);
}
@Override
public List<UserModel> searchForUser(String search) {
return null; //To change body of implemented methods use File | Settings | File Templates.
if (updated != null) return updated.searchForUser(search);
return cacheSession.searchForUser(search, this);
}
@Override
public List<UserModel> searchForUserByAttributes(Map<String, String> attributes) {
return null; //To change body of implemented methods use File | Settings | File Templates.
if (updated != null) return updated.searchForUserByAttributes(attributes);
return cacheSession.searchForUserByAttributes(attributes, this);
}
@Override
public OAuthClientModel addOAuthClient(String name) {
return null; //To change body of implemented methods use File | Settings | File Templates.
getDelegateForUpdate();
return updated.addOAuthClient(name);
}
@Override
public OAuthClientModel addOAuthClient(String id, String name) {
return null; //To change body of implemented methods use File | Settings | File Templates.
getDelegateForUpdate();
return updated.addOAuthClient(id, name);
}
@Override
public OAuthClientModel getOAuthClient(String name) {
return null; //To change body of implemented methods use File | Settings | File Templates.
if (updated != null) return updated.getOAuthClient(name);
String id = cached.getClients().get(name);
if (id == null) return null;
return getOAuthClientById(id);
}
@Override
public OAuthClientModel getOAuthClientById(String id) {
return null; //To change body of implemented methods use File | Settings | File Templates.
if (updated != null) return updated.getOAuthClientById(id);
return cacheSession.getOAuthClientById(id, this);
}
@Override
public boolean removeOAuthClient(String id) {
return false; //To change body of implemented methods use File | Settings | File Templates.
getDelegateForUpdate();
return updated.removeOAuthClient(id);
}
@Override
public List<OAuthClientModel> getOAuthClients() {
return null; //To change body of implemented methods use File | Settings | File Templates.
if (updated != null) return updated.getOAuthClients();
List<OAuthClientModel> clients = new LinkedList<OAuthClientModel>();
for (String id : cached.getClients().values()) {
OAuthClientModel model = cacheSession.getOAuthClientById(id, this);
if (model == null) {
throw new IllegalStateException("Cached oauth client not found: " + id);
}
clients.add(model);
}
return clients;
}
@Override
public Map<String, String> getSmtpConfig() {
return null; //To change body of implemented methods use File | Settings | File Templates.
if (updated != null) return updated.getSmtpConfig();
return cached.getSmtpConfig();
}
@Override
public void setSmtpConfig(Map<String, String> smtpConfig) {
//To change body of implemented methods use File | Settings | File Templates.
getDelegateForUpdate();
updated.setSmtpConfig(smtpConfig);
}
@Override
public Map<String, String> getSocialConfig() {
return null; //To change body of implemented methods use File | Settings | File Templates.
if (updated != null) return updated.getSocialConfig();
return cached.getSocialConfig();
}
@Override
public void setSocialConfig(Map<String, String> socialConfig) {
//To change body of implemented methods use File | Settings | File Templates.
getDelegateForUpdate();
updated.setSocialConfig(socialConfig);
}
@Override
public Map<String, String> getLdapServerConfig() {
return null; //To change body of implemented methods use File | Settings | File Templates.
if (updated != null) return updated.getLdapServerConfig();
return cached.getLdapServerConfig();
}
@Override
public void setLdapServerConfig(Map<String, String> ldapServerConfig) {
//To change body of implemented methods use File | Settings | File Templates.
getDelegateForUpdate();
updated.setLdapServerConfig(ldapServerConfig);
}
@Override
public List<AuthenticationProviderModel> getAuthenticationProviders() {
return null; //To change body of implemented methods use File | Settings | File Templates.
if (updated != null) return updated.getAuthenticationProviders();
return cached.getAuthenticationProviders();
}
@Override
public void setAuthenticationProviders(List<AuthenticationProviderModel> authenticationProviders) {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public Set<RoleModel> getRealmRoleMappings(UserModel user) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public Set<RoleModel> getRealmScopeMappings(ClientModel client) {
return null; //To change body of implemented methods use File | Settings | File Templates.
getDelegateForUpdate();
updated.setAuthenticationProviders(authenticationProviders);
}
@Override
@@ -684,11 +771,6 @@ public class RealmAdapter implements RealmModel {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public boolean hasScope(ClientModel client, RoleModel role) {
return false; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public int getNotBefore() {
return 0; //To change body of implemented methods use File | Settings | File Templates.
@@ -744,6 +826,21 @@ public class RealmAdapter implements RealmModel {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public UsernameLoginFailureModel getUserLoginFailure(String username) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public UsernameLoginFailureModel addUserLoginFailure(String username) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public List<UsernameLoginFailureModel> getAllUserLoginFailures() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public UserSessionModel createUserSession(UserModel user, String ipAddress) {
return null; //To change body of implemented methods use File | Settings | File Templates.
@@ -809,38 +906,4 @@ public class RealmAdapter implements RealmModel {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public boolean hasRole(UserModel user, RoleModel role) {
return false; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void grantRole(UserModel user, RoleModel role) {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public Set<RoleModel> getRoleMappings(UserModel user) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void deleteRoleMapping(UserModel user, RoleModel role) {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public Set<RoleModel> getScopeMappings(ClientModel client) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void addScopeMapping(ClientModel client, RoleModel role) {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void deleteScopeMapping(ClientModel client, RoleModel role) {
//To change body of implemented methods use File | Settings | File Templates.
}
}
@@ -0,0 +1,121 @@
package org.keycloak.models.cache;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.cache.entities.CachedApplicationRole;
import org.keycloak.models.cache.entities.CachedRealmRole;
import org.keycloak.models.cache.entities.CachedRole;
import org.keycloak.models.utils.KeycloakModelUtils;
import java.util.HashSet;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class RoleAdapter implements RoleModel {
protected RoleModel updated;
protected CachedRole cached;
protected KeycloakCache cache;
protected CacheKeycloakSession cacheSession;
protected RealmModel realm;
public RoleAdapter(CachedRole 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) {
updated = cacheSession.getDelegate().getRoleById(getId(), realm);
if (updated == null) throw new IllegalStateException("Not found in database");
}
}
@Override
public String getName() {
if (updated != null) return updated.getName();
return cached.getName();
}
@Override
public String getDescription() {
if (updated != null) return updated.getDescription();
return cached.getDescription();
}
@Override
public void setDescription(String description) {
getDelegateForUpdate();
updated.setDescription(description);
}
@Override
public String getId() {
if (updated != null) return updated.getId();
return cached.getId();
}
@Override
public void setName(String name) {
getDelegateForUpdate();
updated.setName(name);
}
@Override
public boolean isComposite() {
if (updated != null) return updated.isComposite();
return cached.isComposite();
}
@Override
public void addCompositeRole(RoleModel role) {
getDelegateForUpdate();
updated.addCompositeRole(role);
}
@Override
public void removeCompositeRole(RoleModel role) {
getDelegateForUpdate();
updated.removeCompositeRole(role);
}
@Override
public Set<RoleModel> getComposites() {
if (updated != null) return updated.getComposites();
Set<RoleModel> set = new HashSet<RoleModel>();
for (String id : cached.getComposites()) {
RoleModel role = realm.getRoleById(id);
if (role == null) {
throw new IllegalStateException("Could not find composite: " + id);
}
set.add(role);
}
return set;
}
@Override
public RoleContainerModel getContainer() {
if (cached instanceof CachedRealmRole) {
return realm;
} else {
CachedApplicationRole appRole = (CachedApplicationRole)cached;
return realm.getApplicationById(appRole.getAppId());
}
}
@Override
public boolean hasRole(RoleModel role) {
if (this.equals(role)) return true;
if (!isComposite()) return false;
Set<RoleModel> visited = new HashSet<RoleModel>();
return KeycloakModelUtils.searchFor(role, this, visited);
}
}
@@ -5,7 +5,10 @@ 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;
@@ -56,4 +59,64 @@ public class SimpleCache implements KeycloakCache {
public CachedRealm getCachedRealmByName(String name) {
return realmCacheByName.get(name);
}
@Override
public CachedApplication getApplication(String id) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void invalidateApplication(CachedApplication app) {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void addCachedApplication(CachedApplication app) {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void invalidateCachedApplicationById(String id) {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public CachedOAuthClient getOAuthClient(String id) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void invalidateOAuthClient(CachedOAuthClient client) {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void addCachedOAuthClient(CachedOAuthClient client) {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void invalidateCachedOAuthClientById(String id) {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public CachedRole getRole(String id) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void invalidateRole(CachedRole role) {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void addCachedRole(CachedRole role) {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void invalidateCachedRoleById(String id) {
//To change body of implemented methods use File | Settings | File Templates.
}
}
@@ -0,0 +1,70 @@
package org.keycloak.models.cache.entities;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.cache.KeycloakCache;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
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 CachedApplication extends CachedClient {
private boolean surrogateAuthRequired;
private String managementUrl;
private String baseUrl;
private List<String> defaultRoles = new LinkedList<String>();
private boolean bearerOnly;
private Map<String, String> roles = new HashMap<String, String>();
public CachedApplication(KeycloakCache cache, KeycloakSession delegate, RealmModel realm, ApplicationModel model) {
super(cache, delegate, realm, model);
surrogateAuthRequired = model.isSurrogateAuthRequired();
managementUrl = model.getManagementUrl();
baseUrl = model.getBaseUrl();
defaultRoles.addAll(model.getDefaultRoles());
bearerOnly = model.isBearerOnly();
for (RoleModel role : model.getRoles()) {
roles.put(role.getName(), role.getId());
cache.addCachedRole(new CachedApplicationRole(id, role));
}
}
public boolean isSurrogateAuthRequired() {
return surrogateAuthRequired;
}
public String getManagementUrl() {
return managementUrl;
}
public String getBaseUrl() {
return baseUrl;
}
public List<String> getDefaultRoles() {
return defaultRoles;
}
public boolean isBearerOnly() {
return bearerOnly;
}
public Map<String, String> getRoles() {
return roles;
}
}
@@ -0,0 +1,21 @@
package org.keycloak.models.cache.entities;
import org.keycloak.models.RoleModel;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class CachedApplicationRole extends CachedRole {
private final String appId;
public CachedApplicationRole(String appId, RoleModel model) {
super(model);
this.appId = appId;
}
public String getAppId() {
return appId;
}
}
@@ -0,0 +1,90 @@
package org.keycloak.models.cache.entities;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.cache.KeycloakCache;
import java.util.HashSet;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class CachedClient {
protected String id;
protected String name;
protected long allowedClaimsMask;
protected Set<String> redirectUris = new HashSet<String>();
protected boolean enabled;
protected String secret;
protected boolean publicClient;
protected boolean directGrantsOnly;
protected int notBefore;
protected Set<String> scope = new HashSet<String>();
protected Set<String> webOrigins = new HashSet<String>();
public CachedClient(KeycloakCache cache, KeycloakSession delegate, RealmModel realm, ClientModel model) {
id = model.getId();
secret = model.getSecret();
name = model.getClientId();
enabled = model.isEnabled();
notBefore = model.getNotBefore();
directGrantsOnly = model.isDirectGrantsOnly();
publicClient = model.isPublicClient();
allowedClaimsMask = model.getAllowedClaimsMask();
redirectUris.addAll(model.getRedirectUris());
webOrigins.addAll(model.getWebOrigins());
for (RoleModel role : model.getScopeMappings()) {
scope.add(role.getId());
}
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public long getAllowedClaimsMask() {
return allowedClaimsMask;
}
public Set<String> getRedirectUris() {
return redirectUris;
}
public boolean isEnabled() {
return enabled;
}
public String getSecret() {
return secret;
}
public boolean isPublicClient() {
return publicClient;
}
public boolean isDirectGrantsOnly() {
return directGrantsOnly;
}
public int getNotBefore() {
return notBefore;
}
public Set<String> getScope() {
return scope;
}
public Set<String> getWebOrigins() {
return webOrigins;
}
}
@@ -0,0 +1,17 @@
package org.keycloak.models.cache.entities;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.OAuthClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.cache.KeycloakCache;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class CachedOAuthClient extends CachedClient {
public CachedOAuthClient(KeycloakCache cache, KeycloakSession delegate, RealmModel realm, OAuthClientModel model) {
super(cache, delegate, realm, model);
}
}
@@ -1,29 +1,19 @@
package org.keycloak.models.cache.entities;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.AuthenticationLinkModel;
import org.keycloak.models.AuthenticationProviderModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.OAuthClientModel;
import org.keycloak.models.PasswordPolicy;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredCredentialModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.SocialLinkModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserCredentialValueModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.UsernameLoginFailureModel;
import org.keycloak.models.entities.AuthenticationProviderEntity;
import org.keycloak.models.entities.RequiredCredentialEntity;
import org.keycloak.models.cache.KeycloakCache;
import java.io.Serializable;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -81,11 +71,16 @@ public class CachedRealm {
private boolean auditEnabled;
private long auditExpiration;
private Set<String> auditListeners = new HashSet<String>();
private List<String> defaultRoles = new LinkedList<String>();
private Map<String, String> realmRoles = new HashMap<String, String>();
private Set<String> rolesById = new HashSet<String>();
private Map<String, String> applications = new HashMap<String, String>();
private Map<String, String> clients = new HashMap<String, String>();
public CachedRealm() {
}
public CachedRealm(RealmModel model) {
public CachedRealm(KeycloakCache cache, KeycloakSession delegate, RealmModel model) {
id = model.getId();
name = model.getName();
enabled = model.isEnabled();
@@ -133,6 +128,30 @@ public class CachedRealm {
auditEnabled = model.isAuditEnabled();
auditExpiration = model.getAuditExpiration();
auditListeners.addAll(model.getAuditListeners());
defaultRoles.addAll(model.getDefaultRoles());
for (RoleModel role : model.getRoles()) {
realmRoles.put(role.getName(), role.getId());
rolesById.add(role.getId());
CachedRole cachedRole = new CachedRealmRole(role);
cache.addCachedRole(cachedRole);
}
for (ApplicationModel app : model.getApplications()) {
applications.put(app.getName(), app.getId());
CachedApplication cachedApp = new CachedApplication(cache, delegate, model, app);
cache.addCachedApplication(cachedApp);
for (String roleId : cachedApp.getRoles().values()) {
rolesById.add(roleId);
}
}
for (OAuthClientModel client : model.getOAuthClients()) {
clients.put(client.getClientId(), client.getId());
CachedOAuthClient cachedApp = new CachedOAuthClient(cache, delegate, model, client);
cache.addCachedOAuthClient(cachedApp);
}
}
@@ -144,6 +163,26 @@ public class CachedRealm {
return name;
}
public List<String> getDefaultRoles() {
return defaultRoles;
}
public Map<String, String> getRealmRoles() {
return realmRoles;
}
public Set<String> getRolesById() {
return rolesById;
}
public Map<String, String> getApplications() {
return applications;
}
public Map<String, String> getClients() {
return clients;
}
public boolean isEnabled() {
return enabled;
}
@@ -0,0 +1,20 @@
package org.keycloak.models.cache.entities;
import org.keycloak.models.RoleModel;
import java.util.HashSet;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class CachedRealmRole extends CachedRole {
public CachedRealmRole(RoleModel model) {
super(model);
}
}
@@ -0,0 +1,51 @@
package org.keycloak.models.cache.entities;
import org.keycloak.models.RoleModel;
import java.util.HashSet;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class CachedRole {
final protected String id;
final protected String name;
final protected String description;
final protected boolean composite;
final protected Set<String> composites = new HashSet<String>();
public CachedRole(RoleModel model) {
composite = model.isComposite();
description = model.getDescription();
id = model.getId();
name = model.getName();
if (composite) {
for (RoleModel child : model.getComposites()) {
composites.add(child.getId());
}
}
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public boolean isComposite() {
return composite;
}
public Set<String> getComposites() {
return composites;
}
}