@Override public UserCache create(KeycloakSession session) { lazyInit(session); return new UserCacheSession(userCache, session); }
@Override public void preRemove(RealmModel realm) { addRealmInvalidation(realm.getId()); getDelegate().preRemove(realm); }
protected UserModel getUserAdapter(RealmModel realm, String userId, Long loaded, UserModel delegate) { CachedUser cached = cache.get(userId, CachedUser.class); if (cached == null) { return cacheUser(realm, delegate, loaded); } else { return validateCache(realm, cached); } }
@Override public boolean removeUser(RealmModel realm, UserModel user) { fullyInvalidateUser(realm, user); return getDelegate().removeUser(realm, user); }
@Override public boolean revokeConsentForClient(RealmModel realm, String userId, String clientInternalId) { invalidateConsent(userId); return getDelegate().revokeConsentForClient(realm, userId, clientInternalId); }
if (realmInvalidations.contains(realm.getId())) { logger.tracev("realmInvalidations"); return getDelegate().getUserByUsername(username, realm); String cacheKey = getUserByUsernameCacheKey(realm.getId(), username); if (invalidations.contains(cacheKey)) { logger.tracev("invalidations"); return getDelegate().getUserByUsername(username, realm); logger.tracev("query null"); Long loaded = cache.getCurrentRevision(cacheKey); UserModel model = getDelegate().getUserByUsername(username, realm); if (model == null) { logger.tracev("model from delegate null"); UserModel adapter = getUserAdapter(realm, userId, loaded, model); if (adapter instanceof UserAdapter) { // this was cached, so we can cache query too query = new UserListQuery(loaded, cacheKey, realm, model.getId()); if (invalidations.contains(userId)) { logger.tracev("invalidated cache return delegate"); return getDelegate().getUserByUsername(username, realm); return getUserById(userId, realm);
@Override public UserModel getUserById(String id, RealmModel realm) { logger.tracev("getuserById {0}", id); if (isRegisteredForInvalidation(realm, id)) { logger.trace("registered for invalidation return delegate"); return getDelegate().getUserById(id, realm); } if (managedUsers.containsKey(id)) { logger.trace("return managedusers"); return managedUsers.get(id); } CachedUser cached = cache.get(id, CachedUser.class); UserModel adapter = null; if (cached == null) { logger.trace("not cached"); Long loaded = cache.getCurrentRevision(id); UserModel delegate = getDelegate().getUserById(id, realm); if (delegate == null) { logger.trace("delegate returning null"); return null; } adapter = cacheUser(realm, delegate, loaded); } else { adapter = validateCache(realm, cached); } managedUsers.put(id, adapter); return adapter; }
email = email.toLowerCase(); if (realmInvalidations.contains(realm.getId())) { return getDelegate().getUserByEmail(email, realm); String cacheKey = getUserByEmailCacheKey(realm.getId(), email); if (invalidations.contains(cacheKey)) { return getDelegate().getUserByEmail(email, realm); if (query == null) { Long loaded = cache.getCurrentRevision(cacheKey); UserModel model = getDelegate().getUserByEmail(email, realm); if (model == null) return null; userId = model.getId(); if (managedUsers.containsKey(userId)) return managedUsers.get(userId); UserModel adapter = getUserAdapter(realm, userId, loaded, model); if (adapter instanceof UserAdapter) { query = new UserListQuery(loaded, cacheKey, realm, model.getId()); userId = query.getUsers().iterator().next(); if (invalidations.contains(userId)) { return getDelegate().getUserByEmail(email, realm); return getUserById(userId, realm);
return getDelegate().getUserByFederatedIdentity(socialLink, realm); String cacheKey = getUserByFederatedIdentityCacheKey(realm.getId(), socialLink); if (invalidations.contains(cacheKey)) { return getDelegate().getUserByFederatedIdentity(socialLink, realm); if (query == null) { Long loaded = cache.getCurrentRevision(cacheKey); UserModel model = getDelegate().getUserByFederatedIdentity(socialLink, realm); if (model == null) return null; userId = model.getId(); if (managedUsers.containsKey(userId)) return managedUsers.get(userId); UserModel adapter = getUserAdapter(realm, userId, loaded, model); if (adapter instanceof UserAdapter) { query = new UserListQuery(loaded, cacheKey, realm, model.getId()); if (invalidations.contains(userId)) { invalidations.add(cacheKey); return getDelegate().getUserByFederatedIdentity(socialLink, realm); return getUserById(userId, realm);
@Override public void unlinkUsers(RealmModel realm, String storageProviderId) { getDelegate().unlinkUsers(realm, storageProviderId); clear(); addRealmInvalidation(realm.getId()); // easier to just invalidate whole realm }
@Override public int getNotBeforeOfUser(RealmModel realm, UserModel user) { if (isRegisteredForInvalidation(realm, user.getId())) { return getDelegate().getNotBeforeOfUser(realm, user); } UserModel foundUser = getUserById(user.getId(), realm); if (foundUser instanceof UserAdapter) { return ((UserAdapter) foundUser).cached.getNotBefore(); } else { return getDelegate().getNotBeforeOfUser(realm, user); } }
@Override public UserConsentModel getConsentByClient(RealmModel realm, String userId, String clientId) { logger.tracev("getConsentByClient: {0}", userId); String cacheKey = getConsentCacheKey(userId); if (realmInvalidations.contains(realm.getId()) || invalidations.contains(userId) || invalidations.contains(cacheKey)) { return getDelegate().getConsentByClient(realm, userId, clientId); } CachedUserConsents cached = cache.get(cacheKey, CachedUserConsents.class); if (cached == null) { Long loaded = cache.getCurrentRevision(cacheKey); List<UserConsentModel> consents = getDelegate().getConsents(realm, userId); cached = new CachedUserConsents(loaded, cacheKey, realm, consents); cache.addRevisioned(cached, startupRevision); } CachedUserConsent cachedConsent = cached.getConsents().get(clientId); if (cachedConsent == null) return null; return toConsentModel(realm, cachedConsent); }
@Override public List<UserModel> getRoleMembers(RealmModel realm, RoleModel role, int firstResult, int maxResults) { return getDelegate().getRoleMembers(realm, role, firstResult, maxResults); }
public void fullUserInvalidation(String userId, String username, String email, String realmId, boolean identityFederationEnabled, Map<String, String> federatedIdentities, Set<String> invalidations) { userUpdatedInvalidations(userId, username, email, realmId, invalidations); if (identityFederationEnabled) { // Invalidate all keys for lookup this user by any identityProvider link for (Map.Entry<String, String> socialLink : federatedIdentities.entrySet()) { String fedIdentityCacheKey = UserCacheSession.getUserByFederatedIdentityCacheKey(realmId, socialLink.getKey(), socialLink.getValue()); invalidations.add(fedIdentityCacheKey); } // Invalidate federationLinks of user invalidations.add(UserCacheSession.getFederatedIdentityLinksCacheKey(userId)); } // Consents invalidations.add(UserCacheSession.getConsentCacheKey(userId)); }
@Override public FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm) { logger.tracev("getFederatedIdentity: {0} {1}", user.getUsername(), socialProvider); String cacheKey = getFederatedIdentityLinksCacheKey(user.getId()); if (realmInvalidations.contains(realm.getId()) || invalidations.contains(user.getId()) || invalidations.contains(cacheKey)) { return getDelegate().getFederatedIdentity(user, socialProvider, realm); } Set<FederatedIdentityModel> federatedIdentities = getFederatedIdentities(user, realm); for (FederatedIdentityModel socialLink : federatedIdentities) { if (socialLink.getIdentityProvider().equals(socialProvider)) { return socialLink; } } return null; }
@Override public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel socialLink) { invalidateFederationLink(user.getId()); getDelegate().addFederatedIdentity(realm, user, socialLink); }
@Override public UserModel getServiceAccount(ClientModel client) { // Just an attempt to find the user from cache by default serviceAccount username UserModel user = findServiceAccount(client); if (user != null && user.getServiceAccountClientLink() != null && user.getServiceAccountClientLink().equals(client.getId())) { return user; } return getDelegate().getServiceAccount(client); }
@Override public Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm) { logger.tracev("getFederatedIdentities: {0}", user.getUsername()); String cacheKey = getFederatedIdentityLinksCacheKey(user.getId()); if (realmInvalidations.contains(realm.getId()) || invalidations.contains(user.getId()) || invalidations.contains(cacheKey)) { return getDelegate().getFederatedIdentities(user, realm); } CachedFederatedIdentityLinks cachedLinks = cache.get(cacheKey, CachedFederatedIdentityLinks.class); if (cachedLinks == null) { Long loaded = cache.getCurrentRevision(cacheKey); Set<FederatedIdentityModel> federatedIdentities = getDelegate().getFederatedIdentities(user, realm); cachedLinks = new CachedFederatedIdentityLinks(loaded, cacheKey, realm, federatedIdentities); cache.addRevisioned(cachedLinks, startupRevision); return federatedIdentities; } else { return new HashSet<>(cachedLinks.getFederatedIdentities()); } }
@Override public boolean removeFederatedIdentity(RealmModel realm, UserModel user, String socialProvider) { // Needs to invalidate both directions FederatedIdentityModel socialLink = getFederatedIdentity(user, socialProvider, realm); UserFederationLinkRemovedEvent event = UserFederationLinkRemovedEvent.create(user.getId(), realm.getId(), socialLink); cache.federatedIdentityLinkRemovedInvalidation(user.getId(), realm.getId(), event.getIdentityProviderId(), event.getSocialUserId(), invalidations); invalidationEvents.add(event); return getDelegate().removeFederatedIdentity(realm, user, socialProvider); }
protected UserModel validateCache(RealmModel realm, CachedUser cached) { if (!realm.getId().equals(cached.getRealm())) { return null; } StorageId storageId = cached.getFederationLink() != null ? new StorageId(cached.getFederationLink(), cached.getId()) : new StorageId(cached.getId()); if (!storageId.isLocal()) { ComponentModel component = realm.getComponent(storageId.getProviderId()); CacheableStorageProviderModel model = new CacheableStorageProviderModel(component); // although we do set a timeout, Infinispan has no guarantees when the user will be evicted // its also hard to test stuff if (model.shouldInvalidate(cached)) { registerUserInvalidation(realm, cached); return getDelegate().getUserById(cached.getId(), realm); } } return new UserAdapter(cached, this, session, realm); }