user fed refactor
This commit is contained in:
parent
b2d8c6bca2
commit
f51098c50b
88 changed files with 6747 additions and 479 deletions
|
@ -23,6 +23,7 @@ import org.keycloak.models.*;
|
|||
import org.keycloak.models.cache.CacheRealmProvider;
|
||||
import org.keycloak.models.cache.infinispan.entities.CachedRealm;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.storage.StorageProviderModel;
|
||||
|
||||
import java.security.Key;
|
||||
import java.security.PrivateKey;
|
||||
|
@ -739,6 +740,48 @@ public class RealmAdapter implements RealmModel {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public StorageProviderModel addStorageProvider(StorageProviderModel provider) {
|
||||
getDelegateForUpdate();
|
||||
return updated.addStorageProvider(provider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStorageProvider(StorageProviderModel provider) {
|
||||
getDelegateForUpdate();
|
||||
updated.updateStorageProvider(provider);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeStorageProvider(StorageProviderModel provider) {
|
||||
getDelegateForUpdate();
|
||||
updated.removeStorageProvider(provider);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStorageProviders(List<StorageProviderModel> providers) {
|
||||
getDelegateForUpdate();
|
||||
updated.setStorageProviders(providers);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StorageProviderModel> getStorageProviders() {
|
||||
if (isUpdated()) return updated.getStorageProviders();
|
||||
return cached.getStorageProviders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public StorageProviderModel getStorageProvider(String id) {
|
||||
if (isUpdated()) return updated.getStorageProvider(id);
|
||||
for (StorageProviderModel model : cached.getStorageProviders()) {
|
||||
if (model.getId().equals(id)) return model;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLoginTheme() {
|
||||
if (isUpdated()) return updated.getLoginTheme();
|
||||
|
|
|
@ -388,70 +388,6 @@ public class UserAdapter implements UserModel {
|
|||
return KeycloakModelUtils.isMember(roles, group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addConsent(UserConsentModel consent) {
|
||||
getDelegateForUpdate();
|
||||
updated.addConsent(consent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserConsentModel getConsentByClient(String clientId) {
|
||||
if (updated != null) return updated.getConsentByClient(clientId);
|
||||
CachedUserConsent cachedConsent = cached.getConsents().get(clientId);
|
||||
if (cachedConsent == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return toConsentModel(cachedConsent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserConsentModel> getConsents() {
|
||||
if (updated != null) return updated.getConsents();
|
||||
Collection<CachedUserConsent> cachedConsents = cached.getConsents().values();
|
||||
|
||||
List<UserConsentModel> result = new LinkedList<>();
|
||||
for (CachedUserConsent cachedConsent : cachedConsents) {
|
||||
UserConsentModel consent = toConsentModel(cachedConsent);
|
||||
if (consent != null) {
|
||||
result.add(consent);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateConsent(UserConsentModel consent) {
|
||||
getDelegateForUpdate();
|
||||
updated.updateConsent(consent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean revokeConsentForClient(String clientId) {
|
||||
getDelegateForUpdate();
|
||||
return updated.revokeConsentForClient(clientId);
|
||||
}
|
||||
|
||||
private UserConsentModel toConsentModel(CachedUserConsent cachedConsent) {
|
||||
ClientModel client = keycloakSession.realms().getClientById(cachedConsent.getClientDbId(), realm);
|
||||
if (client == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
UserConsentModel consentModel = new UserConsentModel(client);
|
||||
|
||||
for (String roleId : cachedConsent.getRoleIds()) {
|
||||
RoleModel role = keycloakSession.realms().getRoleById(roleId, realm);
|
||||
if (role != null) {
|
||||
consentModel.addGrantedRole(role);
|
||||
}
|
||||
}
|
||||
for (ProtocolMapperModel protocolMapper : cachedConsent.getProtocolMappers()) {
|
||||
consentModel.addGrantedProtocolMapper(protocolMapper);
|
||||
}
|
||||
return consentModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.keycloak.models.KeycloakTransaction;
|
|||
import org.keycloak.models.ProtocolMapperModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserConsentModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
@ -35,7 +36,10 @@ import org.keycloak.models.UserProvider;
|
|||
import org.keycloak.models.cache.CacheUserProvider;
|
||||
import org.keycloak.models.cache.infinispan.entities.CachedFederatedIdentityLinks;
|
||||
import org.keycloak.models.cache.infinispan.entities.CachedUser;
|
||||
import org.keycloak.models.cache.infinispan.entities.CachedUserConsent;
|
||||
import org.keycloak.models.cache.infinispan.entities.CachedUserConsents;
|
||||
import org.keycloak.models.cache.infinispan.entities.UserListQuery;
|
||||
import org.keycloak.storage.StorageProviderModel;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
@ -73,7 +77,7 @@ public class UserCacheSession implements CacheUserProvider {
|
|||
public UserProvider getDelegate() {
|
||||
if (!transactionActive) throw new IllegalStateException("Cannot access delegate without a transaction");
|
||||
if (delegate != null) return delegate;
|
||||
delegate = session.getProvider(UserProvider.class);
|
||||
delegate = session.userStorageManager();
|
||||
|
||||
return delegate;
|
||||
}
|
||||
|
@ -342,7 +346,7 @@ public class UserCacheSession implements CacheUserProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserByServiceAccountClient(ClientModel client) {
|
||||
public UserModel getServiceAccount(ClientModel client) {
|
||||
// Just an attempt to find the user from cache by default serviceAccount username
|
||||
String username = ServiceAccountConstants.SERVICE_ACCOUNT_USER_PREFIX + client.getClientId();
|
||||
UserModel user = getUserByUsername(username, client.getRealm());
|
||||
|
@ -350,7 +354,7 @@ public class UserCacheSession implements CacheUserProvider {
|
|||
return user;
|
||||
}
|
||||
|
||||
return getDelegate().getUserByServiceAccountClient(client);
|
||||
return getDelegate().getServiceAccount(client);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -368,6 +372,16 @@ public class UserCacheSession implements CacheUserProvider {
|
|||
return getDelegate().getUsers(realm, firstResult, maxResults, includeServiceAccounts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getUsers(RealmModel realm) {
|
||||
return getUsers(realm, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
|
||||
return getUsers(realm, firstResult, maxResults, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUser(String search, RealmModel realm) {
|
||||
return getDelegate().searchForUser(search, realm);
|
||||
|
@ -433,6 +447,101 @@ public class UserCacheSession implements CacheUserProvider {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
|
||||
invalidations.add(getConsentCacheKey(user.getId()));
|
||||
getDelegate().updateConsent(realm, user, consent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean revokeConsentForClient(RealmModel realm, UserModel user, String clientInternalId) {
|
||||
invalidations.add(getConsentCacheKey(user.getId()));
|
||||
return getDelegate().revokeConsentForClient(realm, user, clientInternalId);
|
||||
}
|
||||
|
||||
public String getConsentCacheKey(String userId) {
|
||||
return userId + ".consents";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
|
||||
invalidations.add(getConsentCacheKey(user.getId()));
|
||||
getDelegate().addConsent(realm, user, consent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserConsentModel getConsentByClient(RealmModel realm, UserModel user, String clientId) {
|
||||
logger.tracev("getConsentByClient: {0}", user.getUsername());
|
||||
|
||||
String cacheKey = getConsentCacheKey(user.getId());
|
||||
if (realmInvalidations.contains(realm.getId()) || invalidations.contains(user.getId()) || invalidations.contains(cacheKey)) {
|
||||
return getDelegate().getConsentByClient(realm, user, clientId);
|
||||
}
|
||||
|
||||
CachedUserConsents cached = cache.get(cacheKey, CachedUserConsents.class);
|
||||
|
||||
if (cached == null) {
|
||||
Long loaded = cache.getCurrentRevision(cacheKey);
|
||||
List<UserConsentModel> consents = getDelegate().getConsents(realm, user);
|
||||
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<UserConsentModel> getConsents(RealmModel realm, UserModel user) {
|
||||
logger.tracev("getConsents: {0}", user.getUsername());
|
||||
|
||||
String cacheKey = getConsentCacheKey(user.getId());
|
||||
if (realmInvalidations.contains(realm.getId()) || invalidations.contains(user.getId()) || invalidations.contains(cacheKey)) {
|
||||
return getDelegate().getConsents(realm, user);
|
||||
}
|
||||
|
||||
CachedUserConsents cached = cache.get(cacheKey, CachedUserConsents.class);
|
||||
|
||||
if (cached == null) {
|
||||
Long loaded = cache.getCurrentRevision(cacheKey);
|
||||
List<UserConsentModel> consents = getDelegate().getConsents(realm, user);
|
||||
cached = new CachedUserConsents(loaded, cacheKey, realm, consents);
|
||||
cache.addRevisioned(cached, startupRevision);
|
||||
return consents;
|
||||
} else {
|
||||
List<UserConsentModel> result = new LinkedList<>();
|
||||
for (CachedUserConsent cachedConsent : cached.getConsents().values()) {
|
||||
UserConsentModel consent = toConsentModel(realm, cachedConsent);
|
||||
if (consent != null) {
|
||||
result.add(consent);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private UserConsentModel toConsentModel(RealmModel realm, CachedUserConsent cachedConsent) {
|
||||
ClientModel client = session.realms().getClientById(cachedConsent.getClientDbId(), realm);
|
||||
if (client == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
UserConsentModel consentModel = new UserConsentModel(client);
|
||||
|
||||
for (String roleId : cachedConsent.getRoleIds()) {
|
||||
RoleModel role = session.realms().getRoleById(roleId, realm);
|
||||
if (role != null) {
|
||||
consentModel.addGrantedRole(role);
|
||||
}
|
||||
}
|
||||
for (ProtocolMapperModel protocolMapper : cachedConsent.getProtocolMappers()) {
|
||||
consentModel.addGrantedProtocolMapper(protocolMapper);
|
||||
}
|
||||
return consentModel;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions) {
|
||||
UserModel user = getDelegate().addUser(realm, id, username, addDefaultRoles, addDefaultRoles);
|
||||
|
@ -554,4 +663,9 @@ public class UserCacheSession implements CacheUserProvider {
|
|||
public void preRemove(ProtocolMapperModel protocolMapper) {
|
||||
getDelegate().preRemove(protocolMapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, StorageProviderModel provider) {
|
||||
getDelegate().preRemove(realm, provider);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.keycloak.models.UserFederationMapperModel;
|
|||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.cache.infinispan.RealmCache;
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
import org.keycloak.storage.StorageProviderModel;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.security.PrivateKey;
|
||||
|
@ -109,6 +110,7 @@ public class CachedRealm extends AbstractRevisioned {
|
|||
|
||||
protected List<RequiredCredentialModel> requiredCredentials;
|
||||
protected List<UserFederationProviderModel> userFederationProviders;
|
||||
protected List<StorageProviderModel> storageProviders;
|
||||
protected MultivaluedHashMap<String, UserFederationMapperModel> userFederationMappers = new MultivaluedHashMap<String, UserFederationMapperModel>();
|
||||
protected Set<UserFederationMapperModel> userFederationMapperSet;
|
||||
protected List<IdentityProviderModel> identityProviders;
|
||||
|
@ -204,6 +206,7 @@ public class CachedRealm extends AbstractRevisioned {
|
|||
|
||||
requiredCredentials = model.getRequiredCredentials();
|
||||
userFederationProviders = model.getUserFederationProviders();
|
||||
storageProviders = model.getStorageProviders();
|
||||
userFederationMapperSet = model.getUserFederationMappers();
|
||||
for (UserFederationMapperModel mapper : userFederationMapperSet) {
|
||||
this.userFederationMappers.add(mapper.getFederationProviderId(), mapper);
|
||||
|
@ -592,4 +595,8 @@ public class CachedRealm extends AbstractRevisioned {
|
|||
public List<RequiredActionProviderModel> getRequiredActionProviderList() {
|
||||
return requiredActionProviderList;
|
||||
}
|
||||
|
||||
public List<StorageProviderModel> getStorageProviders() {
|
||||
return storageProviders;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,6 @@ public class CachedUser extends AbstractRevisioned implements InRealm {
|
|||
private Set<String> requiredActions = new HashSet<>();
|
||||
private Set<String> roleMappings = new HashSet<>();
|
||||
private Set<String> groups = new HashSet<>();
|
||||
private Map<String, CachedUserConsent> consents = new HashMap<>(); // Key is client DB Id
|
||||
|
||||
|
||||
|
||||
|
@ -82,13 +81,6 @@ public class CachedUser extends AbstractRevisioned implements InRealm {
|
|||
groups.add(group.getId());
|
||||
}
|
||||
}
|
||||
|
||||
List<UserConsentModel> consents = user.getConsents();
|
||||
if (consents != null) {
|
||||
for (UserConsentModel consent : consents) {
|
||||
this.consents.put(consent.getClient().getId(), new CachedUserConsent(consent));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getRealm() {
|
||||
|
@ -155,7 +147,4 @@ public class CachedUser extends AbstractRevisioned implements InRealm {
|
|||
return groups;
|
||||
}
|
||||
|
||||
public Map<String, CachedUserConsent> getConsents() {
|
||||
return consents;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.models.cache.infinispan.entities;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserConsentModel;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class CachedUserConsents extends AbstractRevisioned implements InRealm {
|
||||
private HashMap<String, CachedUserConsent> consents = new HashMap<>();
|
||||
private final String realmId;
|
||||
|
||||
public CachedUserConsents(Long revision, String id, RealmModel realm,
|
||||
List<UserConsentModel> consents) {
|
||||
super(revision, id);
|
||||
this.realmId = realm.getId();
|
||||
if (consents != null) {
|
||||
for (UserConsentModel consent : consents) {
|
||||
this.consents.put(consent.getClient().getId(), new CachedUserConsent(consent));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRealm() {
|
||||
return realmId;
|
||||
}
|
||||
|
||||
|
||||
public HashMap<String, CachedUserConsent> getConsents() {
|
||||
return consents;
|
||||
}
|
||||
}
|
|
@ -22,23 +22,31 @@ import org.keycloak.models.CredentialValidationOutput;
|
|||
import org.keycloak.models.FederatedIdentityModel;
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ModelDuplicateException;
|
||||
import org.keycloak.models.ModelException;
|
||||
import org.keycloak.models.ProtocolMapperModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RequiredActionProviderModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserConsentModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserProvider;
|
||||
import org.keycloak.models.jpa.entities.FederatedIdentityEntity;
|
||||
import org.keycloak.models.jpa.entities.UserAttributeEntity;
|
||||
import org.keycloak.models.jpa.entities.UserConsentEntity;
|
||||
import org.keycloak.models.jpa.entities.UserConsentProtocolMapperEntity;
|
||||
import org.keycloak.models.jpa.entities.UserConsentRoleEntity;
|
||||
import org.keycloak.models.jpa.entities.UserEntity;
|
||||
import org.keycloak.models.utils.CredentialValidation;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.storage.StorageProviderModel;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.TypedQuery;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -173,6 +181,164 @@ public class JpaUserProvider implements UserProvider {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
|
||||
String clientId = consent.getClient().getId();
|
||||
|
||||
UserConsentEntity consentEntity = getGrantedConsentEntity(user, clientId);
|
||||
if (consentEntity != null) {
|
||||
throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + user.getId() + "]");
|
||||
}
|
||||
|
||||
consentEntity = new UserConsentEntity();
|
||||
consentEntity.setId(KeycloakModelUtils.generateId());
|
||||
consentEntity.setUser(em.getReference(UserEntity.class, user.getId()));
|
||||
consentEntity.setClientId(clientId);
|
||||
em.persist(consentEntity);
|
||||
em.flush();
|
||||
|
||||
updateGrantedConsentEntity(consentEntity, consent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserConsentModel getConsentByClient(RealmModel realm, UserModel user, String clientId) {
|
||||
UserConsentEntity entity = getGrantedConsentEntity(user, clientId);
|
||||
return toConsentModel(realm, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserConsentModel> getConsents(RealmModel realm, UserModel user) {
|
||||
TypedQuery<UserConsentEntity> query = em.createNamedQuery("userConsentsByUser", UserConsentEntity.class);
|
||||
query.setParameter("userId", user.getId());
|
||||
List<UserConsentEntity> results = query.getResultList();
|
||||
|
||||
List<UserConsentModel> consents = new ArrayList<UserConsentModel>();
|
||||
for (UserConsentEntity entity : results) {
|
||||
UserConsentModel model = toConsentModel(realm, entity);
|
||||
consents.add(model);
|
||||
}
|
||||
return consents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
|
||||
String clientId = consent.getClient().getId();
|
||||
|
||||
UserConsentEntity consentEntity = getGrantedConsentEntity(user, clientId);
|
||||
if (consentEntity == null) {
|
||||
throw new ModelException("Consent not found for client [" + clientId + "] and user [" + user.getId() + "]");
|
||||
}
|
||||
|
||||
updateGrantedConsentEntity(consentEntity, consent);
|
||||
}
|
||||
|
||||
public boolean revokeConsentForClient(RealmModel realm, UserModel user, String clientId) {
|
||||
UserConsentEntity consentEntity = getGrantedConsentEntity(user, clientId);
|
||||
if (consentEntity == null) return false;
|
||||
|
||||
em.remove(consentEntity);
|
||||
em.flush();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private UserConsentEntity getGrantedConsentEntity(UserModel user, String clientId) {
|
||||
TypedQuery<UserConsentEntity> query = em.createNamedQuery("userConsentByUserAndClient", UserConsentEntity.class);
|
||||
query.setParameter("userId", user.getId());
|
||||
query.setParameter("clientId", clientId);
|
||||
List<UserConsentEntity> results = query.getResultList();
|
||||
if (results.size() > 1) {
|
||||
throw new ModelException("More results found for user [" + user.getUsername() + "] and client [" + clientId + "]");
|
||||
} else if (results.size() == 1) {
|
||||
return results.get(0);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private UserConsentModel toConsentModel(RealmModel realm, UserConsentEntity entity) {
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ClientModel client = realm.getClientById(entity.getClientId());
|
||||
if (client == null) {
|
||||
throw new ModelException("Client with id " + entity.getClientId() + " is not available");
|
||||
}
|
||||
UserConsentModel model = new UserConsentModel(client);
|
||||
|
||||
Collection<UserConsentRoleEntity> grantedRoleEntities = entity.getGrantedRoles();
|
||||
if (grantedRoleEntities != null) {
|
||||
for (UserConsentRoleEntity grantedRole : grantedRoleEntities) {
|
||||
RoleModel grantedRoleModel = realm.getRoleById(grantedRole.getRoleId());
|
||||
if (grantedRoleModel != null) {
|
||||
model.addGrantedRole(grantedRoleModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Collection<UserConsentProtocolMapperEntity> grantedProtocolMapperEntities = entity.getGrantedProtocolMappers();
|
||||
if (grantedProtocolMapperEntities != null) {
|
||||
for (UserConsentProtocolMapperEntity grantedProtMapper : grantedProtocolMapperEntities) {
|
||||
ProtocolMapperModel protocolMapper = client.getProtocolMapperById(grantedProtMapper.getProtocolMapperId());
|
||||
model.addGrantedProtocolMapper(protocolMapper );
|
||||
}
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
// Update roles and protocolMappers to given consentEntity from the consentModel
|
||||
private void updateGrantedConsentEntity(UserConsentEntity consentEntity, UserConsentModel consentModel) {
|
||||
Collection<UserConsentProtocolMapperEntity> grantedProtocolMapperEntities = consentEntity.getGrantedProtocolMappers();
|
||||
Collection<UserConsentProtocolMapperEntity> mappersToRemove = new HashSet<UserConsentProtocolMapperEntity>(grantedProtocolMapperEntities);
|
||||
|
||||
for (ProtocolMapperModel protocolMapper : consentModel.getGrantedProtocolMappers()) {
|
||||
UserConsentProtocolMapperEntity grantedProtocolMapperEntity = new UserConsentProtocolMapperEntity();
|
||||
grantedProtocolMapperEntity.setUserConsent(consentEntity);
|
||||
grantedProtocolMapperEntity.setProtocolMapperId(protocolMapper.getId());
|
||||
|
||||
// Check if it's already there
|
||||
if (!grantedProtocolMapperEntities.contains(grantedProtocolMapperEntity)) {
|
||||
em.persist(grantedProtocolMapperEntity);
|
||||
em.flush();
|
||||
grantedProtocolMapperEntities.add(grantedProtocolMapperEntity);
|
||||
} else {
|
||||
mappersToRemove.remove(grantedProtocolMapperEntity);
|
||||
}
|
||||
}
|
||||
// Those mappers were no longer on consentModel and will be removed
|
||||
for (UserConsentProtocolMapperEntity toRemove : mappersToRemove) {
|
||||
grantedProtocolMapperEntities.remove(toRemove);
|
||||
em.remove(toRemove);
|
||||
}
|
||||
|
||||
Collection<UserConsentRoleEntity> grantedRoleEntities = consentEntity.getGrantedRoles();
|
||||
Set<UserConsentRoleEntity> rolesToRemove = new HashSet<UserConsentRoleEntity>(grantedRoleEntities);
|
||||
for (RoleModel role : consentModel.getGrantedRoles()) {
|
||||
UserConsentRoleEntity consentRoleEntity = new UserConsentRoleEntity();
|
||||
consentRoleEntity.setUserConsent(consentEntity);
|
||||
consentRoleEntity.setRoleId(role.getId());
|
||||
|
||||
// Check if it's already there
|
||||
if (!grantedRoleEntities.contains(consentRoleEntity)) {
|
||||
em.persist(consentRoleEntity);
|
||||
em.flush();
|
||||
grantedRoleEntities.add(consentRoleEntity);
|
||||
} else {
|
||||
rolesToRemove.remove(consentRoleEntity);
|
||||
}
|
||||
}
|
||||
// Those roles were no longer on consentModel and will be removed
|
||||
for (UserConsentRoleEntity toRemove : rolesToRemove) {
|
||||
grantedRoleEntities.remove(toRemove);
|
||||
em.remove(toRemove);
|
||||
}
|
||||
|
||||
em.flush();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void grantToAllUsers(RealmModel realm, RoleModel role) {
|
||||
int num = em.createNamedQuery("grantRoleToAllUsers")
|
||||
|
@ -324,7 +490,7 @@ public class JpaUserProvider implements UserProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserByServiceAccountClient(ClientModel client) {
|
||||
public UserModel getServiceAccount(ClientModel client) {
|
||||
TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserByServiceAccount", UserEntity.class);
|
||||
query.setParameter("realmId", client.getRealm().getId());
|
||||
query.setParameter("clientInternalId", client.getId());
|
||||
|
@ -353,6 +519,16 @@ public class JpaUserProvider implements UserProvider {
|
|||
return ((Number)count).intValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getUsers(RealmModel realm) {
|
||||
return getUsers(realm, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
|
||||
return getUsers(realm, firstResult, maxResults, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults, boolean includeServiceAccounts) {
|
||||
String queryName = includeServiceAccounts ? "getAllUsersByRealm" : "getAllUsersByRealmExcludeServiceAccount" ;
|
||||
|
@ -529,4 +705,9 @@ public class JpaUserProvider implements UserProvider {
|
|||
// Not supported yet
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, StorageProviderModel link) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ import org.keycloak.models.UserFederationProviderCreationEventImpl;
|
|||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.jpa.entities.*;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.storage.StorageProvider;
|
||||
import org.keycloak.storage.StorageProviderModel;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.TypedQuery;
|
||||
|
@ -805,6 +807,15 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
em.flush();
|
||||
}
|
||||
|
||||
|
||||
private void removeFederationMappersForProvider(String federationProviderId) {
|
||||
Set<UserFederationMapperEntity> mappers = getUserFederationMapperEntitiesByFederationProvider(federationProviderId);
|
||||
for (UserFederationMapperEntity mapper : mappers) {
|
||||
realm.getUserFederationMappers().remove(mapper);
|
||||
em.remove(mapper);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserFederationProviderModel> getUserFederationProviders() {
|
||||
List<UserFederationProviderEntity> entities = realm.getUserFederationProviders();
|
||||
|
@ -875,15 +886,6 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void removeFederationMappersForProvider(String federationProviderId) {
|
||||
Set<UserFederationMapperEntity> mappers = getUserFederationMapperEntitiesByFederationProvider(federationProviderId);
|
||||
for (UserFederationMapperEntity mapper : mappers) {
|
||||
realm.getUserFederationMappers().remove(mapper);
|
||||
em.remove(mapper);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateUserFederationProvider(UserFederationProviderModel model) {
|
||||
KeycloakModelUtils.ensureUniqueDisplayName(model.getDisplayName(), model, getUserFederationProviders());
|
||||
|
@ -994,6 +996,186 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StorageProviderModel getStorageProvider(String id) {
|
||||
StorageProviderEntity entity = em.find(StorageProviderEntity.class, id);
|
||||
if (entity == null) return null;
|
||||
return toModel(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StorageProviderModel> getStorageProviders() {
|
||||
List<StorageProviderEntity> entities = realm.getStorageProviders();
|
||||
if (entities.isEmpty()) return Collections.EMPTY_LIST;
|
||||
List<StorageProviderEntity> copy = new LinkedList<>();
|
||||
for (StorageProviderEntity entity : entities) {
|
||||
copy.add(entity);
|
||||
|
||||
}
|
||||
Collections.sort(copy, new Comparator<StorageProviderEntity>() {
|
||||
|
||||
@Override
|
||||
public int compare(StorageProviderEntity o1, StorageProviderEntity o2) {
|
||||
return o1.getPriority() - o2.getPriority();
|
||||
}
|
||||
|
||||
});
|
||||
List<StorageProviderModel> result = new LinkedList<>();
|
||||
for (StorageProviderEntity entity : copy) {
|
||||
result.add(toModel(entity));
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(result);
|
||||
}
|
||||
|
||||
protected StorageProviderModel toModel(StorageProviderEntity entity) {
|
||||
StorageProviderModel model = new StorageProviderModel();
|
||||
model.setId(entity.getId());
|
||||
model.setProviderName(entity.getProviderName());
|
||||
model.getConfig().putAll(entity.getConfig());
|
||||
model.setPriority(entity.getPriority());
|
||||
model.setDisplayName(entity.getDisplayName());
|
||||
return model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StorageProviderModel addStorageProvider(StorageProviderModel model) {
|
||||
KeycloakModelUtils.ensureUniqueDisplayName(model.getDisplayName(), null, getStorageProviders());
|
||||
|
||||
String id = KeycloakModelUtils.generateId();
|
||||
StorageProviderEntity entity = new StorageProviderEntity();
|
||||
entity.setId(id);
|
||||
entity.setRealm(realm);
|
||||
entity.setProviderName(model.getProviderName());
|
||||
entity.setConfig(model.getConfig());
|
||||
entity.setPriority(model.getPriority());
|
||||
String displayName = model.getDisplayName();
|
||||
if (model.getDisplayName() == null) {
|
||||
displayName = id;
|
||||
}
|
||||
entity.setDisplayName(displayName);
|
||||
em.persist(entity);
|
||||
realm.getStorageProviders().add(entity);
|
||||
em.flush();
|
||||
StorageProviderModel providerModel = toModel(entity);
|
||||
|
||||
return providerModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeStorageProvider(StorageProviderModel provider) {
|
||||
Iterator<StorageProviderEntity> it = realm.getStorageProviders().iterator();
|
||||
while (it.hasNext()) {
|
||||
StorageProviderEntity entity = it.next();
|
||||
if (entity.getId().equals(provider.getId())) {
|
||||
|
||||
session.users().preRemove(this, provider);
|
||||
|
||||
it.remove();
|
||||
em.remove(entity);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void updateStorageProvider(StorageProviderModel model) {
|
||||
KeycloakModelUtils.ensureUniqueDisplayName(model.getDisplayName(), model, getStorageProviders());
|
||||
|
||||
Iterator<StorageProviderEntity> it = realm.getStorageProviders().iterator();
|
||||
while (it.hasNext()) {
|
||||
StorageProviderEntity entity = it.next();
|
||||
if (entity.getId().equals(model.getId())) {
|
||||
String displayName = model.getDisplayName();
|
||||
if (displayName != null) {
|
||||
entity.setDisplayName(model.getDisplayName());
|
||||
}
|
||||
entity.setConfig(model.getConfig());
|
||||
entity.setPriority(model.getPriority());
|
||||
entity.setProviderName(model.getProviderName());
|
||||
entity.setPriority(model.getPriority());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStorageProviders(List<StorageProviderModel> providers) {
|
||||
for (StorageProviderModel currentProvider : providers) {
|
||||
KeycloakModelUtils.ensureUniqueDisplayName(currentProvider.getDisplayName(), currentProvider, providers);
|
||||
}
|
||||
|
||||
Iterator<StorageProviderEntity> it = realm.getStorageProviders().iterator();
|
||||
while (it.hasNext()) {
|
||||
StorageProviderEntity entity = it.next();
|
||||
boolean found = false;
|
||||
for (StorageProviderModel model : providers) {
|
||||
if (entity.getId().equals(model.getId())) {
|
||||
entity.setConfig(model.getConfig());
|
||||
entity.setPriority(model.getPriority());
|
||||
entity.setProviderName(model.getProviderName());
|
||||
String displayName = model.getDisplayName();
|
||||
if (displayName != null) {
|
||||
entity.setDisplayName(displayName);
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
if (found) continue;
|
||||
session.users().preRemove(this, toModel(entity));
|
||||
removeFederationMappersForProvider(entity.getId());
|
||||
|
||||
it.remove();
|
||||
em.remove(entity);
|
||||
}
|
||||
|
||||
List<StorageProviderModel> add = new LinkedList<>();
|
||||
for (StorageProviderModel model : providers) {
|
||||
boolean found = false;
|
||||
for (StorageProviderEntity entity : realm.getStorageProviders()) {
|
||||
if (entity.getId().equals(model.getId())) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) add.add(model);
|
||||
}
|
||||
|
||||
for (StorageProviderModel model : add) {
|
||||
StorageProviderEntity entity = new StorageProviderEntity();
|
||||
if (model.getId() != null) {
|
||||
entity.setId(model.getId());
|
||||
} else {
|
||||
String id = KeycloakModelUtils.generateId();
|
||||
entity.setId(id);
|
||||
model.setId(id);
|
||||
}
|
||||
entity.setConfig(model.getConfig());
|
||||
entity.setPriority(model.getPriority());
|
||||
entity.setProviderName(model.getProviderName());
|
||||
entity.setPriority(model.getPriority());
|
||||
String displayName = model.getDisplayName();
|
||||
if (displayName == null) {
|
||||
displayName = entity.getId();
|
||||
}
|
||||
entity.setDisplayName(displayName);
|
||||
entity.setRealm(realm);
|
||||
em.persist(entity);
|
||||
realm.getStorageProviders().add(entity);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected StorageProviderEntity getStorageProviderEntityById(String id) {
|
||||
for (StorageProviderEntity entity : realm.getStorageProviders()) {
|
||||
if (entity.getId().equals(id)) {
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoleModel getRole(String name) {
|
||||
return session.realms().getRealmRole(this, name);
|
||||
|
|
|
@ -668,163 +668,6 @@ public class UserAdapter implements UserModel, JpaModel<UserEntity> {
|
|||
user.setServiceAccountClientLink(clientInternalId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addConsent(UserConsentModel consent) {
|
||||
String clientId = consent.getClient().getId();
|
||||
|
||||
UserConsentEntity consentEntity = getGrantedConsentEntity(clientId);
|
||||
if (consentEntity != null) {
|
||||
throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + user.getId() + "]");
|
||||
}
|
||||
|
||||
consentEntity = new UserConsentEntity();
|
||||
consentEntity.setId(KeycloakModelUtils.generateId());
|
||||
consentEntity.setUser(user);
|
||||
consentEntity.setClientId(clientId);
|
||||
em.persist(consentEntity);
|
||||
em.flush();
|
||||
|
||||
updateGrantedConsentEntity(consentEntity, consent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserConsentModel getConsentByClient(String clientId) {
|
||||
UserConsentEntity entity = getGrantedConsentEntity(clientId);
|
||||
return toConsentModel(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserConsentModel> getConsents() {
|
||||
TypedQuery<UserConsentEntity> query = em.createNamedQuery("userConsentsByUser", UserConsentEntity.class);
|
||||
query.setParameter("userId", getId());
|
||||
List<UserConsentEntity> results = query.getResultList();
|
||||
|
||||
List<UserConsentModel> consents = new ArrayList<UserConsentModel>();
|
||||
for (UserConsentEntity entity : results) {
|
||||
UserConsentModel model = toConsentModel(entity);
|
||||
consents.add(model);
|
||||
}
|
||||
return consents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateConsent(UserConsentModel consent) {
|
||||
String clientId = consent.getClient().getId();
|
||||
|
||||
UserConsentEntity consentEntity = getGrantedConsentEntity(clientId);
|
||||
if (consentEntity == null) {
|
||||
throw new ModelException("Consent not found for client [" + clientId + "] and user [" + user.getId() + "]");
|
||||
}
|
||||
|
||||
updateGrantedConsentEntity(consentEntity, consent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean revokeConsentForClient(String clientId) {
|
||||
UserConsentEntity consentEntity = getGrantedConsentEntity(clientId);
|
||||
if (consentEntity == null) return false;
|
||||
|
||||
em.remove(consentEntity);
|
||||
em.flush();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private UserConsentEntity getGrantedConsentEntity(String clientId) {
|
||||
TypedQuery<UserConsentEntity> query = em.createNamedQuery("userConsentByUserAndClient", UserConsentEntity.class);
|
||||
query.setParameter("userId", getId());
|
||||
query.setParameter("clientId", clientId);
|
||||
List<UserConsentEntity> results = query.getResultList();
|
||||
if (results.size() > 1) {
|
||||
throw new ModelException("More results found for user [" + getUsername() + "] and client [" + clientId + "]");
|
||||
} else if (results.size() == 1) {
|
||||
return results.get(0);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private UserConsentModel toConsentModel(UserConsentEntity entity) {
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ClientModel client = realm.getClientById(entity.getClientId());
|
||||
if (client == null) {
|
||||
throw new ModelException("Client with id " + entity.getClientId() + " is not available");
|
||||
}
|
||||
UserConsentModel model = new UserConsentModel(client);
|
||||
|
||||
Collection<UserConsentRoleEntity> grantedRoleEntities = entity.getGrantedRoles();
|
||||
if (grantedRoleEntities != null) {
|
||||
for (UserConsentRoleEntity grantedRole : grantedRoleEntities) {
|
||||
RoleModel grantedRoleModel = realm.getRoleById(grantedRole.getRoleId());
|
||||
if (grantedRoleModel != null) {
|
||||
model.addGrantedRole(grantedRoleModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Collection<UserConsentProtocolMapperEntity> grantedProtocolMapperEntities = entity.getGrantedProtocolMappers();
|
||||
if (grantedProtocolMapperEntities != null) {
|
||||
for (UserConsentProtocolMapperEntity grantedProtMapper : grantedProtocolMapperEntities) {
|
||||
ProtocolMapperModel protocolMapper = client.getProtocolMapperById(grantedProtMapper.getProtocolMapperId());
|
||||
model.addGrantedProtocolMapper(protocolMapper );
|
||||
}
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
// Update roles and protocolMappers to given consentEntity from the consentModel
|
||||
private void updateGrantedConsentEntity(UserConsentEntity consentEntity, UserConsentModel consentModel) {
|
||||
Collection<UserConsentProtocolMapperEntity> grantedProtocolMapperEntities = consentEntity.getGrantedProtocolMappers();
|
||||
Collection<UserConsentProtocolMapperEntity> mappersToRemove = new HashSet<UserConsentProtocolMapperEntity>(grantedProtocolMapperEntities);
|
||||
|
||||
for (ProtocolMapperModel protocolMapper : consentModel.getGrantedProtocolMappers()) {
|
||||
UserConsentProtocolMapperEntity grantedProtocolMapperEntity = new UserConsentProtocolMapperEntity();
|
||||
grantedProtocolMapperEntity.setUserConsent(consentEntity);
|
||||
grantedProtocolMapperEntity.setProtocolMapperId(protocolMapper.getId());
|
||||
|
||||
// Check if it's already there
|
||||
if (!grantedProtocolMapperEntities.contains(grantedProtocolMapperEntity)) {
|
||||
em.persist(grantedProtocolMapperEntity);
|
||||
em.flush();
|
||||
grantedProtocolMapperEntities.add(grantedProtocolMapperEntity);
|
||||
} else {
|
||||
mappersToRemove.remove(grantedProtocolMapperEntity);
|
||||
}
|
||||
}
|
||||
// Those mappers were no longer on consentModel and will be removed
|
||||
for (UserConsentProtocolMapperEntity toRemove : mappersToRemove) {
|
||||
grantedProtocolMapperEntities.remove(toRemove);
|
||||
em.remove(toRemove);
|
||||
}
|
||||
|
||||
Collection<UserConsentRoleEntity> grantedRoleEntities = consentEntity.getGrantedRoles();
|
||||
Set<UserConsentRoleEntity> rolesToRemove = new HashSet<UserConsentRoleEntity>(grantedRoleEntities);
|
||||
for (RoleModel role : consentModel.getGrantedRoles()) {
|
||||
UserConsentRoleEntity consentRoleEntity = new UserConsentRoleEntity();
|
||||
consentRoleEntity.setUserConsent(consentEntity);
|
||||
consentRoleEntity.setRoleId(role.getId());
|
||||
|
||||
// Check if it's already there
|
||||
if (!grantedRoleEntities.contains(consentRoleEntity)) {
|
||||
em.persist(consentRoleEntity);
|
||||
em.flush();
|
||||
grantedRoleEntities.add(consentRoleEntity);
|
||||
} else {
|
||||
rolesToRemove.remove(consentRoleEntity);
|
||||
}
|
||||
}
|
||||
// Those roles were no longer on consentModel and will be removed
|
||||
for (UserConsentRoleEntity toRemove : rolesToRemove) {
|
||||
grantedRoleEntities.remove(toRemove);
|
||||
em.remove(toRemove);
|
||||
}
|
||||
|
||||
em.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
|
|
|
@ -136,13 +136,16 @@ public class RealmEntity {
|
|||
protected String emailTheme;
|
||||
|
||||
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
|
||||
Collection<RealmAttributeEntity> attributes = new ArrayList<RealmAttributeEntity>();
|
||||
Collection<RealmAttributeEntity> attributes = new ArrayList<>();
|
||||
|
||||
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
|
||||
Collection<RequiredCredentialEntity> requiredCredentials = new ArrayList<RequiredCredentialEntity>();
|
||||
Collection<RequiredCredentialEntity> requiredCredentials = new ArrayList<>();
|
||||
|
||||
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
|
||||
List<UserFederationProviderEntity> userFederationProviders = new ArrayList<UserFederationProviderEntity>();
|
||||
List<UserFederationProviderEntity> userFederationProviders = new ArrayList<>();
|
||||
|
||||
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
|
||||
List<StorageProviderEntity> storageProviders = new ArrayList<>();
|
||||
|
||||
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
|
||||
Collection<UserFederationMapperEntity> userFederationMappers = new ArrayList<UserFederationMapperEntity>();
|
||||
|
@ -551,6 +554,14 @@ public class RealmEntity {
|
|||
this.userFederationProviders = userFederationProviders;
|
||||
}
|
||||
|
||||
public List<StorageProviderEntity> getStorageProviders() {
|
||||
return storageProviders;
|
||||
}
|
||||
|
||||
public void setStorageProviders(List<StorageProviderEntity> storageProviders) {
|
||||
this.storageProviders = storageProviders;
|
||||
}
|
||||
|
||||
public Collection<UserFederationMapperEntity> getUserFederationMappers() {
|
||||
return userFederationMappers;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.models.jpa.entities;
|
||||
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.MapKeyColumn;
|
||||
import javax.persistence.Table;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
* @author <a href="mailto:bburke@redhat.com">Bill Burke</a>
|
||||
*/
|
||||
@Entity
|
||||
@Table(name="STORAGE_PROVIDER")
|
||||
public class StorageProviderEntity {
|
||||
|
||||
@Id
|
||||
@Column(name="ID", length = 36)
|
||||
@Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity. This avoids an extra SQL
|
||||
protected String id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "REALM_ID")
|
||||
protected RealmEntity realm;
|
||||
|
||||
@Column(name="PROVIDER_NAME")
|
||||
private String providerName;
|
||||
@Column(name="PRIORITY")
|
||||
private int priority;
|
||||
|
||||
@ElementCollection
|
||||
@MapKeyColumn(name="name")
|
||||
@Column(name="VALUE")
|
||||
@CollectionTable(name="STORAGE_PROVIDER_CONFIG", joinColumns={ @JoinColumn(name="STORAGE_PROVIDER_ID") })
|
||||
private Map<String, String> config;
|
||||
|
||||
@Column(name="DISPLAY_NAME")
|
||||
private String displayName;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public RealmEntity getRealm() {
|
||||
return realm;
|
||||
}
|
||||
|
||||
public void setRealm(RealmEntity realm) {
|
||||
this.realm = realm;
|
||||
}
|
||||
|
||||
public String getProviderName() {
|
||||
return providerName;
|
||||
}
|
||||
|
||||
public void setProviderName(String providerName) {
|
||||
this.providerName = providerName;
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
public void setPriority(int priority) {
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
public Map<String, String> getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public void setConfig(Map<String, String> config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public void setDisplayName(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null) return false;
|
||||
if (!(o instanceof StorageProviderEntity)) return false;
|
||||
|
||||
StorageProviderEntity that = (StorageProviderEntity) o;
|
||||
|
||||
if (!id.equals(that.getId())) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id.hashCode();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,732 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage.jpa;
|
||||
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.FederatedIdentityModel;
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ModelDuplicateException;
|
||||
import org.keycloak.models.ModelException;
|
||||
import org.keycloak.models.ProtocolMapperModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserConsentModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserCredentialValueModel;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.jpa.entities.CredentialEntity;
|
||||
import org.keycloak.models.utils.FederatedCredentials;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.storage.StorageId;
|
||||
import org.keycloak.storage.StorageProviderModel;
|
||||
import org.keycloak.storage.federated.UserAttributeFederatedStorage;
|
||||
import org.keycloak.storage.federated.UserBrokerLinkFederatedStorage;
|
||||
import org.keycloak.storage.federated.UserConsentFederatedStorage;
|
||||
import org.keycloak.storage.federated.UserCredentialsFederatedStorage;
|
||||
import org.keycloak.storage.federated.UserFederatedStorageProvider;
|
||||
import org.keycloak.storage.federated.UserGroupMembershipFederatedStorage;
|
||||
import org.keycloak.storage.federated.UserRequiredActionsFederatedStorage;
|
||||
import org.keycloak.storage.federated.UserRoleMappingsFederatedStorage;
|
||||
import org.keycloak.storage.jpa.entity.BrokerLinkEntity;
|
||||
import org.keycloak.storage.jpa.entity.FederatedUserAttributeEntity;
|
||||
import org.keycloak.storage.jpa.entity.FederatedUserConsentEntity;
|
||||
import org.keycloak.storage.jpa.entity.FederatedUserConsentProtocolMapperEntity;
|
||||
import org.keycloak.storage.jpa.entity.FederatedUserConsentRoleEntity;
|
||||
import org.keycloak.storage.jpa.entity.FederatedUserCredentialEntity;
|
||||
import org.keycloak.storage.jpa.entity.FederatedUserGroupMembershipEntity;
|
||||
import org.keycloak.storage.jpa.entity.FederatedUserRequiredActionEntity;
|
||||
import org.keycloak.storage.jpa.entity.FederatedUserRoleMappingEntity;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.TypedQuery;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class JpaUserFederatedStorageProvider implements
|
||||
UserFederatedStorageProvider,
|
||||
UserAttributeFederatedStorage,
|
||||
UserBrokerLinkFederatedStorage,
|
||||
UserConsentFederatedStorage,
|
||||
UserCredentialsFederatedStorage,
|
||||
UserGroupMembershipFederatedStorage,
|
||||
UserRequiredActionsFederatedStorage,
|
||||
UserRoleMappingsFederatedStorage {
|
||||
|
||||
private final KeycloakSession session;
|
||||
protected EntityManager em;
|
||||
|
||||
public JpaUserFederatedStorageProvider(KeycloakSession session, EntityManager em) {
|
||||
this.session = session;
|
||||
this.em = em;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setAttribute(RealmModel realm, UserModel user, String name, List<String> values) {
|
||||
deleteAttribute(realm, user, name);
|
||||
em.flush();
|
||||
for (String value : values) {
|
||||
persistAttributeValue(realm, user, name, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteAttribute(RealmModel realm, UserModel user, String name) {
|
||||
em.createNamedQuery("deleteUserFederatedAttributesByUserAndName")
|
||||
.setParameter("userId", user.getId())
|
||||
.setParameter("realmId", realm.getId())
|
||||
.setParameter("name", name)
|
||||
.executeUpdate();
|
||||
}
|
||||
|
||||
private void persistAttributeValue(RealmModel realm, UserModel user, String name, String value) {
|
||||
FederatedUserAttributeEntity attr = new FederatedUserAttributeEntity();
|
||||
attr.setId(KeycloakModelUtils.generateId());
|
||||
attr.setName(name);
|
||||
attr.setValue(value);
|
||||
attr.setUserId(user.getId());
|
||||
attr.setRealmId(realm.getId());
|
||||
attr.setStorageProviderId(StorageId.resolveProviderId(user));
|
||||
em.persist(attr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSingleAttribute(RealmModel realm, UserModel user, String name, String value) {
|
||||
deleteAttribute(realm, user, name);
|
||||
em.flush();
|
||||
persistAttributeValue(realm, user, name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(RealmModel realm, UserModel user, String name) {
|
||||
deleteAttribute(realm, user, name);
|
||||
em.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultivaluedHashMap<String, String> getAttributes(RealmModel realm, UserModel user) {
|
||||
TypedQuery<FederatedUserAttributeEntity> query = em.createNamedQuery("getFederatedAttributesByUser", FederatedUserAttributeEntity.class);
|
||||
List<FederatedUserAttributeEntity> list = query
|
||||
.setParameter("userId", user.getId())
|
||||
.setParameter("realmId", realm.getId())
|
||||
.getResultList();
|
||||
MultivaluedHashMap<String, String> result = new MultivaluedHashMap<>();
|
||||
for (FederatedUserAttributeEntity entity : list) {
|
||||
result.add(entity.getName(), entity.getValue());
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUserByFederatedIdentity(FederatedIdentityModel link, RealmModel realm) {
|
||||
TypedQuery<String> query = em.createNamedQuery("findBrokerLinkByUserAndProvider", String.class)
|
||||
.setParameter("realmid", realm.getId())
|
||||
.setParameter("identityProvider", link.getIdentityProvider())
|
||||
.setParameter("brokerUserId", link.getUserId());
|
||||
List<String> results = query.getResultList();
|
||||
if (results.isEmpty()) {
|
||||
return null;
|
||||
} else if (results.size() > 1) {
|
||||
throw new IllegalStateException("More results found for identityProvider=" + link.getIdentityProvider() +
|
||||
", userId=" + link.getUserId() + ", results=" + results);
|
||||
} else {
|
||||
return results.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel link) {
|
||||
BrokerLinkEntity entity = new BrokerLinkEntity();
|
||||
entity.setRealmId(realm.getId());
|
||||
entity.setUserId(user.getId());
|
||||
entity.setBrokerUserId(link.getUserId());
|
||||
entity.setIdentityProvider(link.getIdentityProvider());
|
||||
entity.setToken(link.getToken());
|
||||
entity.setBrokerUserName(link.getUserName());
|
||||
entity.setStorageProviderId(StorageId.resolveProviderId(user));
|
||||
em.persist(entity);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeFederatedIdentity(RealmModel realm, UserModel user, String socialProvider) {
|
||||
BrokerLinkEntity entity = getBrokerLinkEntity(user, socialProvider);
|
||||
if (entity == null) return false;
|
||||
em.remove(entity);
|
||||
return true;
|
||||
}
|
||||
|
||||
private BrokerLinkEntity getBrokerLinkEntity(UserModel user, String socialProvider) {
|
||||
TypedQuery<BrokerLinkEntity> query = em.createNamedQuery("findBrokerLinkByUserAndProvider", BrokerLinkEntity.class)
|
||||
.setParameter("userId", user.getId())
|
||||
.setParameter("identityProvider", socialProvider);
|
||||
List<BrokerLinkEntity> results = query.getResultList();
|
||||
return results.size() > 0 ? results.get(0) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel model) {
|
||||
BrokerLinkEntity entity = getBrokerLinkEntity(user, model.getIdentityProvider());
|
||||
if (entity == null) return;
|
||||
entity.setBrokerUserName(model.getUserName());
|
||||
entity.setBrokerUserId(model.getUserId());
|
||||
entity.setToken(model.getToken());
|
||||
em.persist(entity);
|
||||
em.flush();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm) {
|
||||
TypedQuery<BrokerLinkEntity> query = em.createNamedQuery("findBrokerLinkByUser", BrokerLinkEntity.class)
|
||||
.setParameter("userId", user.getId());
|
||||
List<BrokerLinkEntity> results = query.getResultList();
|
||||
Set<FederatedIdentityModel> set = new HashSet<>();
|
||||
for (BrokerLinkEntity entity : results) {
|
||||
FederatedIdentityModel model = new FederatedIdentityModel(entity.getIdentityProvider(), entity.getBrokerUserId(), entity.getBrokerUserName(), entity.getToken());
|
||||
set.add(model);
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm) {
|
||||
BrokerLinkEntity entity = getBrokerLinkEntity(user, socialProvider);
|
||||
if (entity == null) return null;
|
||||
return new FederatedIdentityModel(entity.getIdentityProvider(), entity.getBrokerUserId(), entity.getBrokerUserName(), entity.getToken());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
|
||||
String clientId = consent.getClient().getId();
|
||||
|
||||
FederatedUserConsentEntity consentEntity = getGrantedConsentEntity(user, clientId);
|
||||
if (consentEntity != null) {
|
||||
throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + user.getId() + "]");
|
||||
}
|
||||
|
||||
consentEntity = new FederatedUserConsentEntity();
|
||||
consentEntity.setId(KeycloakModelUtils.generateId());
|
||||
consentEntity.setUserId(user.getId());
|
||||
consentEntity.setClientId(clientId);
|
||||
consentEntity.setStorageProviderId(StorageId.resolveProviderId(user));
|
||||
em.persist(consentEntity);
|
||||
em.flush();
|
||||
|
||||
updateGrantedConsentEntity(consentEntity, consent);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserConsentModel getConsentByClient(RealmModel realm, UserModel user, String clientInternalId) {
|
||||
FederatedUserConsentEntity entity = getGrantedConsentEntity(user, clientInternalId);
|
||||
return toConsentModel(realm, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserConsentModel> getConsents(RealmModel realm, UserModel user) {
|
||||
TypedQuery<FederatedUserConsentEntity> query = em.createNamedQuery("userFederatedConsentsByUser", FederatedUserConsentEntity.class);
|
||||
query.setParameter("userId", user.getId());
|
||||
List<FederatedUserConsentEntity> results = query.getResultList();
|
||||
|
||||
List<UserConsentModel> consents = new ArrayList<UserConsentModel>();
|
||||
for (FederatedUserConsentEntity entity : results) {
|
||||
UserConsentModel model = toConsentModel(realm, entity);
|
||||
consents.add(model);
|
||||
}
|
||||
return consents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
|
||||
String clientId = consent.getClient().getId();
|
||||
|
||||
FederatedUserConsentEntity consentEntity = getGrantedConsentEntity(user, clientId);
|
||||
if (consentEntity == null) {
|
||||
throw new ModelException("Consent not found for client [" + clientId + "] and user [" + user.getId() + "]");
|
||||
}
|
||||
|
||||
updateGrantedConsentEntity(consentEntity, consent);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean revokeConsentForClient(RealmModel realm, UserModel user, String clientInternalId) {
|
||||
FederatedUserConsentEntity consentEntity = getGrantedConsentEntity(user, clientInternalId);
|
||||
if (consentEntity == null) return false;
|
||||
|
||||
em.remove(consentEntity);
|
||||
em.flush();
|
||||
return true;
|
||||
}
|
||||
|
||||
private FederatedUserConsentEntity getGrantedConsentEntity(UserModel user, String clientId) {
|
||||
TypedQuery<FederatedUserConsentEntity> query = em.createNamedQuery("userFederatedConsentByUserAndClient", FederatedUserConsentEntity.class);
|
||||
query.setParameter("userId", user.getId());
|
||||
query.setParameter("clientId", clientId);
|
||||
List<FederatedUserConsentEntity> results = query.getResultList();
|
||||
if (results.size() > 1) {
|
||||
throw new ModelException("More results found for user [" + user.getUsername() + "] and client [" + clientId + "]");
|
||||
} else if (results.size() == 1) {
|
||||
return results.get(0);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private UserConsentModel toConsentModel(RealmModel realm, FederatedUserConsentEntity entity) {
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ClientModel client = realm.getClientById(entity.getClientId());
|
||||
if (client == null) {
|
||||
throw new ModelException("Client with id " + entity.getClientId() + " is not available");
|
||||
}
|
||||
UserConsentModel model = new UserConsentModel(client);
|
||||
|
||||
Collection<FederatedUserConsentRoleEntity> grantedRoleEntities = entity.getGrantedRoles();
|
||||
if (grantedRoleEntities != null) {
|
||||
for (FederatedUserConsentRoleEntity grantedRole : grantedRoleEntities) {
|
||||
RoleModel grantedRoleModel = realm.getRoleById(grantedRole.getRoleId());
|
||||
if (grantedRoleModel != null) {
|
||||
model.addGrantedRole(grantedRoleModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Collection<FederatedUserConsentProtocolMapperEntity> grantedProtocolMapperEntities = entity.getGrantedProtocolMappers();
|
||||
if (grantedProtocolMapperEntities != null) {
|
||||
for (FederatedUserConsentProtocolMapperEntity grantedProtMapper : grantedProtocolMapperEntities) {
|
||||
ProtocolMapperModel protocolMapper = client.getProtocolMapperById(grantedProtMapper.getProtocolMapperId());
|
||||
model.addGrantedProtocolMapper(protocolMapper);
|
||||
}
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
// Update roles and protocolMappers to given consentEntity from the consentModel
|
||||
private void updateGrantedConsentEntity(FederatedUserConsentEntity consentEntity, UserConsentModel consentModel) {
|
||||
Collection<FederatedUserConsentProtocolMapperEntity> grantedProtocolMapperEntities = consentEntity.getGrantedProtocolMappers();
|
||||
Collection<FederatedUserConsentProtocolMapperEntity> mappersToRemove = new HashSet<>(grantedProtocolMapperEntities);
|
||||
|
||||
for (ProtocolMapperModel protocolMapper : consentModel.getGrantedProtocolMappers()) {
|
||||
FederatedUserConsentProtocolMapperEntity grantedProtocolMapperEntity = new FederatedUserConsentProtocolMapperEntity();
|
||||
grantedProtocolMapperEntity.setUserConsent(consentEntity);
|
||||
grantedProtocolMapperEntity.setProtocolMapperId(protocolMapper.getId());
|
||||
|
||||
// Check if it's already there
|
||||
if (!grantedProtocolMapperEntities.contains(grantedProtocolMapperEntity)) {
|
||||
em.persist(grantedProtocolMapperEntity);
|
||||
em.flush();
|
||||
grantedProtocolMapperEntities.add(grantedProtocolMapperEntity);
|
||||
} else {
|
||||
mappersToRemove.remove(grantedProtocolMapperEntity);
|
||||
}
|
||||
}
|
||||
// Those mappers were no longer on consentModel and will be removed
|
||||
for (FederatedUserConsentProtocolMapperEntity toRemove : mappersToRemove) {
|
||||
grantedProtocolMapperEntities.remove(toRemove);
|
||||
em.remove(toRemove);
|
||||
}
|
||||
|
||||
Collection<FederatedUserConsentRoleEntity> grantedRoleEntities = consentEntity.getGrantedRoles();
|
||||
Set<FederatedUserConsentRoleEntity> rolesToRemove = new HashSet<>(grantedRoleEntities);
|
||||
for (RoleModel role : consentModel.getGrantedRoles()) {
|
||||
FederatedUserConsentRoleEntity consentRoleEntity = new FederatedUserConsentRoleEntity();
|
||||
consentRoleEntity.setUserConsent(consentEntity);
|
||||
consentRoleEntity.setRoleId(role.getId());
|
||||
|
||||
// Check if it's already there
|
||||
if (!grantedRoleEntities.contains(consentRoleEntity)) {
|
||||
em.persist(consentRoleEntity);
|
||||
em.flush();
|
||||
grantedRoleEntities.add(consentRoleEntity);
|
||||
} else {
|
||||
rolesToRemove.remove(consentRoleEntity);
|
||||
}
|
||||
}
|
||||
// Those roles were no longer on consentModel and will be removed
|
||||
for (FederatedUserConsentRoleEntity toRemove : rolesToRemove) {
|
||||
grantedRoleEntities.remove(toRemove);
|
||||
em.remove(toRemove);
|
||||
}
|
||||
|
||||
em.flush();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public List<UserCredentialValueModel> getCredentials(RealmModel realm, UserModel user) {
|
||||
TypedQuery<FederatedUserCredentialEntity> query = em.createNamedQuery("federatedUserCredentialByUser", FederatedUserCredentialEntity.class)
|
||||
.setParameter("userId", user.getId());
|
||||
List<FederatedUserCredentialEntity> results = query.getResultList();
|
||||
List<UserCredentialValueModel> list = new LinkedList<>();
|
||||
for (FederatedUserCredentialEntity credEntity : results) {
|
||||
UserCredentialValueModel credModel = new UserCredentialValueModel();
|
||||
credModel.setId(credEntity.getId());
|
||||
credModel.setType(credEntity.getType());
|
||||
credModel.setDevice(credEntity.getDevice());
|
||||
credModel.setValue(credEntity.getValue());
|
||||
credModel.setCreatedDate(credEntity.getCreatedDate());
|
||||
credModel.setSalt(credEntity.getSalt());
|
||||
credModel.setHashIterations(credEntity.getHashIterations());
|
||||
credModel.setCounter(credEntity.getCounter());
|
||||
credModel.setAlgorithm(credEntity.getAlgorithm());
|
||||
credModel.setDigits(credEntity.getDigits());
|
||||
credModel.setPeriod(credEntity.getPeriod());
|
||||
|
||||
list.add(credModel);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCredential(RealmModel realm, UserModel user, UserCredentialModel cred) {
|
||||
FederatedCredentials.updateCredential(session, this, realm, user, cred);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCredential(RealmModel realm, UserModel user, UserCredentialValueModel cred) {
|
||||
FederatedUserCredentialEntity entity = null;
|
||||
if (cred.getId() != null) entity = em.find(FederatedUserCredentialEntity.class, cred.getId());
|
||||
boolean newEntity = false;
|
||||
if (entity == null) {
|
||||
entity = new FederatedUserCredentialEntity();
|
||||
entity.setId(KeycloakModelUtils.generateId());
|
||||
newEntity = true;
|
||||
}
|
||||
entity.setUserId(user.getId());
|
||||
entity.setRealmId(realm.getId());
|
||||
entity.setStorageProviderId(StorageId.resolveProviderId(user));
|
||||
entity.setAlgorithm(cred.getAlgorithm());
|
||||
entity.setCounter(cred.getCounter());
|
||||
Long createdDate = cred.getCreatedDate();
|
||||
if (createdDate == null) createdDate = System.currentTimeMillis();
|
||||
entity.setCreatedDate(createdDate);
|
||||
entity.setDevice(cred.getDevice());
|
||||
entity.setDigits(cred.getDigits());
|
||||
entity.setHashIterations(cred.getHashIterations());
|
||||
entity.setPeriod(cred.getPeriod());
|
||||
entity.setSalt(cred.getSalt());
|
||||
entity.setType(cred.getType());
|
||||
entity.setValue(cred.getValue());
|
||||
if (newEntity) {
|
||||
em.persist(entity);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCredential(RealmModel realm, UserModel user, UserCredentialValueModel cred) {
|
||||
FederatedUserCredentialEntity entity = em.find(FederatedUserCredentialEntity.class, cred.getId());
|
||||
em.remove(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<GroupModel> getGroups(RealmModel realm, UserModel user) {
|
||||
Set<GroupModel> set = new HashSet<>();
|
||||
TypedQuery<FederatedUserGroupMembershipEntity> query = em.createNamedQuery("feduserGroupMembership", FederatedUserGroupMembershipEntity.class);
|
||||
query.setParameter("userId", user.getId());
|
||||
List<FederatedUserGroupMembershipEntity> results = query.getResultList();
|
||||
if (results.size() == 0) return set;
|
||||
for (FederatedUserGroupMembershipEntity entity : results) {
|
||||
GroupModel group = realm.getGroupById(entity.getGroupId());
|
||||
set.add(group);
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void joinGroup(RealmModel realm, UserModel user, GroupModel group) {
|
||||
if (isMemberOf(realm, user, group)) return;
|
||||
FederatedUserGroupMembershipEntity entity = new FederatedUserGroupMembershipEntity();
|
||||
entity.setUserId(user.getId());
|
||||
entity.setStorageProviderId(StorageId.resolveProviderId(user));
|
||||
entity.setGroupId(group.getId());
|
||||
entity.setRealmId(realm.getId());
|
||||
em.persist(entity);
|
||||
|
||||
}
|
||||
|
||||
public boolean isMemberOf(RealmModel realm, UserModel user, GroupModel group) {
|
||||
Set<GroupModel> roles = user.getGroups();
|
||||
return KeycloakModelUtils.isMember(roles, group);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void leaveGroup(RealmModel realm, UserModel user, GroupModel group) {
|
||||
if (user == null || group == null) return;
|
||||
|
||||
TypedQuery<FederatedUserGroupMembershipEntity> query1 = em.createNamedQuery("feduserMemberOf", FederatedUserGroupMembershipEntity.class);
|
||||
query1.setParameter("userId", user.getId());
|
||||
query1.setParameter("groupId", group.getId());
|
||||
TypedQuery<FederatedUserGroupMembershipEntity> query = query1;
|
||||
List<FederatedUserGroupMembershipEntity> results = query.getResultList();
|
||||
if (results.size() == 0) return;
|
||||
for (FederatedUserGroupMembershipEntity entity : results) {
|
||||
em.remove(entity);
|
||||
}
|
||||
em.flush();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Set<String> getRequiredActions(RealmModel realm, UserModel user) {
|
||||
Set<String> set = new HashSet<>();
|
||||
List<FederatedUserRequiredActionEntity> values = getRequiredActionEntities(realm, user);
|
||||
for (FederatedUserRequiredActionEntity entity : values) {
|
||||
set.add(entity.getAction());
|
||||
}
|
||||
|
||||
return set;
|
||||
|
||||
}
|
||||
|
||||
private List<FederatedUserRequiredActionEntity> getRequiredActionEntities(RealmModel realm, UserModel user) {
|
||||
TypedQuery<FederatedUserRequiredActionEntity> query = em.createNamedQuery("getFederatedUserRequiredActionsByUser", FederatedUserRequiredActionEntity.class)
|
||||
.setParameter("userId", user.getId())
|
||||
.setParameter("realmId", realm.getId());
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRequiredAction(RealmModel realm, UserModel user, String action) {
|
||||
if (user.getRequiredActions().contains(action)) return;
|
||||
FederatedUserRequiredActionEntity entity = new FederatedUserRequiredActionEntity();
|
||||
entity.setUserId(user.getId());
|
||||
entity.setRealmId(realm.getId());
|
||||
entity.setStorageProviderId(StorageId.resolveProviderId(user));
|
||||
entity.setAction(action);
|
||||
em.persist(entity);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRequiredAction(RealmModel realm, UserModel user, String action) {
|
||||
List<FederatedUserRequiredActionEntity> values = getRequiredActionEntities(realm, user);
|
||||
for (FederatedUserRequiredActionEntity entity : values) {
|
||||
if (action.equals(entity.getAction())) em.remove(entity);
|
||||
}
|
||||
em.flush();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void grantRole(RealmModel realm, UserModel user, RoleModel role) {
|
||||
if (user.hasRole(role)) return;
|
||||
FederatedUserRoleMappingEntity entity = new FederatedUserRoleMappingEntity();
|
||||
entity.setUserId(user.getId());
|
||||
entity.setStorageProviderId(StorageId.resolveProviderId(user));
|
||||
entity.setRealmId(realm.getId());
|
||||
entity.setRoleId(role.getId());
|
||||
em.persist(entity);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRoleMappings(RealmModel realm, UserModel user) {
|
||||
Set<RoleModel> set = new HashSet<>();
|
||||
TypedQuery<FederatedUserRoleMappingEntity> query = em.createNamedQuery("feduserRoleMappings", FederatedUserRoleMappingEntity.class);
|
||||
query.setParameter("userId", user.getId());
|
||||
List<FederatedUserRoleMappingEntity> results = query.getResultList();
|
||||
if (results.size() == 0) return set;
|
||||
for (FederatedUserRoleMappingEntity entity : results) {
|
||||
RoleModel role = realm.getRoleById(entity.getRoleId());
|
||||
set.add(role);
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteRoleMapping(RealmModel realm, UserModel user, RoleModel role) {
|
||||
TypedQuery<FederatedUserRoleMappingEntity> query = em.createNamedQuery("feduserRoleMappings", FederatedUserRoleMappingEntity.class);
|
||||
query.setParameter("userId", user.getId());
|
||||
List<FederatedUserRoleMappingEntity> results = query.getResultList();
|
||||
for (FederatedUserRoleMappingEntity entity : results) {
|
||||
if (entity.getRoleId().equals(role.getId())) em.remove(entity);
|
||||
|
||||
}
|
||||
em.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm) {
|
||||
int num = em.createNamedQuery("deleteUserConsentRolesByRealm")
|
||||
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||
num = em.createNamedQuery("deleteFederatedUserConsentProtMappersByRealm")
|
||||
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||
num = em.createNamedQuery("deleteFederatedUserConsentsByRealm")
|
||||
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||
num = em.createNamedQuery("deleteFederatedUserRoleMappingsByRealm")
|
||||
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||
num = em.createNamedQuery("deleteFederatedUserRequiredActionsByRealm")
|
||||
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||
num = em.createNamedQuery("deleteBrokerLinkByRealm")
|
||||
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||
num = em.createNamedQuery("deleteFederatedUserCredentialsByRealm")
|
||||
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||
num = em.createNamedQuery("deleteUserFederatedAttributesByRealm")
|
||||
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||
num = em.createNamedQuery("deleteFederatedUserGroupMembershipByRealm")
|
||||
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, UserFederationProviderModel link) {
|
||||
int num = em.createNamedQuery("deleteFederatedUserRoleMappingsByRealmAndLink")
|
||||
.setParameter("realmId", realm.getId())
|
||||
.setParameter("link", link.getId())
|
||||
.executeUpdate();
|
||||
num = em.createNamedQuery("deleteFederatedUserRequiredActionsByRealmAndLink")
|
||||
.setParameter("realmId", realm.getId())
|
||||
.setParameter("link", link.getId())
|
||||
.executeUpdate();
|
||||
num = em.createNamedQuery("deleteBrokerLinkByRealmAndLink")
|
||||
.setParameter("realmId", realm.getId())
|
||||
.setParameter("link", link.getId())
|
||||
.executeUpdate();
|
||||
num = em.createNamedQuery("deleteFederatedUserCredentialsByRealmAndLink")
|
||||
.setParameter("realmId", realm.getId())
|
||||
.setParameter("link", link.getId())
|
||||
.executeUpdate();
|
||||
num = em.createNamedQuery("deleteUserFederatedAttributesByRealmAndLink")
|
||||
.setParameter("realmId", realm.getId())
|
||||
.setParameter("link", link.getId())
|
||||
.executeUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, RoleModel role) {
|
||||
em.createNamedQuery("deleteFederatedUserRoleMappingsByRole").setParameter("roleId", role.getId()).executeUpdate();
|
||||
em.createNamedQuery("deleteFederatedUserRoleMappingsByRole").setParameter("roleId", role.getId()).executeUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, GroupModel group) {
|
||||
em.createNamedQuery("deleteFederatedUserGroupMembershipsByGroup").setParameter("groupId", group.getId()).executeUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, ClientModel client) {
|
||||
em.createNamedQuery("deleteFederatedUserConsentProtMappersByClient").setParameter("clientId", client.getId()).executeUpdate();
|
||||
em.createNamedQuery("deleteFederatedUserConsentRolesByClient").setParameter("clientId", client.getId()).executeUpdate();
|
||||
em.createNamedQuery("deleteFederatedUserConsentsByClient").setParameter("clientId", client.getId()).executeUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(ProtocolMapperModel protocolMapper) {
|
||||
em.createNamedQuery("deleteFederatedUserConsentProtMappersByProtocolMapper")
|
||||
.setParameter("protocolMapperId", protocolMapper.getId())
|
||||
.executeUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, UserModel user) {
|
||||
em.createNamedQuery("deleteBrokerLinkByUser")
|
||||
.setParameter("userId", user.getId())
|
||||
.setParameter("realmId", realm.getId())
|
||||
.executeUpdate();
|
||||
em.createNamedQuery("deleteUserFederatedAttributesByUser")
|
||||
.setParameter("userId", user.getId())
|
||||
.setParameter("realmId", realm.getId())
|
||||
.executeUpdate();
|
||||
em.createNamedQuery("deleteFederatedUserConsentProtMappersByUser")
|
||||
.setParameter("userId", user.getId())
|
||||
.setParameter("realmId", realm.getId())
|
||||
.executeUpdate();
|
||||
em.createNamedQuery("deleteFederatedUserConsentRolesByUser")
|
||||
.setParameter("userId", user.getId())
|
||||
.setParameter("realmId", realm.getId())
|
||||
.executeUpdate();
|
||||
em.createNamedQuery("deleteFederatedUserConsentsByUser")
|
||||
.setParameter("userId", user.getId())
|
||||
.setParameter("realmId", realm.getId())
|
||||
.executeUpdate();
|
||||
em.createNamedQuery("deleteFederatedUserCredentialByUser")
|
||||
.setParameter("userId", user.getId())
|
||||
.setParameter("realmId", realm.getId())
|
||||
.executeUpdate();
|
||||
em.createNamedQuery("deleteFederatedUserGroupMembershipsByUser")
|
||||
.setParameter("userId", user.getId())
|
||||
.setParameter("realmId", realm.getId())
|
||||
.executeUpdate();
|
||||
em.createNamedQuery("getFederatedUserRequiredActionsByUser")
|
||||
.setParameter("userId", user.getId())
|
||||
.setParameter("realmId", realm.getId())
|
||||
.executeUpdate();
|
||||
em.createNamedQuery("deleteFederatedUserRoleMappingsByUser")
|
||||
.setParameter("userId", user.getId())
|
||||
.setParameter("realmId", realm.getId())
|
||||
.executeUpdate();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, StorageProviderModel model) {
|
||||
em.createNamedQuery("deleteBrokerLinkByStorageProvider")
|
||||
.setParameter("storageProviderId", model.getId())
|
||||
.executeUpdate();
|
||||
em.createNamedQuery("deleteFederatedAttributesByStorageProvider")
|
||||
.setParameter("storageProviderId", model.getId())
|
||||
.executeUpdate();
|
||||
em.createNamedQuery("deleteFederatedUserConsentProtMappersByStorageProvider")
|
||||
.setParameter("storageProviderId", model.getId())
|
||||
.executeUpdate();
|
||||
em.createNamedQuery("deleteFederatedUserRoleMappingsByStorageProvider")
|
||||
.setParameter("storageProviderId", model.getId())
|
||||
.executeUpdate();
|
||||
em.createNamedQuery("deleteFederatedUserConsentsByStorageProvider")
|
||||
.setParameter("storageProviderId", model.getId())
|
||||
.executeUpdate();
|
||||
em.createNamedQuery("deleteFederatedUserCredentialsByStorageProvider")
|
||||
.setParameter("storageProviderId", model.getId())
|
||||
.executeUpdate();
|
||||
em.createNamedQuery("deleteFederatedUserGroupMembershipByStorageProvider")
|
||||
.setParameter("storageProviderId", model.getId())
|
||||
.executeUpdate();
|
||||
em.createNamedQuery("deleteFederatedUserRequiredActionsByStorageProvider")
|
||||
.setParameter("storageProviderId", model.getId())
|
||||
.executeUpdate();
|
||||
em.createNamedQuery("deleteFederatedUserRoleMappingsByStorageProvider")
|
||||
.setParameter("storageProviderId", model.getId())
|
||||
.executeUpdate();
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage.jpa;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.connections.jpa.JpaConnectionProvider;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.storage.federated.UserFederatedStorageProvider;
|
||||
import org.keycloak.storage.federated.UserFederatedStorageProviderFactory;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class JpaUserFederatedStorageProviderFactory implements UserFederatedStorageProviderFactory {
|
||||
@Override
|
||||
public UserFederatedStorageProvider create(KeycloakSession session) {
|
||||
EntityManager em = session.getProvider(JpaConnectionProvider.class).getEntityManager();
|
||||
return new JpaUserFederatedStorageProvider(session, em);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "jpa";
|
||||
}
|
||||
}
|
191
model/jpa/src/main/java/org/keycloak/storage/jpa/entity/BrokerLinkEntity.java
Executable file
191
model/jpa/src/main/java/org/keycloak/storage/jpa/entity/BrokerLinkEntity.java
Executable file
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.storage.jpa.entity;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
@NamedQueries({
|
||||
@NamedQuery(name= "findBrokerLinkByUser", query="select link from BrokerLinkEntity link where link.userId = :userId"),
|
||||
@NamedQuery(name= "findBrokerLinkByUserAndProvider", query="select link from BrokerLinkEntity link where link.userId = :userId and link.identityProvider = :identityProvider"),
|
||||
@NamedQuery(name= "findUserByBrokerLinkAndRealm", query="select link.userId from BrokerLinkEntity link where link.realmId = :realmId and link.identityProvider = :identityProvider and link.brokerUserId = :brokerUserId"),
|
||||
@NamedQuery(name= "deleteBrokerLinkByStorageProvider", query="delete from BrokerLinkEntity social where social.storageProviderId = :storageProviderId"),
|
||||
@NamedQuery(name= "deleteBrokerLinkByRealm", query="delete from BrokerLinkEntity social where social.realmId = :realmId"),
|
||||
@NamedQuery(name= "deleteBrokerLinkByRealmAndLink", query="delete from BrokerLinkEntity social where social.userId IN (select u.id from UserEntity u where realmId=:realmId and u.federationLink=:link)"),
|
||||
@NamedQuery(name= "deleteBrokerLinkByUser", query="delete from BrokerLinkEntity social where social.userId = :userId and social.realmId = :realmId")
|
||||
})
|
||||
@Table(name="BROKER_LINK")
|
||||
@Entity
|
||||
@IdClass(BrokerLinkEntity.Key.class)
|
||||
public class BrokerLinkEntity {
|
||||
|
||||
@Id
|
||||
private String userId;
|
||||
|
||||
@Id
|
||||
@Column(name = "IDENTITY_PROVIDER")
|
||||
protected String identityProvider;
|
||||
|
||||
@Column(name = "REALM_ID")
|
||||
protected String realmId;
|
||||
|
||||
@Column(name = "STORAGE_PROVIDER_ID")
|
||||
protected String storageProviderId;
|
||||
|
||||
@Column(name = "BROKER_USER_ID")
|
||||
protected String brokerUserId;
|
||||
@Column(name = "BROKER_USERNAME")
|
||||
protected String brokerUserName;
|
||||
|
||||
@Column(name = "TOKEN")
|
||||
protected String token;
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getIdentityProvider() {
|
||||
return identityProvider;
|
||||
}
|
||||
|
||||
public void setIdentityProvider(String identityProvider) {
|
||||
this.identityProvider = identityProvider;
|
||||
}
|
||||
|
||||
public String getBrokerUserId() {
|
||||
return brokerUserId;
|
||||
}
|
||||
|
||||
public void setBrokerUserId(String brokerUserId) {
|
||||
this.brokerUserId = brokerUserId;
|
||||
}
|
||||
|
||||
public String getBrokerUserName() {
|
||||
return brokerUserName;
|
||||
}
|
||||
|
||||
public void setBrokerUserName(String brokerUserName) {
|
||||
this.brokerUserName = brokerUserName;
|
||||
}
|
||||
|
||||
public String getStorageProviderId() {
|
||||
return storageProviderId;
|
||||
}
|
||||
|
||||
public void setStorageProviderId(String storageProviderId) {
|
||||
this.storageProviderId = storageProviderId;
|
||||
}
|
||||
|
||||
public String getRealmId() {
|
||||
return realmId;
|
||||
}
|
||||
|
||||
public void setRealmId(String realmId) {
|
||||
this.realmId = realmId;
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public static class Key implements Serializable {
|
||||
|
||||
protected String userId;
|
||||
|
||||
protected String identityProvider;
|
||||
|
||||
public Key() {
|
||||
}
|
||||
|
||||
public Key(String userId, String identityProvider) {
|
||||
this.userId = userId;
|
||||
this.identityProvider = identityProvider;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public String getIdentityProvider() {
|
||||
return identityProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Key key = (Key) o;
|
||||
|
||||
if (identityProvider != null ? !identityProvider.equals(key.identityProvider) : key.identityProvider != null)
|
||||
return false;
|
||||
if (userId != null ? !userId.equals(key.userId != null ? key.userId : null) : key.userId != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = userId != null ? userId.hashCode() : 0;
|
||||
result = 31 * result + (identityProvider != null ? identityProvider.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null) return false;
|
||||
if (!(o instanceof BrokerLinkEntity)) return false;
|
||||
|
||||
BrokerLinkEntity key = (BrokerLinkEntity) o;
|
||||
|
||||
if (identityProvider != null ? !identityProvider.equals(key.identityProvider) : key.identityProvider != null)
|
||||
return false;
|
||||
if (userId != null ? !userId.equals(key.userId != null ? key.userId : null) : key.userId != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = userId != null ? userId.hashCode() : 0;
|
||||
result = 31 * result + (identityProvider != null ? identityProvider.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.storage.jpa.entity;
|
||||
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
@NamedQueries({
|
||||
@NamedQuery(name="getFederatedAttributesByNameAndValue", query="select attr from FederatedUserAttributeEntity attr where attr.name = :name and attr.value = :value and attr.realmId=:realmId"),
|
||||
@NamedQuery(name="getFederatedAttributesByUser", query="select attr from FederatedUserAttributeEntity attr where attr.userId = :userId and attr.realmId=:realmId"),
|
||||
@NamedQuery(name="deleteUserFederatedAttributesByUser", query="delete from FederatedUserAttributeEntity attr where attr.userId = :userId and attr.realmId=:realmId"),
|
||||
@NamedQuery(name="deleteUserFederatedAttributesByUserAndName", query="delete from FederatedUserAttributeEntity attr where attr.userId = :userId and attr.name=:name and attr.realmId=:realmId"),
|
||||
@NamedQuery(name="deleteUserFederatedAttributesByRealm", query="delete from FederatedUserAttributeEntity attr where attr.realmId=:realmId"),
|
||||
@NamedQuery(name="deleteFederatedAttributesByStorageProvider", query="delete from FederatedUserAttributeEntity e where e.storageProviderId=:storageProviderId"),
|
||||
@NamedQuery(name="deleteUserFederatedAttributesByRealmAndLink", query="delete from FederatedUserAttributeEntity attr where attr.userId IN (select u.id from UserEntity u where u.realmId=:realmId and u.federationLink=:link)")
|
||||
})
|
||||
@Table(name="FED_USER_ATTRIBUTE")
|
||||
@Entity
|
||||
public class FederatedUserAttributeEntity {
|
||||
|
||||
@Id
|
||||
@Column(name="ID", length = 36)
|
||||
@Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity. This avoids an extra SQL
|
||||
protected String id;
|
||||
|
||||
@Column(name = "USER_ID")
|
||||
protected String userId;
|
||||
|
||||
@Column(name = "REALM_ID")
|
||||
protected String realmId;
|
||||
|
||||
@Column(name = "STORAGE_PROVIDER_ID")
|
||||
protected String storageProviderId;
|
||||
|
||||
@Column(name = "NAME")
|
||||
protected String name;
|
||||
@Column(name = "VALUE")
|
||||
protected String value;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getRealmId() {
|
||||
return realmId;
|
||||
}
|
||||
|
||||
public void setRealmId(String realmId) {
|
||||
this.realmId = realmId;
|
||||
}
|
||||
|
||||
public String getStorageProviderId() {
|
||||
return storageProviderId;
|
||||
}
|
||||
|
||||
public void setStorageProviderId(String storageProviderId) {
|
||||
this.storageProviderId = storageProviderId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null) return false;
|
||||
if (!(o instanceof FederatedUserAttributeEntity)) return false;
|
||||
|
||||
FederatedUserAttributeEntity that = (FederatedUserAttributeEntity) o;
|
||||
|
||||
if (!id.equals(that.getId())) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id.hashCode();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.storage.jpa.entity;
|
||||
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
@Entity
|
||||
@Table(name="FED_USER_CONSENT", uniqueConstraints = {
|
||||
@UniqueConstraint(columnNames = {"USER_ID", "CLIENT_ID"})
|
||||
})
|
||||
@NamedQueries({
|
||||
@NamedQuery(name="userFederatedConsentByUserAndClient", query="select consent from UserConsentEntity consent where consent.userId = :userId and consent.clientId = :clientId"),
|
||||
@NamedQuery(name="userFederatedConsentsByUser", query="select consent from UserConsentEntity consent where consent.userId = :userId"),
|
||||
@NamedQuery(name="deleteFederatedUserConsentsByRealm", query="delete from UserConsentEntity consent where consent.realmId=:realmId"),
|
||||
@NamedQuery(name="deleteFederatedUserConsentsByStorageProvider", query="delete from FederatedUserConsentEntity e where e.storageProviderId=:storageProviderId"),
|
||||
@NamedQuery(name="deleteFederatedUserConsentsByUser", query="delete from UserConsentEntity consent where consent.userId = :userId and consent.realmId = :realmId"),
|
||||
@NamedQuery(name="deleteFederatedUserConsentsByClient", query="delete from UserConsentEntity consent where consent.clientId = :clientId"),
|
||||
})
|
||||
public class FederatedUserConsentEntity {
|
||||
|
||||
@Id
|
||||
@Column(name="ID", length = 36)
|
||||
@Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity. This avoids an extra SQL
|
||||
protected String id;
|
||||
|
||||
@Column(name = "USER_ID")
|
||||
protected String userId;
|
||||
|
||||
@Column(name = "REALM_ID")
|
||||
protected String realmId;
|
||||
|
||||
@Column(name = "STORAGE_PROVIDER_ID")
|
||||
protected String storageProviderId;
|
||||
|
||||
@Column(name="CLIENT_ID")
|
||||
protected String clientId;
|
||||
|
||||
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "userConsent")
|
||||
Collection<FederatedUserConsentRoleEntity> grantedRoles = new ArrayList<FederatedUserConsentRoleEntity>();
|
||||
|
||||
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "userConsent")
|
||||
Collection<FederatedUserConsentProtocolMapperEntity> grantedProtocolMappers = new ArrayList<FederatedUserConsentProtocolMapperEntity>();
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getRealmId() {
|
||||
return realmId;
|
||||
}
|
||||
|
||||
public void setRealmId(String realmId) {
|
||||
this.realmId = realmId;
|
||||
}
|
||||
|
||||
public String getStorageProviderId() {
|
||||
return storageProviderId;
|
||||
}
|
||||
|
||||
public void setStorageProviderId(String storageProviderId) {
|
||||
this.storageProviderId = storageProviderId;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public void setClientId(String clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
public Collection<FederatedUserConsentRoleEntity> getGrantedRoles() {
|
||||
return grantedRoles;
|
||||
}
|
||||
|
||||
public void setGrantedRoles(Collection<FederatedUserConsentRoleEntity> grantedRoles) {
|
||||
this.grantedRoles = grantedRoles;
|
||||
}
|
||||
|
||||
public Collection<FederatedUserConsentProtocolMapperEntity> getGrantedProtocolMappers() {
|
||||
return grantedProtocolMappers;
|
||||
}
|
||||
|
||||
public void setGrantedProtocolMappers(Collection<FederatedUserConsentProtocolMapperEntity> grantedProtocolMappers) {
|
||||
this.grantedProtocolMappers = grantedProtocolMappers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null) return false;
|
||||
if (!(o instanceof FederatedUserConsentEntity)) return false;
|
||||
|
||||
FederatedUserConsentEntity that = (FederatedUserConsentEntity) o;
|
||||
|
||||
if (!id.equals(that.getId())) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id.hashCode();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.storage.jpa.entity;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
@NamedQueries({
|
||||
@NamedQuery(name="deleteFederatedUserConsentProtMappersByRealm", query=
|
||||
"delete from FederatedUserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.realmId = :realmId)"),
|
||||
@NamedQuery(name="deleteFederatedUserConsentProtMappersByUser", query="delete from FederatedUserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.userId = :userId and consent.realmId = :realmId)"),
|
||||
@NamedQuery(name="deleteFederatedUserConsentProtMappersByStorageProvider", query="delete from FederatedUserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.storageProviderId = :storageProviderId)"),
|
||||
@NamedQuery(name="deleteFederatedUserConsentProtMappersByProtocolMapper", query="delete from FederatedUserConsentProtocolMapperEntity csm where csm.protocolMapperId = :protocolMapperId"),
|
||||
@NamedQuery(name="deleteFederatedUserConsentProtMappersByClient", query="delete from FederatedUserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.clientId = :clientId)"),
|
||||
})
|
||||
@Entity
|
||||
@Table(name="FED_USER_CONSENT_PROT_MAPPER")
|
||||
@IdClass(FederatedUserConsentProtocolMapperEntity.Key.class)
|
||||
public class FederatedUserConsentProtocolMapperEntity {
|
||||
|
||||
@Id
|
||||
@ManyToOne(fetch= FetchType.LAZY)
|
||||
@JoinColumn(name = "USER_CONSENT_ID")
|
||||
protected FederatedUserConsentEntity userConsent;
|
||||
|
||||
@Id
|
||||
@Column(name="PROTOCOL_MAPPER_ID")
|
||||
protected String protocolMapperId;
|
||||
|
||||
public FederatedUserConsentEntity getUserConsent() {
|
||||
return userConsent;
|
||||
}
|
||||
|
||||
public void setUserConsent(FederatedUserConsentEntity userConsent) {
|
||||
this.userConsent = userConsent;
|
||||
}
|
||||
|
||||
public String getProtocolMapperId() {
|
||||
return protocolMapperId;
|
||||
}
|
||||
|
||||
public void setProtocolMapperId(String protocolMapperId) {
|
||||
this.protocolMapperId = protocolMapperId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null) return false;
|
||||
if (!(o instanceof FederatedUserConsentProtocolMapperEntity)) return false;
|
||||
|
||||
FederatedUserConsentProtocolMapperEntity that = (FederatedUserConsentProtocolMapperEntity)o;
|
||||
Key myKey = new Key(this.userConsent, this.protocolMapperId);
|
||||
Key hisKey = new Key(that.userConsent, that.protocolMapperId);
|
||||
return myKey.equals(hisKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
Key myKey = new Key(this.userConsent, this.protocolMapperId);
|
||||
return myKey.hashCode();
|
||||
}
|
||||
|
||||
public static class Key implements Serializable {
|
||||
|
||||
protected FederatedUserConsentEntity userConsent;
|
||||
|
||||
protected String protocolMapperId;
|
||||
|
||||
public Key() {
|
||||
}
|
||||
|
||||
public Key(FederatedUserConsentEntity userConsent, String protocolMapperId) {
|
||||
this.userConsent = userConsent;
|
||||
this.protocolMapperId = protocolMapperId;
|
||||
}
|
||||
|
||||
public FederatedUserConsentEntity getUserConsent() {
|
||||
return userConsent;
|
||||
}
|
||||
|
||||
public String getProtocolMapperId() {
|
||||
return protocolMapperId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Key key = (Key) o;
|
||||
|
||||
if (userConsent != null ? !userConsent.getId().equals(key.userConsent != null ? key.userConsent.getId() : null) : key.userConsent != null) return false;
|
||||
if (protocolMapperId != null ? !protocolMapperId.equals(key.protocolMapperId) : key.protocolMapperId != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = userConsent != null ? userConsent.getId().hashCode() : 0;
|
||||
result = 31 * result + (protocolMapperId != null ? protocolMapperId.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.storage.jpa.entity;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
@NamedQueries({
|
||||
@NamedQuery(name="deleteFederatedUserConsentRolesByRealm", query="delete from FederatedUserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.realmId = :realmId)"),
|
||||
@NamedQuery(name="deleteFederatedUserConsentRolesByUser", query="delete from FederatedUserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.userId = :userId and consent.realmId = :realmId)"),
|
||||
@NamedQuery(name="deleteFederatedUserConsentRolesByStorageProvider", query="delete from FederatedUserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.storageProviderId = :storageProviderId)"),
|
||||
@NamedQuery(name="deleteFederatedUserConsentRolesByRole", query="delete from FederatedUserConsentRoleEntity grantedRole where grantedRole.roleId = :roleId"),
|
||||
@NamedQuery(name="deleteFederatedUserConsentRolesByClient", query="delete from FederatedUserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.clientId = :clientId)"),
|
||||
})
|
||||
@Entity
|
||||
@Table(name="FED_USER_CONSENT_ROLE")
|
||||
@IdClass(FederatedUserConsentRoleEntity.Key.class)
|
||||
public class FederatedUserConsentRoleEntity {
|
||||
|
||||
@Id
|
||||
@ManyToOne(fetch= FetchType.LAZY)
|
||||
@JoinColumn(name = "USER_CONSENT_ID")
|
||||
protected FederatedUserConsentEntity userConsent;
|
||||
|
||||
@Id
|
||||
@Column(name="ROLE_ID")
|
||||
protected String roleId;
|
||||
|
||||
public FederatedUserConsentEntity getUserConsent() {
|
||||
return userConsent;
|
||||
}
|
||||
|
||||
public void setUserConsent(FederatedUserConsentEntity userConsent) {
|
||||
this.userConsent = userConsent;
|
||||
}
|
||||
|
||||
public String getRoleId() {
|
||||
return roleId;
|
||||
}
|
||||
|
||||
public void setRoleId(String roleId) {
|
||||
this.roleId = roleId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null) return false;
|
||||
if (!(o instanceof FederatedUserConsentRoleEntity)) return false;
|
||||
|
||||
FederatedUserConsentRoleEntity that = (FederatedUserConsentRoleEntity)o;
|
||||
Key myKey = new Key(this.userConsent, this.roleId);
|
||||
Key hisKey = new Key(that.userConsent, that.roleId);
|
||||
return myKey.equals(hisKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
Key myKey = new Key(this.userConsent, this.roleId);
|
||||
return myKey.hashCode();
|
||||
}
|
||||
|
||||
public static class Key implements Serializable {
|
||||
|
||||
protected FederatedUserConsentEntity userConsent;
|
||||
|
||||
protected String roleId;
|
||||
|
||||
public Key() {
|
||||
}
|
||||
|
||||
public Key(FederatedUserConsentEntity userConsent, String roleId) {
|
||||
this.userConsent = userConsent;
|
||||
this.roleId = roleId;
|
||||
}
|
||||
|
||||
public FederatedUserConsentEntity getUserConsent() {
|
||||
return userConsent;
|
||||
}
|
||||
|
||||
public String getRoleId() {
|
||||
return roleId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Key key = (Key) o;
|
||||
|
||||
if (userConsent != null ? !userConsent.getId().equals(key.userConsent != null ? key.userConsent.getId() : null) : key.userConsent != null) return false;
|
||||
if (roleId != null ? !roleId.equals(key.roleId) : key.roleId != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = userConsent != null ? userConsent.getId().hashCode() : 0;
|
||||
result = 31 * result + (roleId != null ? roleId.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.storage.jpa.entity;
|
||||
|
||||
import org.keycloak.models.jpa.entities.UserEntity;
|
||||
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
@NamedQueries({
|
||||
@NamedQuery(name="federatedUserCredentialByUser", query="select cred from FederatedUserCredentialEntity cred where cred.userId = :userId"),
|
||||
@NamedQuery(name="federatedUserCredentialByUserAndType", query="select cred from FederatedUserCredentialEntity cred where cred.userId = :userId and cred.type = :type"),
|
||||
@NamedQuery(name="deleteFederatedUserCredentialByUser", query="delete from FederatedUserCredentialEntity cred where cred.userId = :userId and cred.realmId = :realmId"),
|
||||
@NamedQuery(name="deleteFederatedUserCredentialByUserAndType", query="delete from FederatedUserCredentialEntity cred where cred.userId = :userId and cred.type = :type"),
|
||||
@NamedQuery(name="deleteFederatedUserCredentialByUserAndTypeAndDevice", query="delete from FederatedUserCredentialEntity cred where cred.userId = :userId and cred.type = :type and cred.device = :device"),
|
||||
@NamedQuery(name="deleteFederatedUserCredentialsByRealm", query="delete from FederatedUserCredentialEntity cred where cred.realmId=:realmId"),
|
||||
@NamedQuery(name="deleteFederatedUserCredentialsByStorageProvider", query="delete from FederatedUserCredentialEntity cred where cred.storageProviderId=:storageProviderId"),
|
||||
@NamedQuery(name="deleteFederatedUserCredentialsByRealmAndLink", query="delete from FederatedUserCredentialEntity cred where cred.userId IN (select u.id from UserEntity u where u.realmId=:realmId and u.federationLink=:link)")
|
||||
|
||||
})
|
||||
@Table(name="FED_USER_CREDENTIAL")
|
||||
@Entity
|
||||
public class FederatedUserCredentialEntity {
|
||||
@Id
|
||||
@Column(name="ID", length = 36)
|
||||
@Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity. This avoids an extra SQL
|
||||
protected String id;
|
||||
|
||||
@Column(name="TYPE")
|
||||
protected String type;
|
||||
@Column(name="VALUE")
|
||||
protected String value;
|
||||
@Column(name="DEVICE")
|
||||
protected String device;
|
||||
@Column(name="SALT")
|
||||
protected byte[] salt;
|
||||
@Column(name="HASH_ITERATIONS")
|
||||
protected int hashIterations;
|
||||
@Column(name="CREATED_DATE")
|
||||
protected Long createdDate;
|
||||
|
||||
@Column(name="USER_ID")
|
||||
protected String userId;
|
||||
|
||||
@Column(name = "REALM_ID")
|
||||
protected String realmId;
|
||||
|
||||
@Column(name = "STORAGE_PROVIDER_ID")
|
||||
protected String storageProviderId;
|
||||
|
||||
|
||||
|
||||
@Column(name="COUNTER")
|
||||
protected int counter;
|
||||
|
||||
@Column(name="ALGORITHM")
|
||||
protected String algorithm;
|
||||
@Column(name="DIGITS")
|
||||
protected int digits;
|
||||
@Column(name="PERIOD")
|
||||
protected int period;
|
||||
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getDevice() {
|
||||
return device;
|
||||
}
|
||||
|
||||
public void setDevice(String device) {
|
||||
this.device = device;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getRealmId() {
|
||||
return realmId;
|
||||
}
|
||||
|
||||
public void setRealmId(String realmId) {
|
||||
this.realmId = realmId;
|
||||
}
|
||||
|
||||
public String getStorageProviderId() {
|
||||
return storageProviderId;
|
||||
}
|
||||
|
||||
public void setStorageProviderId(String storageProviderId) {
|
||||
this.storageProviderId = storageProviderId;
|
||||
}
|
||||
|
||||
public byte[] getSalt() {
|
||||
return salt;
|
||||
}
|
||||
|
||||
public void setSalt(byte[] salt) {
|
||||
this.salt = salt;
|
||||
}
|
||||
|
||||
public int getHashIterations() {
|
||||
return hashIterations;
|
||||
}
|
||||
|
||||
public void setHashIterations(int hashIterations) {
|
||||
this.hashIterations = hashIterations;
|
||||
}
|
||||
|
||||
public Long getCreatedDate() {
|
||||
return createdDate;
|
||||
}
|
||||
|
||||
public void setCreatedDate(Long createdDate) {
|
||||
this.createdDate = createdDate;
|
||||
}
|
||||
|
||||
public int getCounter() {
|
||||
return counter;
|
||||
}
|
||||
|
||||
public void setCounter(int counter) {
|
||||
this.counter = counter;
|
||||
}
|
||||
|
||||
public String getAlgorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
public void setAlgorithm(String algorithm) {
|
||||
this.algorithm = algorithm;
|
||||
}
|
||||
|
||||
public int getDigits() {
|
||||
return digits;
|
||||
}
|
||||
|
||||
public void setDigits(int digits) {
|
||||
this.digits = digits;
|
||||
}
|
||||
|
||||
public int getPeriod() {
|
||||
return period;
|
||||
}
|
||||
|
||||
public void setPeriod(int period) {
|
||||
this.period = period;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null) return false;
|
||||
if (!(o instanceof FederatedUserCredentialEntity)) return false;
|
||||
|
||||
FederatedUserCredentialEntity that = (FederatedUserCredentialEntity) o;
|
||||
|
||||
if (!id.equals(that.getId())) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id.hashCode();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.storage.jpa.entity;
|
||||
|
||||
import org.keycloak.models.jpa.entities.UserEntity;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
@NamedQueries({
|
||||
@NamedQuery(name="feduserMemberOf", query="select m from FederatedUserGroupMembershipEntity m where m.userId = :userId and m.groupId = :groupId"),
|
||||
@NamedQuery(name="feduserGroupMembership", query="select m from FederatedUserGroupMembershipEntity m where m.userId = :userId"),
|
||||
@NamedQuery(name="fedgroupMembership", query="select g.user from FederatedUserGroupMembershipEntity g where g.groupId = :groupId"),
|
||||
@NamedQuery(name="feduserGroupIds", query="select m.groupId from FederatedUserGroupMembershipEntity m where m.userId = :userId"),
|
||||
@NamedQuery(name="deleteFederatedUserGroupMembershipByRealm", query="delete from FederatedUserGroupMembershipEntity mapping where mapping.realmId=:realmId"),
|
||||
@NamedQuery(name="deleteFederatedUserGroupMembershipByStorageProvider", query="delete from FederatedUserGroupMembershipEntity e where e.storageProviderId=:storageProviderId"),
|
||||
@NamedQuery(name="deleteFederatedUserGroupMembershipsByRealmAndLink", query="delete from FederatedUserGroupMembershipEntity mapping where mapping.userId IN (select u.id from UserEntity u where u.realmId=:realmId and u.federationLink=:link)"),
|
||||
@NamedQuery(name="deleteFederatedUserGroupMembershipsByGroup", query="delete from FederatedUserGroupMembershipEntity m where m.groupId = :groupId"),
|
||||
@NamedQuery(name="deleteFederatedUserGroupMembershipsByUser", query="delete from FederatedUserGroupMembershipEntity m where m.userId = :userId and m.realmId = :realmId")
|
||||
|
||||
})
|
||||
@Table(name="FED_USER_GROUP_MEMBERSHIP")
|
||||
@Entity
|
||||
@IdClass(FederatedUserGroupMembershipEntity.Key.class)
|
||||
public class FederatedUserGroupMembershipEntity {
|
||||
|
||||
@Id
|
||||
protected String userId;
|
||||
|
||||
@Id
|
||||
@Column(name = "GROUP_ID")
|
||||
protected String groupId;
|
||||
|
||||
@Column(name = "REALM_ID")
|
||||
protected String realmId;
|
||||
|
||||
@Column(name = "STORAGE_PROVIDER_ID")
|
||||
protected String storageProviderId;
|
||||
|
||||
public String getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
public void setGroupId(String groupId) {
|
||||
this.groupId = groupId;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getRealmId() {
|
||||
return realmId;
|
||||
}
|
||||
|
||||
public void setRealmId(String realmId) {
|
||||
this.realmId = realmId;
|
||||
}
|
||||
|
||||
public String getStorageProviderId() {
|
||||
return storageProviderId;
|
||||
}
|
||||
|
||||
public void setStorageProviderId(String storageProviderId) {
|
||||
this.storageProviderId = storageProviderId;
|
||||
}
|
||||
|
||||
public static class Key implements Serializable {
|
||||
|
||||
protected String userId;
|
||||
|
||||
protected String groupId;
|
||||
|
||||
public Key() {
|
||||
}
|
||||
|
||||
public Key(String userId, String groupId) {
|
||||
this.userId = userId;
|
||||
this.groupId = groupId;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public String getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Key key = (Key) o;
|
||||
|
||||
if (!groupId.equals(key.groupId)) return false;
|
||||
if (!userId.equals(key.userId)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = userId.hashCode();
|
||||
result = 31 * result + groupId.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null) return false;
|
||||
if (!(o instanceof FederatedUserGroupMembershipEntity)) return false;
|
||||
|
||||
FederatedUserGroupMembershipEntity key = (FederatedUserGroupMembershipEntity) o;
|
||||
|
||||
if (!groupId.equals(key.groupId)) return false;
|
||||
if (!userId.equals(key.userId)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = userId.hashCode();
|
||||
result = 31 * result + groupId.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.storage.jpa.entity;
|
||||
|
||||
import org.keycloak.models.jpa.entities.UserEntity;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
@NamedQueries({
|
||||
@NamedQuery(name="getFederatedUserRequiredActionsByUser", query="select action from FederatedUserRequiredActionEntity action where action.userId = :userId and attr.realmId=:realmId"),
|
||||
@NamedQuery(name="deleteFederatedUserRequiredActionsByRealm", query="delete from FederatedUserRequiredActionEntity action where action.realmId=:realmId"),
|
||||
@NamedQuery(name="deleteFederatedUserRequiredActionsByStorageProvider", query="delete from FederatedUserRequiredActionEntity e where e.storageProviderId=:storageProviderId"),
|
||||
@NamedQuery(name="deleteFederatedUserRequiredActionsByRealmAndLink", query="delete from FederatedUserRequiredActionEntity action where action.userId IN (select u.id from UserEntity u where u.realmId=:realmId and u.federationLink=:link)")
|
||||
})
|
||||
@Entity
|
||||
@Table(name="FED_USER_REQUIRED_ACTION")
|
||||
@IdClass(FederatedUserRequiredActionEntity.Key.class)
|
||||
public class FederatedUserRequiredActionEntity {
|
||||
|
||||
@Id
|
||||
@Column(name="USER_ID")
|
||||
protected String userId;
|
||||
|
||||
@Id
|
||||
@Column(name="REQUIRED_ACTION")
|
||||
protected String action;
|
||||
|
||||
@Column(name = "REALM_ID")
|
||||
protected String realmId;
|
||||
|
||||
@Column(name = "STORAGE_PROVIDER_ID")
|
||||
protected String storageProviderId;
|
||||
|
||||
public String getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public void setAction(String action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getRealmId() {
|
||||
return realmId;
|
||||
}
|
||||
|
||||
public void setRealmId(String realmId) {
|
||||
this.realmId = realmId;
|
||||
}
|
||||
|
||||
public String getStorageProviderId() {
|
||||
return storageProviderId;
|
||||
}
|
||||
|
||||
public void setStorageProviderId(String storageProviderId) {
|
||||
this.storageProviderId = storageProviderId;
|
||||
}
|
||||
|
||||
public static class Key implements Serializable {
|
||||
|
||||
protected String userId;
|
||||
|
||||
protected String action;
|
||||
|
||||
public Key() {
|
||||
}
|
||||
|
||||
public Key(String user, String action) {
|
||||
this.userId = user;
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public String getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Key key = (Key) o;
|
||||
|
||||
if (action != key.action) return false;
|
||||
if (userId != null ? !userId.equals(key.userId != null ? key.userId : null) : key.userId != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = userId != null ? userId.hashCode() : 0;
|
||||
result = 31 * result + (action != null ? action.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null) return false;
|
||||
if (!(o instanceof FederatedUserRequiredActionEntity)) return false;
|
||||
|
||||
FederatedUserRequiredActionEntity key = (FederatedUserRequiredActionEntity) o;
|
||||
|
||||
if (action != key.action) return false;
|
||||
if (userId != null ? !userId.equals(key.userId != null ? key.userId : null) : key.userId != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = userId != null ? userId.hashCode() : 0;
|
||||
result = 31 * result + (action != null ? action.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.storage.jpa.entity;
|
||||
|
||||
import org.keycloak.models.jpa.entities.UserEntity;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
@NamedQueries({
|
||||
@NamedQuery(name="feduserHasRole", query="select m from FederatedUserRoleMappingEntity m where m.userId = :userId and m.roleId = :roleId"),
|
||||
@NamedQuery(name="feduserRoleMappings", query="select m from FederatedUserRoleMappingEntity m where m.userId = :userId"),
|
||||
@NamedQuery(name="deleteFederatedUserRoleMappingsByRealm", query="delete from FederatedUserRoleMappingEntity mapping where mapping.realmId=:realmId"),
|
||||
@NamedQuery(name="deleteFederatedUserRoleMappingsByStorageProvider", query="delete from FederatedUserRoleMappingEntity e where e.storageProviderId=:storageProviderId"),
|
||||
@NamedQuery(name="deleteFederatedUserRoleMappingsByRealmAndLink", query="delete from FederatedUserRoleMappingEntity mapping where mapping.userId IN (select u.id from UserEntity u where u.realmId=:realmId and u.federationLink=:link)"),
|
||||
@NamedQuery(name="deleteFederatedUserRoleMappingsByRole", query="delete from FederatedUserRoleMappingEntity m where m.roleId = :roleId"),
|
||||
@NamedQuery(name="deleteFederatedUserRoleMappingsByUser", query="delete from FederatedUserRoleMappingEntity m where m.userId = :userId and m.realmId = :realmId"),
|
||||
|
||||
})
|
||||
@Table(name="FED_USER_ROLE_MAPPING")
|
||||
@Entity
|
||||
@IdClass(FederatedUserRoleMappingEntity.Key.class)
|
||||
public class FederatedUserRoleMappingEntity {
|
||||
|
||||
@Id
|
||||
protected String userId;
|
||||
|
||||
@Id
|
||||
@Column(name = "ROLE_ID")
|
||||
protected String roleId;
|
||||
|
||||
@Column(name = "REALM_ID")
|
||||
protected String realmId;
|
||||
|
||||
@Column(name = "STORAGE_PROVIDER_ID")
|
||||
protected String storageProviderId;
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getRealmId() {
|
||||
return realmId;
|
||||
}
|
||||
|
||||
public void setRealmId(String realmId) {
|
||||
this.realmId = realmId;
|
||||
}
|
||||
|
||||
public String getStorageProviderId() {
|
||||
return storageProviderId;
|
||||
}
|
||||
|
||||
public void setStorageProviderId(String storageProviderId) {
|
||||
this.storageProviderId = storageProviderId;
|
||||
}
|
||||
|
||||
public String getRoleId() {
|
||||
return roleId;
|
||||
}
|
||||
|
||||
public void setRoleId(String roleId) {
|
||||
this.roleId = roleId;
|
||||
}
|
||||
|
||||
|
||||
public static class Key implements Serializable {
|
||||
|
||||
protected String userId;
|
||||
|
||||
protected String roleId;
|
||||
|
||||
public Key() {
|
||||
}
|
||||
|
||||
public Key(String userId, String roleId) {
|
||||
this.userId = userId;
|
||||
this.roleId = roleId;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public String getRoleId() {
|
||||
return roleId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Key key = (Key) o;
|
||||
|
||||
if (!roleId.equals(key.roleId)) return false;
|
||||
if (!userId.equals(key.userId)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = userId.hashCode();
|
||||
result = 31 * result + roleId.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null) return false;
|
||||
if (!(o instanceof FederatedUserRoleMappingEntity)) return false;
|
||||
|
||||
FederatedUserRoleMappingEntity key = (FederatedUserRoleMappingEntity) o;
|
||||
|
||||
if (!roleId.equals(key.roleId)) return false;
|
||||
if (!userId.equals(key.userId)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = userId.hashCode();
|
||||
result = 31 * result + roleId.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -28,22 +28,28 @@ import org.keycloak.models.CredentialValidationOutput;
|
|||
import org.keycloak.models.FederatedIdentityModel;
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ModelDuplicateException;
|
||||
import org.keycloak.models.ModelException;
|
||||
import org.keycloak.models.ProtocolMapperModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RequiredActionProviderModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserConsentModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserProvider;
|
||||
import org.keycloak.models.entities.FederatedIdentityEntity;
|
||||
import org.keycloak.models.entities.UserConsentEntity;
|
||||
import org.keycloak.models.mongo.keycloak.entities.MongoUserConsentEntity;
|
||||
import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity;
|
||||
import org.keycloak.models.utils.CredentialValidation;
|
||||
import org.keycloak.storage.StorageProviderModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -140,7 +146,7 @@ public class MongoUserProvider implements UserProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserByServiceAccountClient(ClientModel client) {
|
||||
public UserModel getServiceAccount(ClientModel client) {
|
||||
DBObject query = new QueryBuilder()
|
||||
.and("serviceAccountClientLink").is(client.getId())
|
||||
.and("realmId").is(client.getRealm().getId())
|
||||
|
@ -157,6 +163,17 @@ public class MongoUserProvider implements UserProvider {
|
|||
return userModels;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getUsers(RealmModel realm) {
|
||||
return getUsers(realm, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
|
||||
return getUsers(realm, firstResult, maxResults, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public List<UserModel> getUsers(RealmModel realm, boolean includeServiceAccounts) {
|
||||
|
@ -509,4 +526,112 @@ public class MongoUserProvider implements UserProvider {
|
|||
// Not supported yet
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
|
||||
String clientId = consent.getClient().getId();
|
||||
if (getConsentEntityByClientId(user, clientId) != null) {
|
||||
throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + user.getId() + "]");
|
||||
}
|
||||
|
||||
MongoUserConsentEntity consentEntity = new MongoUserConsentEntity();
|
||||
consentEntity.setUserId(user.getId());
|
||||
consentEntity.setClientId(clientId);
|
||||
fillEntityFromModel(consent, consentEntity);
|
||||
getMongoStore().insertEntity(consentEntity, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserConsentModel getConsentByClient(RealmModel realm, UserModel user, String clientId) {
|
||||
UserConsentEntity consentEntity = getConsentEntityByClientId(user, clientId);
|
||||
return consentEntity!=null ? toConsentModel(realm, consentEntity) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserConsentModel> getConsents(RealmModel realm, UserModel user) {
|
||||
List<UserConsentModel> result = new ArrayList<UserConsentModel>();
|
||||
|
||||
DBObject query = new QueryBuilder()
|
||||
.and("userId").is(user.getId())
|
||||
.get();
|
||||
List<MongoUserConsentEntity> grantedConsents = getMongoStore().loadEntities(MongoUserConsentEntity.class, query, invocationContext);
|
||||
|
||||
for (UserConsentEntity consentEntity : grantedConsents) {
|
||||
UserConsentModel model = toConsentModel(realm, consentEntity);
|
||||
result.add(model);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private MongoUserConsentEntity getConsentEntityByClientId(UserModel user, String clientId) {
|
||||
DBObject query = new QueryBuilder()
|
||||
.and("userId").is(user.getId())
|
||||
.and("clientId").is(clientId)
|
||||
.get();
|
||||
return getMongoStore().loadSingleEntity(MongoUserConsentEntity.class, query, invocationContext);
|
||||
}
|
||||
|
||||
private UserConsentModel toConsentModel(RealmModel realm, UserConsentEntity entity) {
|
||||
ClientModel client = realm.getClientById(entity.getClientId());
|
||||
if (client == null) {
|
||||
throw new ModelException("Client with id " + entity.getClientId() + " is not available");
|
||||
}
|
||||
UserConsentModel model = new UserConsentModel(client);
|
||||
|
||||
for (String roleId : entity.getGrantedRoles()) {
|
||||
RoleModel roleModel = realm.getRoleById(roleId);
|
||||
if (roleModel != null) {
|
||||
model.addGrantedRole(roleModel);
|
||||
}
|
||||
}
|
||||
|
||||
for (String protMapperId : entity.getGrantedProtocolMappers()) {
|
||||
ProtocolMapperModel protocolMapper = client.getProtocolMapperById(protMapperId);
|
||||
model.addGrantedProtocolMapper(protocolMapper);
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
// Fill roles and protocolMappers to entity
|
||||
private void fillEntityFromModel(UserConsentModel consent, MongoUserConsentEntity consentEntity) {
|
||||
List<String> roleIds = new LinkedList<String>();
|
||||
for (RoleModel role : consent.getGrantedRoles()) {
|
||||
roleIds.add(role.getId());
|
||||
}
|
||||
consentEntity.setGrantedRoles(roleIds);
|
||||
|
||||
List<String> protMapperIds = new LinkedList<String>();
|
||||
for (ProtocolMapperModel protMapperModel : consent.getGrantedProtocolMappers()) {
|
||||
protMapperIds.add(protMapperModel.getId());
|
||||
}
|
||||
consentEntity.setGrantedProtocolMappers(protMapperIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
|
||||
String clientId = consent.getClient().getId();
|
||||
MongoUserConsentEntity consentEntity = getConsentEntityByClientId(user, clientId);
|
||||
if (consentEntity == null) {
|
||||
throw new ModelException("Consent not found for client [" + clientId + "] and user [" + user.getId() + "]");
|
||||
} else {
|
||||
fillEntityFromModel(consent, consentEntity);
|
||||
getMongoStore().updateEntity(consentEntity, invocationContext);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean revokeConsentForClient(RealmModel realm, UserModel user, String clientId) {
|
||||
MongoUserConsentEntity entity = getConsentEntityByClientId(user, clientId);
|
||||
if (entity == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return getMongoStore().removeEntity(entity, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, StorageProviderModel link) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ import org.keycloak.models.entities.IdentityProviderEntity;
|
|||
import org.keycloak.models.entities.IdentityProviderMapperEntity;
|
||||
import org.keycloak.models.entities.RequiredActionProviderEntity;
|
||||
import org.keycloak.models.entities.RequiredCredentialEntity;
|
||||
import org.keycloak.models.entities.StorageProviderEntity;
|
||||
import org.keycloak.models.entities.UserFederationMapperEntity;
|
||||
import org.keycloak.models.entities.UserFederationProviderEntity;
|
||||
import org.keycloak.models.mongo.keycloak.entities.MongoClientEntity;
|
||||
|
@ -58,6 +59,7 @@ import org.keycloak.models.mongo.keycloak.entities.MongoGroupEntity;
|
|||
import org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity;
|
||||
import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.storage.StorageProviderModel;
|
||||
|
||||
import java.security.Key;
|
||||
import java.security.PrivateKey;
|
||||
|
@ -984,6 +986,14 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
|||
updateRealm();
|
||||
}
|
||||
|
||||
|
||||
private void removeFederationMappersForProvider(String federationProviderId) {
|
||||
Set<UserFederationMapperEntity> mappers = getUserFederationMapperEntitiesByFederationProvider(federationProviderId);
|
||||
for (UserFederationMapperEntity mapper : mappers) {
|
||||
getMongoEntity().getUserFederationMappers().remove(mapper);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserFederationProviderModel addUserFederationProvider(String providerName, Map<String, String> config, int priority, String displayName, int fullSyncPeriod, int changedSyncPeriod, int lastSync) {
|
||||
KeycloakModelUtils.ensureUniqueDisplayName(displayName, null, getUserFederationProviders());
|
||||
|
@ -1025,14 +1035,6 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
|||
}
|
||||
updateRealm();
|
||||
}
|
||||
|
||||
private void removeFederationMappersForProvider(String federationProviderId) {
|
||||
Set<UserFederationMapperEntity> mappers = getUserFederationMapperEntitiesByFederationProvider(federationProviderId);
|
||||
for (UserFederationMapperEntity mapper : mappers) {
|
||||
getMongoEntity().getUserFederationMappers().remove(mapper);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateUserFederationProvider(UserFederationProviderModel model) {
|
||||
KeycloakModelUtils.ensureUniqueDisplayName(model.getDisplayName(), model, getUserFederationProviders());
|
||||
|
@ -1161,6 +1163,173 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
|||
updateRealm();
|
||||
}
|
||||
|
||||
@Override
|
||||
public StorageProviderModel addStorageProvider(StorageProviderModel model) {
|
||||
KeycloakModelUtils.ensureUniqueDisplayName(model.getDisplayName(), null, getStorageProviders());
|
||||
|
||||
StorageProviderEntity entity = new StorageProviderEntity();
|
||||
entity.setId(KeycloakModelUtils.generateId());
|
||||
entity.setPriority(model.getPriority());
|
||||
entity.setProviderName(model.getProviderName());
|
||||
entity.setConfig(model.getConfig());
|
||||
String displayName = model.getDisplayName();
|
||||
if (displayName == null) {
|
||||
displayName = entity.getId();
|
||||
}
|
||||
entity.setDisplayName(displayName);
|
||||
realm.getStorageProviders().add(entity);
|
||||
updateRealm();
|
||||
|
||||
StorageProviderModel providerModel = new StorageProviderModel(entity.getId(), model.getProviderName(),
|
||||
model.getConfig(), model.getPriority(), displayName);
|
||||
|
||||
|
||||
return providerModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStorageProvider(StorageProviderModel provider) {
|
||||
KeycloakModelUtils.ensureUniqueDisplayName(provider.getDisplayName(), provider, getStorageProviders());
|
||||
|
||||
Iterator<StorageProviderEntity> it = realm.getStorageProviders().iterator();
|
||||
while (it.hasNext()) {
|
||||
StorageProviderEntity entity = it.next();
|
||||
if (entity.getId().equals(provider.getId())) {
|
||||
entity.setProviderName(provider.getProviderName());
|
||||
entity.setConfig(provider.getConfig());
|
||||
entity.setPriority(provider.getPriority());
|
||||
String displayName = provider.getDisplayName();
|
||||
if (displayName != null) {
|
||||
entity.setDisplayName(provider.getDisplayName());
|
||||
}
|
||||
}
|
||||
}
|
||||
updateRealm();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeStorageProvider(StorageProviderModel provider) {
|
||||
Iterator<StorageProviderEntity> it = realm.getStorageProviders().iterator();
|
||||
while (it.hasNext()) {
|
||||
StorageProviderEntity entity = it.next();
|
||||
if (entity.getId().equals(provider.getId())) {
|
||||
session.users().preRemove(this, new StorageProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName()
|
||||
));
|
||||
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
updateRealm();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStorageProviders(List<StorageProviderModel> providers) {
|
||||
for (StorageProviderModel currentProvider : providers) {
|
||||
KeycloakModelUtils.ensureUniqueDisplayName(currentProvider.getDisplayName(), currentProvider, providers);
|
||||
}
|
||||
|
||||
List<StorageProviderEntity> existingProviders = realm.getStorageProviders();
|
||||
List<StorageProviderEntity> toRemove = new LinkedList<>();
|
||||
for (StorageProviderEntity entity : existingProviders) {
|
||||
boolean found = false;
|
||||
for (StorageProviderModel model : providers) {
|
||||
if (entity.getId().equals(model.getId())) {
|
||||
entity.setConfig(model.getConfig());
|
||||
entity.setPriority(model.getPriority());
|
||||
entity.setProviderName(model.getProviderName());
|
||||
String displayName = model.getDisplayName();
|
||||
if (displayName != null) {
|
||||
entity.setDisplayName(displayName);
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
if (found) continue;
|
||||
session.users().preRemove(this, new StorageProviderModel(entity.getId(), entity.getProviderName(),
|
||||
entity.getConfig(), entity.getPriority(), entity.getDisplayName()));
|
||||
toRemove.add(entity);
|
||||
}
|
||||
|
||||
for (StorageProviderEntity entity : toRemove) {
|
||||
realm.getStorageProviders().remove(entity);
|
||||
}
|
||||
|
||||
List<StorageProviderModel> add = new LinkedList<>();
|
||||
for (StorageProviderModel model : providers) {
|
||||
boolean found = false;
|
||||
for (StorageProviderEntity entity : realm.getStorageProviders()) {
|
||||
if (entity.getId().equals(model.getId())) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) add.add(model);
|
||||
}
|
||||
|
||||
for (StorageProviderModel model : add) {
|
||||
StorageProviderEntity entity = new StorageProviderEntity();
|
||||
if (model.getId() != null) {
|
||||
entity.setId(model.getId());
|
||||
} else {
|
||||
String id = KeycloakModelUtils.generateId();
|
||||
entity.setId(id);
|
||||
model.setId(id);
|
||||
}
|
||||
entity.setProviderName(model.getProviderName());
|
||||
entity.setConfig(model.getConfig());
|
||||
entity.setPriority(model.getPriority());
|
||||
String displayName = model.getDisplayName();
|
||||
if (displayName == null) {
|
||||
displayName = entity.getId();
|
||||
}
|
||||
entity.setDisplayName(displayName);
|
||||
realm.getStorageProviders().add(entity);
|
||||
|
||||
}
|
||||
|
||||
updateRealm();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StorageProviderModel> getStorageProviders() {
|
||||
List<StorageProviderEntity> entities = realm.getStorageProviders();
|
||||
if (entities.isEmpty()) return Collections.EMPTY_LIST;
|
||||
List<StorageProviderEntity> copy = new LinkedList<>();
|
||||
for (StorageProviderEntity entity : entities) {
|
||||
copy.add(entity);
|
||||
|
||||
}
|
||||
Collections.sort(copy, new Comparator<StorageProviderEntity>() {
|
||||
|
||||
@Override
|
||||
public int compare(StorageProviderEntity o1, StorageProviderEntity o2) {
|
||||
return o1.getPriority() - o2.getPriority();
|
||||
}
|
||||
|
||||
});
|
||||
List<StorageProviderModel> result = new LinkedList<>();
|
||||
for (StorageProviderEntity entity : copy) {
|
||||
result.add(new StorageProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName()
|
||||
));
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StorageProviderModel getStorageProvider(String id) {
|
||||
for (StorageProviderEntity entity : realm.getStorageProviders()) {
|
||||
if (entity.getId().equals(id)) return new StorageProviderModel(entity.getId(), entity.getProviderName(),
|
||||
entity.getConfig(), entity.getPriority(), entity.getDisplayName());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEventsEnabled() {
|
||||
return realm.isEventsEnabled();
|
||||
|
|
|
@ -566,108 +566,6 @@ public class UserAdapter extends AbstractMongoAdapter<MongoUserEntity> implement
|
|||
updateUser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addConsent(UserConsentModel consent) {
|
||||
String clientId = consent.getClient().getId();
|
||||
if (getConsentEntityByClientId(clientId) != null) {
|
||||
throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + user.getId() + "]");
|
||||
}
|
||||
|
||||
MongoUserConsentEntity consentEntity = new MongoUserConsentEntity();
|
||||
consentEntity.setUserId(getId());
|
||||
consentEntity.setClientId(clientId);
|
||||
fillEntityFromModel(consent, consentEntity);
|
||||
getMongoStore().insertEntity(consentEntity, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserConsentModel getConsentByClient(String clientId) {
|
||||
UserConsentEntity consentEntity = getConsentEntityByClientId(clientId);
|
||||
return consentEntity!=null ? toConsentModel(consentEntity) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserConsentModel> getConsents() {
|
||||
List<UserConsentModel> result = new ArrayList<UserConsentModel>();
|
||||
|
||||
DBObject query = new QueryBuilder()
|
||||
.and("userId").is(getId())
|
||||
.get();
|
||||
List<MongoUserConsentEntity> grantedConsents = getMongoStore().loadEntities(MongoUserConsentEntity.class, query, invocationContext);
|
||||
|
||||
for (UserConsentEntity consentEntity : grantedConsents) {
|
||||
UserConsentModel model = toConsentModel(consentEntity);
|
||||
result.add(model);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private MongoUserConsentEntity getConsentEntityByClientId(String clientId) {
|
||||
DBObject query = new QueryBuilder()
|
||||
.and("userId").is(getId())
|
||||
.and("clientId").is(clientId)
|
||||
.get();
|
||||
return getMongoStore().loadSingleEntity(MongoUserConsentEntity.class, query, invocationContext);
|
||||
}
|
||||
|
||||
private UserConsentModel toConsentModel(UserConsentEntity entity) {
|
||||
ClientModel client = realm.getClientById(entity.getClientId());
|
||||
if (client == null) {
|
||||
throw new ModelException("Client with id " + entity.getClientId() + " is not available");
|
||||
}
|
||||
UserConsentModel model = new UserConsentModel(client);
|
||||
|
||||
for (String roleId : entity.getGrantedRoles()) {
|
||||
RoleModel roleModel = realm.getRoleById(roleId);
|
||||
if (roleModel != null) {
|
||||
model.addGrantedRole(roleModel);
|
||||
}
|
||||
}
|
||||
|
||||
for (String protMapperId : entity.getGrantedProtocolMappers()) {
|
||||
ProtocolMapperModel protocolMapper = client.getProtocolMapperById(protMapperId);
|
||||
model.addGrantedProtocolMapper(protocolMapper);
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
// Fill roles and protocolMappers to entity
|
||||
private void fillEntityFromModel(UserConsentModel consent, MongoUserConsentEntity consentEntity) {
|
||||
List<String> roleIds = new LinkedList<String>();
|
||||
for (RoleModel role : consent.getGrantedRoles()) {
|
||||
roleIds.add(role.getId());
|
||||
}
|
||||
consentEntity.setGrantedRoles(roleIds);
|
||||
|
||||
List<String> protMapperIds = new LinkedList<String>();
|
||||
for (ProtocolMapperModel protMapperModel : consent.getGrantedProtocolMappers()) {
|
||||
protMapperIds.add(protMapperModel.getId());
|
||||
}
|
||||
consentEntity.setGrantedProtocolMappers(protMapperIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateConsent(UserConsentModel consent) {
|
||||
String clientId = consent.getClient().getId();
|
||||
MongoUserConsentEntity consentEntity = getConsentEntityByClientId(clientId);
|
||||
if (consentEntity == null) {
|
||||
throw new ModelException("Consent not found for client [" + clientId + "] and user [" + user.getId() + "]");
|
||||
} else {
|
||||
fillEntityFromModel(consent, consentEntity);
|
||||
getMongoStore().updateEntity(consentEntity, invocationContext);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean revokeConsentForClient(String clientId) {
|
||||
MongoUserConsentEntity entity = getConsentEntityByClientId(clientId);
|
||||
if (entity == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return getMongoStore().removeEntity(entity, invocationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
|
|
|
@ -34,8 +34,8 @@ import org.keycloak.provider.Provider;
|
|||
public interface UserFederationMapper extends Provider {
|
||||
|
||||
/**
|
||||
* Sync data from federation storage to Keycloak. It's useful just if mapper needs some data preloaded from federation storage (For example
|
||||
* load roles from federation provider and sync them to Keycloak database)
|
||||
* Sync data from federated storage to Keycloak. It's useful just if mapper needs some data preloaded from federated storage (For example
|
||||
* load roles from federated provider and sync them to Keycloak database)
|
||||
*
|
||||
* Applicable just if sync is supported (see UserFederationMapperFactory.getSyncConfig() )
|
||||
*
|
||||
|
@ -48,7 +48,7 @@ public interface UserFederationMapper extends Provider {
|
|||
UserFederationSyncResult syncDataFromFederationProviderToKeycloak(UserFederationMapperModel mapperModel, UserFederationProvider federationProvider, KeycloakSession session, RealmModel realm);
|
||||
|
||||
/**
|
||||
* Sync data from Keycloak back to federation storage
|
||||
* Sync data from Keycloak back to federated storage
|
||||
*
|
||||
* @see UserFederationMapperFactory#getSyncConfig()
|
||||
* @param mapperModel
|
||||
|
|
|
@ -32,7 +32,7 @@ import org.keycloak.representations.idm.UserFederationMapperSyncConfigRepresenta
|
|||
public interface UserFederationMapperFactory extends ProviderFactory<UserFederationMapper>, ConfiguredProvider {
|
||||
|
||||
/**
|
||||
* Refers to providerName (type) of the federation provider, which this mapper can be used for. For example "ldap" or "kerberos"
|
||||
* Refers to providerName (type) of the federated provider, which this mapper can be used for. For example "ldap" or "kerberos"
|
||||
*
|
||||
* @return providerName
|
||||
*/
|
||||
|
@ -42,7 +42,7 @@ public interface UserFederationMapperFactory extends ProviderFactory<UserFederat
|
|||
String getDisplayType();
|
||||
|
||||
/**
|
||||
* Specifies if mapper supports sync data from federation storage to keycloak and viceversa.
|
||||
* Specifies if mapper supports sync data from federated storage to keycloak and viceversa.
|
||||
* Also specifies messages to be displayed in admin console UI (For example "Sync roles from LDAP" etc)
|
||||
*
|
||||
* @return syncConfig representation
|
||||
|
|
|
@ -56,7 +56,7 @@ public class MigrateTo1_3_0 {
|
|||
if (fedProvider.getProviderName().equals(LDAPConstants.LDAP_PROVIDER)) {
|
||||
Map<String, String> config = fedProvider.getConfig();
|
||||
|
||||
// Update config properties for LDAP federation provider
|
||||
// Update config properties for LDAP federated provider
|
||||
if (config.get(LDAPConstants.SEARCH_SCOPE) == null) {
|
||||
config.put(LDAPConstants.SEARCH_SCOPE, String.valueOf(SearchControls.SUBTREE_SCOPE));
|
||||
}
|
||||
|
|
|
@ -57,4 +57,25 @@ public class FederatedIdentityModel {
|
|||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
FederatedIdentityModel that = (FederatedIdentityModel) o;
|
||||
|
||||
if (userId != null ? !userId.equals(that.userId) : that.userId != null) return false;
|
||||
if (!identityProvider.equals(that.identityProvider)) return false;
|
||||
return userName != null ? userName.equals(that.userName) : that.userName == null;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = userId != null ? userId.hashCode() : 0;
|
||||
result = 31 * result + identityProvider.hashCode();
|
||||
result = 31 * result + (userName != null ? userName.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ package org.keycloak.models;
|
|||
|
||||
import org.keycloak.provider.Provider;
|
||||
import org.keycloak.scripting.ScriptingProvider;
|
||||
import org.keycloak.storage.federated.UserFederatedStorageProvider;
|
||||
import org.keycloak.storage.federated.UserFederatedStorageProviderFactory;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -73,11 +75,16 @@ public interface KeycloakSession {
|
|||
*/
|
||||
UserFederationManager users();
|
||||
|
||||
UserProvider userStorageManager();
|
||||
|
||||
/**
|
||||
* Keycloak user storage. Non-federated, but possibly cache (if it is on) view of users.
|
||||
*/
|
||||
UserProvider userStorage();
|
||||
|
||||
UserFederatedStorageProvider userFederatedStorage();
|
||||
UserProvider userLocalStorage();
|
||||
|
||||
/**
|
||||
* Keycloak scripting support.
|
||||
*/
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.keycloak.models;
|
|||
|
||||
import org.keycloak.common.enums.SslRequired;
|
||||
import org.keycloak.provider.ProviderEvent;
|
||||
import org.keycloak.storage.StorageProviderModel;
|
||||
|
||||
import java.security.Key;
|
||||
import java.security.PrivateKey;
|
||||
|
@ -263,9 +264,16 @@ public interface RealmModel extends RoleContainerModel {
|
|||
public IdentityProviderMapperModel getIdentityProviderMapperById(String id);
|
||||
public IdentityProviderMapperModel getIdentityProviderMapperByName(String brokerAlias, String name);
|
||||
|
||||
|
||||
StorageProviderModel addStorageProvider(StorageProviderModel model);
|
||||
void updateStorageProvider(StorageProviderModel provider);
|
||||
void removeStorageProvider(StorageProviderModel provider);
|
||||
void setStorageProviders(List<StorageProviderModel> providers);
|
||||
List<StorageProviderModel> getStorageProviders();
|
||||
StorageProviderModel getStorageProvider(String id);
|
||||
|
||||
// Should return list sorted by UserFederationProviderModel.priority
|
||||
List<UserFederationProviderModel> getUserFederationProviders();
|
||||
|
||||
UserFederationProviderModel addUserFederationProvider(String providerName, Map<String, String> config, int priority, String displayName, int fullSyncPeriod, int changedSyncPeriod, int lastSync);
|
||||
void updateUserFederationProvider(UserFederationProviderModel provider);
|
||||
void removeUserFederationProvider(UserFederationProviderModel provider);
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.models;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserCredentialAuthenticationProvider {
|
||||
Set<String> getSupportedCredentialAuthenticationTypes();
|
||||
CredentialValidationOutput validCredential(KeycloakSession session, RealmModel realm, UserCredentialModel input);
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.models;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserCredentialValidatorProvider {
|
||||
boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, List<UserCredentialModel> input);
|
||||
}
|
|
@ -25,7 +25,7 @@ import java.io.Serializable;
|
|||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class UserCredentialValueModel implements Serializable {
|
||||
|
||||
private String id;
|
||||
private String type;
|
||||
private String value;
|
||||
private String device;
|
||||
|
@ -40,6 +40,14 @@ public class UserCredentialValueModel implements Serializable {
|
|||
private int period;
|
||||
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.keycloak.models;
|
|||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.services.managers.UserManager;
|
||||
import org.keycloak.storage.StorageProviderModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -174,6 +175,38 @@ public class UserFederationManager implements UserProvider {
|
|||
return session.userStorage().removeFederatedIdentity(realm, user, socialProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
|
||||
validateUser(realm, user);
|
||||
session.userStorage().addConsent(realm, user, consent);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserConsentModel getConsentByClient(RealmModel realm, UserModel user, String clientInternalId) {
|
||||
validateUser(realm, user);
|
||||
return session.userStorage().getConsentByClient(realm, user, clientInternalId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserConsentModel> getConsents(RealmModel realm, UserModel user) {
|
||||
validateUser(realm, user);
|
||||
return session.userStorage().getConsents(realm, user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
|
||||
validateUser(realm, user);
|
||||
session.userStorage().updateConsent(realm, user, consent);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean revokeConsentForClient(RealmModel realm, UserModel user, String clientInternalId) {
|
||||
validateUser(realm, user);
|
||||
return session.userStorage().revokeConsentForClient(realm, user, clientInternalId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserById(String id, RealmModel realm) {
|
||||
UserModel user = session.userStorage().getUserById(id, realm);
|
||||
|
@ -265,8 +298,8 @@ public class UserFederationManager implements UserProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserByServiceAccountClient(ClientModel client) {
|
||||
UserModel user = session.userStorage().getUserByServiceAccountClient(client);
|
||||
public UserModel getServiceAccount(ClientModel client) {
|
||||
UserModel user = session.userStorage().getServiceAccount(client);
|
||||
if (user != null) {
|
||||
user = validateAndProxyUser(client.getRealm(), user);
|
||||
}
|
||||
|
@ -279,6 +312,16 @@ public class UserFederationManager implements UserProvider {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getUsers(RealmModel realm) {
|
||||
return getUsers(realm, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
|
||||
return getUsers(realm, firstResult, maxResults, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUsersCount(RealmModel realm) {
|
||||
return session.userStorage().getUsersCount(realm);
|
||||
|
@ -442,6 +485,11 @@ public class UserFederationManager implements UserProvider {
|
|||
session.userStorage().preRemove(protocolMapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, StorageProviderModel link) {
|
||||
|
||||
}
|
||||
|
||||
public void updateCredential(RealmModel realm, UserModel user, UserCredentialModel credential) {
|
||||
if (credential.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
if (realm.getPasswordPolicy() != null) {
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.models;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserLookupProvider {
|
||||
UserModel getUserById(String id, RealmModel realm);
|
||||
|
||||
UserModel getUserByUsername(String username, RealmModel realm);
|
||||
|
||||
UserModel getUserByEmail(String email, RealmModel realm);
|
||||
}
|
|
@ -122,12 +122,6 @@ public interface UserModel extends RoleMapperModel {
|
|||
String getServiceAccountClientLink();
|
||||
void setServiceAccountClientLink(String clientInternalId);
|
||||
|
||||
void addConsent(UserConsentModel consent);
|
||||
UserConsentModel getConsentByClient(String clientInternalId);
|
||||
List<UserConsentModel> getConsents();
|
||||
void updateConsent(UserConsentModel consent);
|
||||
boolean revokeConsentForClient(String clientInternalId);
|
||||
|
||||
public static enum RequiredAction {
|
||||
VERIFY_EMAIL, UPDATE_PROFILE, CONFIGURE_TOTP, UPDATE_PASSWORD
|
||||
}
|
||||
|
|
|
@ -18,56 +18,44 @@
|
|||
package org.keycloak.models;
|
||||
|
||||
import org.keycloak.provider.Provider;
|
||||
import org.keycloak.storage.StorageProviderModel;
|
||||
|
||||
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 interface UserProvider extends Provider {
|
||||
public interface UserProvider extends Provider, UserLookupProvider, UserQueryProvider, UserCredentialValidatorProvider, UserUpdateProvider {
|
||||
// Note: The reason there are so many query methods here is for layering a cache on top of an persistent KeycloakSession
|
||||
|
||||
UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions);
|
||||
UserModel addUser(RealmModel realm, String username);
|
||||
boolean removeUser(RealmModel realm, UserModel user);
|
||||
|
||||
public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel socialLink);
|
||||
public boolean removeFederatedIdentity(RealmModel realm, UserModel user, String socialProvider);
|
||||
void updateFederatedIdentity(RealmModel realm, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel);
|
||||
|
||||
UserModel getUserById(String id, RealmModel realm);
|
||||
UserModel getUserByUsername(String username, RealmModel realm);
|
||||
UserModel getUserByEmail(String email, RealmModel realm);
|
||||
|
||||
List<UserModel> getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults);
|
||||
|
||||
Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm);
|
||||
FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm);
|
||||
UserModel getUserByFederatedIdentity(FederatedIdentityModel socialLink, RealmModel realm);
|
||||
UserModel getUserByServiceAccountClient(ClientModel client);
|
||||
List<UserModel> getUsers(RealmModel realm, boolean includeServiceAccounts);
|
||||
|
||||
// Service account is included for counts
|
||||
int getUsersCount(RealmModel realm);
|
||||
List<UserModel> getGroupMembers(RealmModel realm, GroupModel group);
|
||||
void addConsent(RealmModel realm, UserModel user, UserConsentModel consent);
|
||||
UserConsentModel getConsentByClient(RealmModel realm, UserModel user, String clientInternalId);
|
||||
List<UserConsentModel> getConsents(RealmModel realm, UserModel user);
|
||||
void updateConsent(RealmModel realm, UserModel user, UserConsentModel consent);
|
||||
boolean revokeConsentForClient(RealmModel realm, UserModel user, String clientInternalId);
|
||||
|
||||
|
||||
UserModel getServiceAccount(ClientModel client);
|
||||
List<UserModel> getUsers(RealmModel realm, boolean includeServiceAccounts);
|
||||
List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults, boolean includeServiceAccounts);
|
||||
List<UserModel> searchForUser(String search, RealmModel realm);
|
||||
List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults);
|
||||
List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm);
|
||||
List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults);
|
||||
|
||||
// Searching by UserModel.attribute (not property)
|
||||
List<UserModel> searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm);
|
||||
|
||||
Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm);
|
||||
FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm);
|
||||
|
||||
void grantToAllUsers(RealmModel realm, RoleModel role);
|
||||
|
||||
void preRemove(RealmModel realm);
|
||||
|
||||
void preRemove(RealmModel realm, UserFederationProviderModel link);
|
||||
void preRemove(RealmModel realm, StorageProviderModel link);
|
||||
|
||||
void preRemove(RealmModel realm, RoleModel role);
|
||||
void preRemove(RealmModel realm, GroupModel group);
|
||||
|
@ -75,9 +63,10 @@ public interface UserProvider extends Provider {
|
|||
void preRemove(RealmModel realm, ClientModel client);
|
||||
void preRemove(ProtocolMapperModel protocolMapper);
|
||||
|
||||
boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, List<UserCredentialModel> input);
|
||||
|
||||
boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, UserCredentialModel... input);
|
||||
CredentialValidationOutput validCredentials(KeycloakSession session, RealmModel realm, UserCredentialModel... input);
|
||||
|
||||
|
||||
void close();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.models;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserQueryProvider {
|
||||
|
||||
// Service account is included for counts
|
||||
int getUsersCount(RealmModel realm);
|
||||
|
||||
List<UserModel> getUsers(RealmModel realm);
|
||||
List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm);
|
||||
|
||||
List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults);
|
||||
List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults);
|
||||
List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
List<UserModel> getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults);
|
||||
List<UserModel> getGroupMembers(RealmModel realm, GroupModel group);
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.models;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserUpdateProvider {
|
||||
UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions);
|
||||
|
||||
UserModel addUser(RealmModel realm, String username);
|
||||
|
||||
boolean removeUser(RealmModel realm, UserModel user);
|
||||
|
||||
void grantToAllUsers(RealmModel realm, RoleModel role);
|
||||
|
||||
}
|
|
@ -19,6 +19,7 @@ package org.keycloak.models.entities;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -80,13 +81,14 @@ public class RealmEntity extends AbstractIdentifiableEntity {
|
|||
private String emailTheme;
|
||||
|
||||
// We are using names of defaultRoles (not ids)
|
||||
private List<String> defaultRoles = new ArrayList<String>();
|
||||
private List<String> defaultGroups = new ArrayList<String>();
|
||||
private List<String> defaultRoles = new LinkedList<String>();
|
||||
private List<String> defaultGroups = new LinkedList<String>();
|
||||
|
||||
private List<RequiredCredentialEntity> requiredCredentials = new ArrayList<RequiredCredentialEntity>();
|
||||
private List<UserFederationProviderEntity> userFederationProviders = new ArrayList<UserFederationProviderEntity>();
|
||||
private List<UserFederationMapperEntity> userFederationMappers = new ArrayList<UserFederationMapperEntity>();
|
||||
private List<IdentityProviderEntity> identityProviders = new ArrayList<IdentityProviderEntity>();
|
||||
private List<RequiredCredentialEntity> requiredCredentials = new LinkedList<>();
|
||||
private List<StorageProviderEntity> storageProviders = new LinkedList<>();
|
||||
private List<UserFederationProviderEntity> userFederationProviders = new LinkedList<UserFederationProviderEntity>();
|
||||
private List<UserFederationMapperEntity> userFederationMappers = new LinkedList<UserFederationMapperEntity>();
|
||||
private List<IdentityProviderEntity> identityProviders = new LinkedList<IdentityProviderEntity>();
|
||||
|
||||
private Map<String, String> browserSecurityHeaders = new HashMap<String, String>();
|
||||
private Map<String, String> smtpConfig = new HashMap<String, String>();
|
||||
|
@ -682,6 +684,14 @@ public class RealmEntity extends AbstractIdentifiableEntity {
|
|||
public void setDefaultGroups(List<String> defaultGroups) {
|
||||
this.defaultGroups = defaultGroups;
|
||||
}
|
||||
|
||||
public List<StorageProviderEntity> getStorageProviders() {
|
||||
return storageProviders;
|
||||
}
|
||||
|
||||
public void setStorageProviders(List<StorageProviderEntity> storageProviders) {
|
||||
this.storageProviders = storageProviders;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.models.entities;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class StorageProviderEntity extends AbstractIdentifiableEntity {
|
||||
protected String providerName;
|
||||
protected Map<String, String> config;
|
||||
protected int priority;
|
||||
protected String displayName;
|
||||
|
||||
|
||||
public String getProviderName() {
|
||||
return providerName;
|
||||
}
|
||||
|
||||
public void setProviderName(String providerName) {
|
||||
this.providerName = providerName;
|
||||
}
|
||||
|
||||
public Map<String, String> getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public void setConfig(Map<String, String> config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
public void setPriority(int priority) {
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public void setDisplayName(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
}
|
|
@ -48,7 +48,7 @@ public class CredentialValidation {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Will update password if hash iteration policy has changed
|
||||
*
|
||||
* @param realm
|
||||
|
@ -195,7 +195,7 @@ public class CredentialValidation {
|
|||
return true;
|
||||
}
|
||||
|
||||
private static boolean validCredential(KeycloakSession session, RealmModel realm, UserModel user, UserCredentialModel credential) {
|
||||
public static boolean validCredential(KeycloakSession session, RealmModel realm, UserModel user, UserCredentialModel credential) {
|
||||
if (credential.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
if (!validPassword(session, realm, user, credential.getValue())) {
|
||||
return false;
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.models.utils;
|
||||
|
||||
import org.keycloak.common.util.Time;
|
||||
import org.keycloak.hash.PasswordHashManager;
|
||||
import org.keycloak.jose.jws.JWSInput;
|
||||
import org.keycloak.jose.jws.JWSInputException;
|
||||
import org.keycloak.jose.jws.crypto.RSAProvider;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.OTPPolicy;
|
||||
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.representations.PasswordToken;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class FederatedCredentialValidation {
|
||||
|
||||
private static int hashIterations(RealmModel realm) {
|
||||
PasswordPolicy policy = realm.getPasswordPolicy();
|
||||
if (policy != null) {
|
||||
return policy.getHashIterations();
|
||||
}
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Will update password if hash iteration policy has changed
|
||||
*
|
||||
* @param realm
|
||||
* @param user
|
||||
* @param password
|
||||
* @return
|
||||
*/
|
||||
public static boolean validPassword(KeycloakSession session, RealmModel realm, UserModel user, String password, UserCredentialValueModel fedCred) {
|
||||
return validateHashedCredential(session, realm, user, password, fedCred);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static boolean validateHashedCredential(KeycloakSession session, RealmModel realm, UserModel user, String unhashedCredValue, UserCredentialValueModel credential) {
|
||||
if (unhashedCredValue == null || unhashedCredValue.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean validated = PasswordHashManager.verify(session, realm, unhashedCredValue, credential);
|
||||
|
||||
if (validated) {
|
||||
int iterations = hashIterations(realm);
|
||||
if (iterations > -1 && iterations != credential.getHashIterations()) {
|
||||
|
||||
UserCredentialValueModel newCred = PasswordHashManager.encode(session, realm, unhashedCredValue);
|
||||
session.userFederatedStorage().updateCredential(realm, user, newCred);
|
||||
}
|
||||
|
||||
}
|
||||
return validated;
|
||||
}
|
||||
|
||||
public static boolean validPasswordToken(RealmModel realm, UserModel user, String encodedPasswordToken) {
|
||||
try {
|
||||
JWSInput jws = new JWSInput(encodedPasswordToken);
|
||||
if (!RSAProvider.verify(jws, realm.getPublicKey())) {
|
||||
return false;
|
||||
}
|
||||
PasswordToken passwordToken = jws.readJsonContent(PasswordToken.class);
|
||||
if (!passwordToken.getRealm().equals(realm.getName())) {
|
||||
return false;
|
||||
}
|
||||
if (!passwordToken.getUser().equals(user.getId())) {
|
||||
return false;
|
||||
}
|
||||
if (Time.currentTime() - passwordToken.getTimestamp() > realm.getAccessCodeLifespanUserAction()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} catch (JWSInputException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean validHOTP(KeycloakSession session, RealmModel realm, UserModel user, String otp, List<UserCredentialValueModel> fedCreds) {
|
||||
UserCredentialValueModel passwordCred = null;
|
||||
OTPPolicy policy = realm.getOTPPolicy();
|
||||
HmacOTP validator = new HmacOTP(policy.getDigits(), policy.getAlgorithm(), policy.getLookAheadWindow());
|
||||
for (UserCredentialValueModel cred : fedCreds) {
|
||||
if (cred.getType().equals(UserCredentialModel.HOTP)) {
|
||||
int counter = validator.validateHOTP(otp, cred.getValue(), cred.getCounter());
|
||||
if (counter < 0) return false;
|
||||
cred.setCounter(counter);
|
||||
session.userFederatedStorage().updateCredential(realm, user, cred);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
public static boolean validTOTP(RealmModel realm, UserModel user, String otp, List<UserCredentialValueModel> fedCreds) {
|
||||
UserCredentialValueModel passwordCred = null;
|
||||
OTPPolicy policy = realm.getOTPPolicy();
|
||||
TimeBasedOTP validator = new TimeBasedOTP(policy.getAlgorithm(), policy.getDigits(), policy.getPeriod(), policy.getLookAheadWindow());
|
||||
for (UserCredentialValueModel cred : fedCreds) {
|
||||
if (validator.validateTOTP(otp, cred.getValue().getBytes())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
public static boolean validSecret(RealmModel realm, UserModel user, String secret, UserCredentialValueModel cred) {
|
||||
return cred.getValue().equals(secret);
|
||||
|
||||
}
|
||||
|
||||
public static boolean validCredential(KeycloakSession session, RealmModel realm, UserModel user, UserCredentialModel credential, List<UserCredentialValueModel> fedCreds) {
|
||||
if (credential.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
if (!validPassword(session, realm, user, credential.getValue(), fedCreds.get(0))) {
|
||||
return false;
|
||||
}
|
||||
} else if (credential.getType().equals(UserCredentialModel.PASSWORD_TOKEN)) {
|
||||
if (!validPasswordToken(realm, user, credential.getValue())) {
|
||||
return false;
|
||||
}
|
||||
} else if (credential.getType().equals(UserCredentialModel.TOTP)) {
|
||||
if (!validTOTP(realm, user, credential.getValue(), fedCreds)) {
|
||||
return false;
|
||||
}
|
||||
} else if (credential.getType().equals(UserCredentialModel.HOTP)) {
|
||||
if (!validHOTP(session, realm, user, credential.getValue(), fedCreds)) {
|
||||
return false;
|
||||
}
|
||||
} else if (credential.getType().equals(UserCredentialModel.SECRET)) {
|
||||
if (!validSecret(realm, user, credential.getValue(), fedCreds.get(0))) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.models.utils;
|
||||
|
||||
import org.keycloak.common.util.Time;
|
||||
import org.keycloak.hash.PasswordHashManager;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.OTPPolicy;
|
||||
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.storage.federated.UserFederatedStorageProvider;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class FederatedCredentials {
|
||||
public static void updateCredential(KeycloakSession session, UserFederatedStorageProvider provider, RealmModel realm, UserModel user, UserCredentialModel cred) {
|
||||
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
updatePasswordCredential(session, provider,realm, user, cred);
|
||||
} else if (UserCredentialModel.isOtp(cred.getType())) {
|
||||
updateOtpCredential(session, provider, realm, user, cred);
|
||||
} else {
|
||||
UserCredentialValueModel fedCred = getCredentialByType(provider, realm, user, cred.getType());
|
||||
if (fedCred == null) {
|
||||
fedCred.setCreatedDate(Time.toMillis(Time.currentTime()));
|
||||
fedCred.setType(cred.getType());
|
||||
fedCred.setDevice(cred.getDevice());
|
||||
fedCred.setValue(cred.getValue());
|
||||
|
||||
} else {
|
||||
fedCred.setValue(cred.getValue());
|
||||
}
|
||||
provider.updateCredential(realm, user, fedCred);
|
||||
}
|
||||
}
|
||||
|
||||
public static UserCredentialValueModel getCredentialByType(UserFederatedStorageProvider provider, RealmModel realm, UserModel user, String type) {
|
||||
List<UserCredentialValueModel> creds = provider.getCredentials(realm, user);
|
||||
for (UserCredentialValueModel cred : creds) {
|
||||
if (cred.getType().equals(type)) return cred;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static LinkedList<UserCredentialValueModel> getCredentialsByType(UserFederatedStorageProvider provider, RealmModel realm, UserModel user, String type) {
|
||||
List<UserCredentialValueModel> creds = provider.getCredentials(realm, user);
|
||||
LinkedList<UserCredentialValueModel> newCreds = new LinkedList<>();
|
||||
for (UserCredentialValueModel cred : creds) {
|
||||
if (cred.getType().equals(type)) newCreds.add(cred);
|
||||
}
|
||||
return newCreds;
|
||||
}
|
||||
|
||||
public static void updatePasswordCredential(KeycloakSession session, UserFederatedStorageProvider provider, RealmModel realm, UserModel user, UserCredentialModel cred) {
|
||||
UserCredentialValueModel fedCred = getCredentialByType(provider, realm, user, cred.getType());
|
||||
if (fedCred == null) {
|
||||
UserCredentialValueModel newCred = PasswordHashManager.encode(session, realm, cred.getValue());
|
||||
newCred.setCreatedDate(Time.toMillis(Time.currentTime()));
|
||||
newCred.setType(cred.getType());
|
||||
newCred.setDevice(cred.getDevice());
|
||||
provider.updateCredential(realm, user, newCred);
|
||||
} else {
|
||||
int expiredPasswordsPolicyValue = -1;
|
||||
PasswordPolicy policy = realm.getPasswordPolicy();
|
||||
if(policy != null) {
|
||||
expiredPasswordsPolicyValue = policy.getExpiredPasswords();
|
||||
}
|
||||
|
||||
if (expiredPasswordsPolicyValue != -1) {
|
||||
fedCred.setType(UserCredentialModel.PASSWORD_HISTORY);
|
||||
|
||||
LinkedList<UserCredentialValueModel> credentialEntities = getCredentialsByType(provider, realm, user, UserCredentialModel.PASSWORD_HISTORY);
|
||||
if (credentialEntities.size() > expiredPasswordsPolicyValue - 1) {
|
||||
Collections.sort(credentialEntities, new Comparator<UserCredentialValueModel>() {
|
||||
@Override
|
||||
public int compare(UserCredentialValueModel o1, UserCredentialValueModel o2) {
|
||||
if (o1.getCreatedDate().equals(o2.getCreatedDate())) return 0;
|
||||
return o1.getCreatedDate() < o2.getCreatedDate() ? -1 : 1;
|
||||
}
|
||||
});
|
||||
while (credentialEntities.size() > expiredPasswordsPolicyValue - 1) {
|
||||
UserCredentialValueModel model = credentialEntities.removeFirst();
|
||||
provider.removeCredential(realm, user, model);
|
||||
}
|
||||
|
||||
}
|
||||
provider.updateCredential(realm, user, fedCred);
|
||||
fedCred = PasswordHashManager.encode(session, realm, cred.getValue());
|
||||
fedCred.setCreatedDate(Time.toMillis(Time.currentTime()));
|
||||
fedCred.setType(cred.getType());
|
||||
fedCred.setDevice(cred.getDevice());
|
||||
provider.updateCredential(realm, user, fedCred);
|
||||
} else {
|
||||
// clear password history as it is not required anymore
|
||||
for (UserCredentialValueModel model : getCredentialsByType(provider, realm, user, UserCredentialModel.PASSWORD_HISTORY)) {
|
||||
provider.removeCredential(realm, user, model);
|
||||
}
|
||||
UserCredentialValueModel newCred = PasswordHashManager.encode(session, realm, cred.getValue());
|
||||
newCred.setCreatedDate(Time.toMillis(Time.currentTime()));
|
||||
newCred.setType(cred.getType());
|
||||
newCred.setDevice(cred.getDevice());
|
||||
newCred.setId(fedCred.getId());
|
||||
provider.updateCredential(realm, user, newCred);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static void updateOtpCredential(KeycloakSession session, UserFederatedStorageProvider provider, RealmModel realm, UserModel user, UserCredentialModel cred) {
|
||||
LinkedList<UserCredentialValueModel> credentialEntities = getCredentialsByType(provider, realm, user, UserCredentialModel.PASSWORD_HISTORY);
|
||||
|
||||
if (credentialEntities.isEmpty()) {
|
||||
UserCredentialValueModel fedCred = new UserCredentialValueModel();
|
||||
fedCred.setCreatedDate(Time.toMillis(Time.currentTime()));
|
||||
fedCred.setType(cred.getType());
|
||||
fedCred.setDevice(cred.getDevice());
|
||||
fedCred.setValue(cred.getValue());
|
||||
OTPPolicy otpPolicy = realm.getOTPPolicy();
|
||||
fedCred.setAlgorithm(otpPolicy.getAlgorithm());
|
||||
fedCred.setDigits(otpPolicy.getDigits());
|
||||
fedCred.setCounter(otpPolicy.getInitialCounter());
|
||||
fedCred.setPeriod(otpPolicy.getPeriod());
|
||||
provider.updateCredential(realm, user, fedCred);
|
||||
} else {
|
||||
OTPPolicy policy = realm.getOTPPolicy();
|
||||
if (cred.getDevice() == null) {
|
||||
for (UserCredentialValueModel model : credentialEntities) provider.removeCredential(realm, user, model);
|
||||
UserCredentialValueModel fedCred = new UserCredentialValueModel();
|
||||
fedCred.setCreatedDate(Time.toMillis(Time.currentTime()));
|
||||
fedCred.setType(cred.getType());
|
||||
fedCred.setDevice(cred.getDevice());
|
||||
fedCred.setDigits(policy.getDigits());
|
||||
fedCred.setCounter(policy.getInitialCounter());
|
||||
fedCred.setAlgorithm(policy.getAlgorithm());
|
||||
fedCred.setValue(cred.getValue());
|
||||
fedCred.setPeriod(policy.getPeriod());
|
||||
provider.updateCredential(realm, user, fedCred);
|
||||
} else {
|
||||
UserCredentialValueModel fedCred = new UserCredentialValueModel();
|
||||
for (UserCredentialValueModel model : credentialEntities) {
|
||||
if (cred.getDevice().equals(model.getDevice())) {
|
||||
fedCred = model;
|
||||
break;
|
||||
}
|
||||
}
|
||||
fedCred.setCreatedDate(Time.toMillis(Time.currentTime()));
|
||||
fedCred.setType(cred.getType());
|
||||
fedCred.setDevice(cred.getDevice());
|
||||
fedCred.setDigits(policy.getDigits());
|
||||
fedCred.setCounter(policy.getInitialCounter());
|
||||
fedCred.setAlgorithm(policy.getAlgorithm());
|
||||
fedCred.setValue(cred.getValue());
|
||||
fedCred.setPeriod(policy.getPeriod());
|
||||
provider.updateCredential(realm, user, fedCred);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -44,6 +44,7 @@ import org.keycloak.models.UserModel;
|
|||
import org.keycloak.representations.idm.CertificateRepresentation;
|
||||
import org.keycloak.common.util.CertificateUtils;
|
||||
import org.keycloak.common.util.PemUtils;
|
||||
import org.keycloak.storage.StorageProviderModel;
|
||||
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.IOException;
|
||||
|
@ -341,6 +342,43 @@ public final class KeycloakModelUtils {
|
|||
}
|
||||
// USER FEDERATION RELATED STUFF
|
||||
|
||||
/**
|
||||
* Ensure that displayName of myProvider (if not null) is unique and there is no other provider with same displayName in the list.
|
||||
*
|
||||
* @param displayName to check for duplications
|
||||
* @param myProvider provider, which is excluded from the list (if present)
|
||||
* @param federationProviders
|
||||
* @throws ModelDuplicateException if there is other provider with same displayName
|
||||
*/
|
||||
public static void ensureUniqueDisplayName(String displayName, StorageProviderModel myProvider, List<StorageProviderModel> federationProviders) throws ModelDuplicateException {
|
||||
if (displayName != null) {
|
||||
|
||||
for (StorageProviderModel federationProvider : federationProviders) {
|
||||
if (myProvider != null && (myProvider.equals(federationProvider) || (myProvider.getId() != null && myProvider.getId().equals(federationProvider.getId())))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (displayName.equals(federationProvider.getDisplayName())) {
|
||||
throw new ModelDuplicateException("There is already existing federation provider with display name: " + displayName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static StorageProviderModel findStorageProviderByDisplayName(String displayName, RealmModel realm) {
|
||||
if (displayName == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (StorageProviderModel provider : realm.getStorageProviders()) {
|
||||
if (displayName.equals(provider.getDisplayName())) {
|
||||
return provider;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that displayName of myProvider (if not null) is unique and there is no other provider with same displayName in the list.
|
||||
*
|
||||
|
@ -378,7 +416,6 @@ public final class KeycloakModelUtils {
|
|||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static UserFederationProviderModel findUserFederationProviderById(String fedProviderId, RealmModel realm) {
|
||||
for (UserFederationProviderModel fedProvider : realm.getUserFederationProviders()) {
|
||||
if (fedProviderId.equals(fedProvider.getId())) {
|
||||
|
|
|
@ -1279,7 +1279,7 @@ public class RepresentationToModel {
|
|||
if (userRep.getClientConsents() != null) {
|
||||
for (UserConsentRepresentation consentRep : userRep.getClientConsents()) {
|
||||
UserConsentModel consentModel = toModel(newRealm, consentRep);
|
||||
user.addConsent(consentModel);
|
||||
session.userStorage().addConsent(newRealm, user, consentModel);
|
||||
}
|
||||
}
|
||||
if (userRep.getServiceAccountClientId() != null) {
|
||||
|
|
|
@ -235,31 +235,6 @@ public class UserModelDelegate implements UserModel {
|
|||
delegate.setServiceAccountClientLink(clientInternalId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addConsent(UserConsentModel consent) {
|
||||
delegate.addConsent(consent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserConsentModel getConsentByClient(String clientId) {
|
||||
return delegate.getConsentByClient(clientId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserConsentModel> getConsents() {
|
||||
return delegate.getConsents();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateConsent(UserConsentModel consent) {
|
||||
delegate.updateConsent(consent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean revokeConsentForClient(String clientId) {
|
||||
return delegate.revokeConsentForClient(clientId);
|
||||
}
|
||||
|
||||
public UserModel getDelegate() {
|
||||
return delegate;
|
||||
}
|
||||
|
|
65
server-spi/src/main/java/org/keycloak/storage/StorageId.java
Normal file
65
server-spi/src/main/java/org/keycloak/storage/StorageId.java
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage;
|
||||
|
||||
import org.keycloak.models.UserModel;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class StorageId implements Serializable {
|
||||
private String id;
|
||||
private String providerId;
|
||||
private String storageId;
|
||||
|
||||
|
||||
public StorageId(String id) {
|
||||
this.id = id;
|
||||
if (!id.startsWith("f:")) {
|
||||
storageId = id;
|
||||
return;
|
||||
}
|
||||
int providerIndex = id.indexOf(':', 2);
|
||||
providerId = id.substring(2, providerIndex);
|
||||
storageId = id.substring(providerIndex + 1);
|
||||
|
||||
}
|
||||
|
||||
public static String resolveProviderId(UserModel user) {
|
||||
return new StorageId(user.getId()).getProviderId();
|
||||
}
|
||||
public static boolean isLocalStorage(UserModel user) {
|
||||
return new StorageId(user.getId()).getProviderId() == null;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getProviderId() {
|
||||
return providerId;
|
||||
}
|
||||
|
||||
public String getStorageId() {
|
||||
return storageId;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage;
|
||||
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.ProtocolMapperModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.provider.Provider;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface StorageProvider extends Provider {
|
||||
StorageProviderModel getModel();
|
||||
|
||||
void preRemove(RealmModel realm);
|
||||
void preRemove(RealmModel realm, GroupModel group);
|
||||
void preRemove(RealmModel realm, RoleModel role);
|
||||
void preRemove(RealmModel realm, StorageProviderModel model);
|
||||
|
||||
}
|
||||
|
62
server-spi/src/main/java/org/keycloak/storage/StorageProviderFactory.java
Executable file
62
server-spi/src/main/java/org/keycloak/storage/StorageProviderFactory.java
Executable file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.storage;
|
||||
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface StorageProviderFactory extends ProviderFactory<StorageProvider> {
|
||||
boolean supports(Class<?> type);
|
||||
/**
|
||||
* called per Keycloak transaction.
|
||||
*
|
||||
* @param session
|
||||
* @param model
|
||||
* @return
|
||||
*/
|
||||
StorageProvider getInstance(KeycloakSession session, StorageProviderModel model);
|
||||
|
||||
/**
|
||||
* Config options to display in generic admin console page for federated
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Set<String> getConfigurationOptions();
|
||||
|
||||
/**
|
||||
* This is the name of the provider and will be showed in the admin console as an option.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
String getId();
|
||||
|
||||
/**
|
||||
* This method is never called and is only an artifact of ProviderFactory. Returning null with no implementation is recommended.
|
||||
* @param session
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
StorageProvider create(KeycloakSession session);
|
||||
}
|
89
server-spi/src/main/java/org/keycloak/storage/StorageProviderModel.java
Executable file
89
server-spi/src/main/java/org/keycloak/storage/StorageProviderModel.java
Executable file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.storage;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Stored configuration of a User Storage provider instance.
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
* @author <a href="mailto:bburke@redhat.com">Bill Burke</a>
|
||||
*/
|
||||
public class StorageProviderModel implements Serializable {
|
||||
|
||||
private String id;
|
||||
private String providerName;
|
||||
private Map<String, String> config = new HashMap<String, String>();
|
||||
private int priority;
|
||||
private String displayName;
|
||||
|
||||
public StorageProviderModel() {}
|
||||
|
||||
public StorageProviderModel(String id, String providerName, Map<String, String> config, int priority, String displayName) {
|
||||
this.id = id;
|
||||
this.providerName = providerName;
|
||||
if (config != null) {
|
||||
this.config.putAll(config);
|
||||
}
|
||||
this.priority = priority;
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getProviderName() {
|
||||
return providerName;
|
||||
}
|
||||
|
||||
public void setProviderName(String providerName) {
|
||||
this.providerName = providerName;
|
||||
}
|
||||
|
||||
public Map<String, String> getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public void setConfig(Map<String, String> config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
public void setPriority(int priority) {
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public void setDisplayName(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
}
|
49
server-spi/src/main/java/org/keycloak/storage/StorageProviderSpi.java
Executable file
49
server-spi/src/main/java/org/keycloak/storage/StorageProviderSpi.java
Executable file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.storage;
|
||||
|
||||
import org.keycloak.provider.Provider;
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
import org.keycloak.provider.Spi;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class StorageProviderSpi implements Spi {
|
||||
|
||||
@Override
|
||||
public boolean isInternal() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "userFederation";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Provider> getProviderClass() {
|
||||
return StorageProvider.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends ProviderFactory> getProviderFactoryClass() {
|
||||
return StorageProviderFactory.class;
|
||||
}
|
||||
|
||||
}
|
549
server-spi/src/main/java/org/keycloak/storage/UserStorageManager.java
Executable file
549
server-spi/src/main/java/org/keycloak/storage/UserStorageManager.java
Executable file
|
@ -0,0 +1,549 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.storage;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.CredentialValidationOutput;
|
||||
import org.keycloak.models.FederatedIdentityModel;
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ModelException;
|
||||
import org.keycloak.models.ProtocolMapperModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserConsentModel;
|
||||
import org.keycloak.models.UserCredentialAuthenticationProvider;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserCredentialValidatorProvider;
|
||||
import org.keycloak.models.UserCredentialValueModel;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.UserLookupProvider;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserProvider;
|
||||
import org.keycloak.models.UserQueryProvider;
|
||||
import org.keycloak.models.UserUpdateProvider;
|
||||
import org.keycloak.models.utils.CredentialValidation;
|
||||
import org.keycloak.storage.federated.UserFederatedStorageProvider;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
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 UserStorageManager implements UserProvider {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(UserStorageManager.class);
|
||||
|
||||
protected KeycloakSession session;
|
||||
|
||||
// Set of already validated/proxied federation users during this session. Key is user ID
|
||||
private Map<String, UserModel> managedUsers = new HashMap<>();
|
||||
private UserProvider localStorage = null;
|
||||
|
||||
public UserStorageManager(KeycloakSession session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
protected UserProvider localStorage() {
|
||||
return session.userLocalStorage();
|
||||
}
|
||||
|
||||
protected List<StorageProviderModel> getStorageProviders(RealmModel realm) {
|
||||
return realm.getStorageProviders();
|
||||
}
|
||||
|
||||
protected <T> T getFirstStorageProvider(RealmModel realm, Class<T> type) {
|
||||
for (StorageProviderModel model : getStorageProviders(realm)) {
|
||||
StorageProviderFactory factory = (StorageProviderFactory)session.getKeycloakSessionFactory().getProviderFactory(StorageProvider.class, model.getProviderName());
|
||||
if (factory.supports(type)) {
|
||||
return type.cast(factory.getInstance(session, model));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected <T> List<T> getStorageProviders(RealmModel realm, Class<T> type) {
|
||||
List<T> list = new LinkedList<>();
|
||||
for (StorageProviderModel model : getStorageProviders(realm)) {
|
||||
StorageProviderFactory factory = (StorageProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(StorageProvider.class, model.getProviderName());
|
||||
if (factory.supports(type)) {
|
||||
list.add(type.cast(factory.getInstance(session, model)));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions) {
|
||||
UserUpdateProvider registry = getFirstStorageProvider(realm, UserUpdateProvider.class);
|
||||
if (registry != null) {
|
||||
return registry.addUser(realm, id, username, addDefaultRoles, addDefaultRequiredActions);
|
||||
}
|
||||
return localStorage().addUser(realm, id, username.toLowerCase(), addDefaultRoles, addDefaultRequiredActions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel addUser(RealmModel realm, String username) {
|
||||
UserUpdateProvider registry = getFirstStorageProvider(realm, UserUpdateProvider.class);
|
||||
if (registry != null) {
|
||||
return registry.addUser(realm, username);
|
||||
}
|
||||
return localStorage().addUser(realm, username.toLowerCase());
|
||||
}
|
||||
|
||||
public StorageProvider getStorageProvider(StorageProviderModel model) {
|
||||
StorageProviderFactory factory = (StorageProviderFactory)session.getKeycloakSessionFactory().getProviderFactory(StorageProvider.class, model.getProviderName());
|
||||
return factory.getInstance(session, model);
|
||||
}
|
||||
|
||||
public StorageProvider getStorageProvider(RealmModel realm, String providerId) {
|
||||
StorageProviderModel model = realm.getStorageProvider(providerId);
|
||||
if (model == null) return null;
|
||||
StorageProviderFactory factory = (StorageProviderFactory)session.getKeycloakSessionFactory().getProviderFactory(StorageProvider.class, model.getProviderName());
|
||||
if (factory == null) {
|
||||
throw new ModelException("Could not find StorageProviderFactory for: " + model.getProviderName());
|
||||
}
|
||||
return factory.getInstance(session, model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeUser(RealmModel realm, UserModel user) {
|
||||
StorageId storageId = new StorageId(user.getId());
|
||||
if (storageId.getProviderId() == null) {
|
||||
return localStorage().removeUser(realm, user);
|
||||
}
|
||||
UserUpdateProvider registry = (UserUpdateProvider)getStorageProvider(realm, storageId.getProviderId());
|
||||
if (registry == null) {
|
||||
throw new ModelException("Could not resolve StorageProvider: " + storageId.getProviderId());
|
||||
}
|
||||
return registry.removeUser(realm, user);
|
||||
|
||||
}
|
||||
|
||||
public UserFederatedStorageProvider getFederatedStorage() {
|
||||
return session.userFederatedStorage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel socialLink) {
|
||||
getFederatedStorage().addFederatedIdentity(realm, user, socialLink);
|
||||
}
|
||||
|
||||
public void updateFederatedIdentity(RealmModel realm, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel) {
|
||||
getFederatedStorage().updateFederatedIdentity(realm, federatedUser, federatedIdentityModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeFederatedIdentity(RealmModel realm, UserModel user, String socialProvider) {
|
||||
return getFederatedStorage().removeFederatedIdentity(realm, user, socialProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
|
||||
getFederatedStorage().addConsent(realm, user, consent);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserConsentModel getConsentByClient(RealmModel realm, UserModel user, String clientInternalId) {
|
||||
return getFederatedStorage().getConsentByClient(realm, user, clientInternalId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserConsentModel> getConsents(RealmModel realm, UserModel user) {
|
||||
return getFederatedStorage().getConsents(realm, user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
|
||||
getFederatedStorage().updateConsent(realm, user, consent);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean revokeConsentForClient(RealmModel realm, UserModel user, String clientInternalId) {
|
||||
return getFederatedStorage().revokeConsentForClient(realm, user, clientInternalId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserById(String id, RealmModel realm) {
|
||||
StorageId storageId = new StorageId(id);
|
||||
if (storageId.getProviderId() == null) {
|
||||
return localStorage().getUserById(id, realm);
|
||||
}
|
||||
UserLookupProvider provider = (UserLookupProvider)getStorageProvider(realm, storageId.getProviderId());
|
||||
return provider.getUserById(id, realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group) {
|
||||
return getGroupMembers(realm, group, -1, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserByUsername(String username, RealmModel realm) {
|
||||
UserModel user = localStorage().getUserByUsername(username, realm);
|
||||
if (user != null) return user;
|
||||
for (UserLookupProvider provider : getStorageProviders(realm, UserLookupProvider.class)) {
|
||||
user = provider.getUserByUsername(username, realm);
|
||||
if (user != null) return user;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserByEmail(String email, RealmModel realm) {
|
||||
UserModel user = localStorage().getUserByEmail(email, realm);
|
||||
if (user != null) return user;
|
||||
for (UserLookupProvider provider : getStorageProviders(realm, UserLookupProvider.class)) {
|
||||
user = provider.getUserByEmail(email, realm);
|
||||
if (user != null) return user;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserByFederatedIdentity(FederatedIdentityModel socialLink, RealmModel realm) {
|
||||
UserModel user = localStorage().getUserByFederatedIdentity(socialLink, realm);
|
||||
if (user != null) {
|
||||
return user;
|
||||
}
|
||||
String id = getFederatedStorage().getUserByFederatedIdentity(socialLink, realm);
|
||||
if (id != null) return getUserById(id, realm);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getServiceAccount(ClientModel client) {
|
||||
return localStorage().getServiceAccount(client);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getUsers(RealmModel realm, boolean includeServiceAccounts) {
|
||||
return getUsers(realm, 0, Integer.MAX_VALUE - 1, includeServiceAccounts);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getUsers(RealmModel realm) {
|
||||
return getUsers(realm, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
|
||||
return getUsers(realm, firstResult, maxResults, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUsersCount(RealmModel realm) {
|
||||
int size = localStorage().getUsersCount(realm);
|
||||
for (UserQueryProvider provider : getStorageProviders(realm, UserQueryProvider.class)) {
|
||||
size += provider.getUsersCount(realm);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
interface PaginatedQuery {
|
||||
List<UserModel> query(UserQueryProvider provider, int first, int max);
|
||||
}
|
||||
|
||||
protected List<UserModel> query(PaginatedQuery pagedQuery, RealmModel realm, int firstResult, int maxResults) {
|
||||
List<UserModel> results = new LinkedList<UserModel>();
|
||||
if (maxResults == 0) return results;
|
||||
|
||||
|
||||
List<UserQueryProvider> storageProviders = getStorageProviders(realm, UserQueryProvider.class);
|
||||
LinkedList<UserQueryProvider> providers = new LinkedList<>();
|
||||
if (providers.isEmpty()) {
|
||||
return pagedQuery.query(localStorage(), firstResult, maxResults);
|
||||
}
|
||||
providers.add(localStorage());
|
||||
providers.addAll(storageProviders);
|
||||
|
||||
int leftToRead = maxResults;
|
||||
int leftToFirstResult = firstResult;
|
||||
|
||||
Iterator<UserQueryProvider> it = providers.iterator();
|
||||
while (it.hasNext() && leftToRead != 0) {
|
||||
UserQueryProvider provider = it.next();
|
||||
boolean exhausted = false;
|
||||
int index = 0;
|
||||
if (leftToFirstResult > 0) {
|
||||
do {
|
||||
int toRead = Math.min(50, leftToFirstResult);
|
||||
List<UserModel> tmp = pagedQuery.query(provider, index, toRead);
|
||||
leftToFirstResult -= tmp.size();
|
||||
index += tmp.size();
|
||||
if (tmp.size() < toRead) {
|
||||
exhausted = true;
|
||||
break;
|
||||
}
|
||||
} while (leftToFirstResult > 0);
|
||||
}
|
||||
if (exhausted) continue;
|
||||
List<UserModel> tmp = pagedQuery.query(provider, index, leftToRead);
|
||||
results.addAll(tmp);
|
||||
if (leftToRead > 0) leftToRead -= tmp.size();
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getUsers(final RealmModel realm, int firstResult, int maxResults, final boolean includeServiceAccounts) {
|
||||
return query(new PaginatedQuery() {
|
||||
@Override
|
||||
public List<UserModel> query(UserQueryProvider provider, int first, int max) {
|
||||
if (provider instanceof UserProvider) { // it is local storage
|
||||
return ((UserProvider)provider).getUsers(realm, first, max, includeServiceAccounts);
|
||||
}
|
||||
return provider.getUsers(realm, first, max);
|
||||
}
|
||||
}, realm, firstResult, maxResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUser(String search, RealmModel realm) {
|
||||
return searchForUser(search, realm, 0, Integer.MAX_VALUE - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUser(final String search, final RealmModel realm, int firstResult, int maxResults) {
|
||||
final Map<String, String> attributes = new HashMap<String, String>();
|
||||
int spaceIndex = search.lastIndexOf(' ');
|
||||
if (spaceIndex > -1) {
|
||||
String firstName = search.substring(0, spaceIndex).trim();
|
||||
String lastName = search.substring(spaceIndex).trim();
|
||||
attributes.put(UserModel.FIRST_NAME, firstName);
|
||||
attributes.put(UserModel.LAST_NAME, lastName);
|
||||
} else if (search.indexOf('@') > -1) {
|
||||
attributes.put(UserModel.USERNAME, search.trim().toLowerCase());
|
||||
attributes.put(UserModel.EMAIL, search.trim().toLowerCase());
|
||||
} else {
|
||||
attributes.put(UserModel.LAST_NAME, search.trim());
|
||||
attributes.put(UserModel.USERNAME, search.trim().toLowerCase());
|
||||
}
|
||||
return query(new PaginatedQuery() {
|
||||
@Override
|
||||
public List<UserModel> query(UserQueryProvider provider, int first, int max) {
|
||||
return provider.searchForUserByAttributes(attributes, realm, first, max);
|
||||
}
|
||||
}, realm, firstResult, maxResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm) {
|
||||
return searchForUserByAttributes(attributes, realm, 0, Integer.MAX_VALUE - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUserByAttributes(final Map<String, String> attributes, final RealmModel realm, int firstResult, int maxResults) {
|
||||
return query(new PaginatedQuery() {
|
||||
@Override
|
||||
public List<UserModel> query(UserQueryProvider provider, int first, int max) {
|
||||
return provider.searchForUserByAttributes(attributes, realm, first, max);
|
||||
}
|
||||
}, realm, firstResult, maxResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm) {
|
||||
Map<String, String> attributes = new HashMap<>();
|
||||
attributes.put(attrName, attrValue);
|
||||
return searchForUserByAttributes(attributes, realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm) {
|
||||
if (user == null) throw new IllegalStateException("Federated user no longer valid");
|
||||
if (StorageId.isLocalStorage(user)) {
|
||||
return localStorage().getFederatedIdentities(user, realm);
|
||||
}
|
||||
return getFederatedStorage().getFederatedIdentities(user, realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm) {
|
||||
if (user == null) throw new IllegalStateException("Federated user no longer valid");
|
||||
if (StorageId.isLocalStorage(user)) {
|
||||
return localStorage().getFederatedIdentity(user, socialProvider, realm);
|
||||
}
|
||||
return getFederatedStorage().getFederatedIdentity(user, socialProvider, realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void grantToAllUsers(RealmModel realm, RoleModel role) {
|
||||
// not federation-aware for now
|
||||
List<UserUpdateProvider> storageProviders = getStorageProviders(realm, UserUpdateProvider.class);
|
||||
LinkedList<UserUpdateProvider> providers = new LinkedList<>();
|
||||
providers.add(localStorage());
|
||||
providers.addAll(storageProviders);
|
||||
for (UserUpdateProvider provider : providers) {
|
||||
provider.grantToAllUsers(realm, role);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getGroupMembers(final RealmModel realm, final GroupModel group, int firstResult, int maxResults) {
|
||||
return query(new PaginatedQuery() {
|
||||
@Override
|
||||
public List<UserModel> query(UserQueryProvider provider, int first, int max) {
|
||||
return provider.getGroupMembers(realm, group, first, max);
|
||||
}
|
||||
}, realm, firstResult, maxResults);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm) {
|
||||
localStorage().preRemove(realm);
|
||||
getFederatedStorage().preRemove(realm);
|
||||
for (StorageProvider provider : getStorageProviders(realm, StorageProvider.class)) {
|
||||
provider.preRemove(realm);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, UserFederationProviderModel model) {
|
||||
localStorage().preRemove(realm, model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, GroupModel group) {
|
||||
localStorage().preRemove(realm, group);
|
||||
getFederatedStorage().preRemove(realm, group);
|
||||
for (StorageProvider provider : getStorageProviders(realm, StorageProvider.class)) {
|
||||
provider.preRemove(realm, group);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, RoleModel role) {
|
||||
localStorage().preRemove(realm, role);
|
||||
getFederatedStorage().preRemove(realm, role);
|
||||
for (StorageProvider provider : getStorageProviders(realm, StorageProvider.class)) {
|
||||
provider.preRemove(realm, role);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, ClientModel client) {
|
||||
localStorage().preRemove(realm, client);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(ProtocolMapperModel protocolMapper) {
|
||||
localStorage().preRemove(protocolMapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, List<UserCredentialModel> input) {
|
||||
if (StorageId.isLocalStorage(user)) {
|
||||
return localStorage().validCredentials(session, realm, user, input);
|
||||
}
|
||||
// make sure we hit the cache here!
|
||||
List<UserCredentialValueModel> userCreds = user.getCredentialsDirectly();
|
||||
|
||||
LinkedList<UserCredentialModel> toValidate = new LinkedList<>();
|
||||
toValidate.addAll(input);
|
||||
Iterator<UserCredentialModel> it = toValidate.iterator();
|
||||
boolean failedStoredCredential = false;
|
||||
// we allow for multiple credentials of same type, i.e. multiple OTP devices
|
||||
while (it.hasNext()) {
|
||||
UserCredentialModel cred = it.next();
|
||||
boolean credValidated = false;
|
||||
for (UserCredentialValueModel userCred : userCreds) {
|
||||
if (!userCred.getType().equals(cred.getType())) continue;
|
||||
if (CredentialValidation.validCredential(session, realm, user, cred)) {
|
||||
credValidated = true;
|
||||
break;
|
||||
} else {
|
||||
failedStoredCredential = true;
|
||||
}
|
||||
}
|
||||
if (credValidated) {
|
||||
it.remove();
|
||||
} else if (failedStoredCredential) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (toValidate.isEmpty()) return true;
|
||||
|
||||
StorageProvider provider = getStorageProvider(realm, StorageId.resolveProviderId(user));
|
||||
if (!(provider instanceof UserCredentialValidatorProvider)) {
|
||||
return false;
|
||||
}
|
||||
return ((UserCredentialValidatorProvider)provider).validCredentials(session, realm, user, toValidate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, UserCredentialModel... input) {
|
||||
return validCredentials(session, realm, user, Arrays.asList(input));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CredentialValidationOutput validCredentials(KeycloakSession session, RealmModel realm, UserCredentialModel... input) {
|
||||
List<UserCredentialAuthenticationProvider> providers = getStorageProviders(realm, UserCredentialAuthenticationProvider.class);
|
||||
if (providers.isEmpty()) return CredentialValidationOutput.failed();
|
||||
|
||||
CredentialValidationOutput result = null;
|
||||
for (UserCredentialModel cred : input) {
|
||||
UserCredentialAuthenticationProvider providerSupportingCreds = null;
|
||||
|
||||
// Find first provider, which supports required credential type
|
||||
for (UserCredentialAuthenticationProvider provider : providers) {
|
||||
if (provider.getSupportedCredentialAuthenticationTypes().contains(cred.getType())) {
|
||||
providerSupportingCreds = provider;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (providerSupportingCreds == null) {
|
||||
logger.warn("Don't have provider supporting credentials of type " + cred.getType());
|
||||
return CredentialValidationOutput.failed();
|
||||
}
|
||||
|
||||
logger.debug("Found provider [" + providerSupportingCreds + "] supporting credentials of type " + cred.getType());
|
||||
CredentialValidationOutput currentResult = providerSupportingCreds.validCredential(session, realm, cred);
|
||||
result = (result == null) ? currentResult : result.merge(currentResult);
|
||||
}
|
||||
|
||||
// For now, validCredentials(realm, input) is not supported for local userProviders
|
||||
return (result != null) ? result : CredentialValidationOutput.failed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, StorageProviderModel link) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserStorageProvider {
|
||||
void preRemove(RealmModel realm);
|
||||
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage.adapter;
|
||||
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserCredentialValueModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.storage.federated.UserFederatedStorageProvider;
|
||||
|
||||
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 abstract class AbstractUserAdapter implements UserModel {
|
||||
protected KeycloakSession session;
|
||||
protected RealmModel realm;
|
||||
|
||||
public UserFederatedStorageProvider getFederatedStorage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getRequiredActions() {
|
||||
return getFederatedStorage().getRequiredActions(realm, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRequiredAction(String action) {
|
||||
getFederatedStorage().addRequiredAction(realm, this, action);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRequiredAction(String action) {
|
||||
getFederatedStorage().removeRequiredAction(realm, this, action);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRequiredAction(RequiredAction action) {
|
||||
getFederatedStorage().addRequiredAction(realm, this, action.name());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRequiredAction(RequiredAction action) {
|
||||
getFederatedStorage().removeRequiredAction(realm, this, action.name());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<GroupModel> getGroups() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void joinGroup(GroupModel group) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leaveGroup(GroupModel group) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMemberOf(GroupModel group) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFederationLink() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFederationLink(String link) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServiceAccountClientLink() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setServiceAccountClientLink(String clientInternalId) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRealmRoleMappings() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getClientRoleMappings(ClientModel app) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRole(RoleModel role) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void grantRole(RoleModel role) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRoleMappings() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteRoleMapping(RoleModel role) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOtpEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOtpEnabled(boolean totp) {
|
||||
|
||||
}
|
||||
}
|
387
server-spi/src/main/java/org/keycloak/storage/changeset/UserData.java
Executable file
387
server-spi/src/main/java/org/keycloak/storage/changeset/UserData.java
Executable file
|
@ -0,0 +1,387 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.storage.changeset;
|
||||
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
import org.keycloak.models.UserCredentialValueModel;
|
||||
import org.keycloak.models.entities.AbstractIdentifiableEntity;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class UserData {
|
||||
|
||||
private String id;
|
||||
private boolean idChanged;
|
||||
private String username;
|
||||
private boolean usernameChanged;
|
||||
private Long createdTimestamp;
|
||||
private boolean createdTimestampChanged;
|
||||
private String firstName;
|
||||
private boolean firstNameChanged;
|
||||
private String lastName;
|
||||
private boolean lastNameChanged;
|
||||
private String email;
|
||||
private boolean emailChanged;
|
||||
private boolean emailVerified;
|
||||
private boolean emailVerifiedChanged;
|
||||
private boolean totp;
|
||||
private boolean totpChanged;
|
||||
private boolean enabled;
|
||||
private boolean enabledChanged;
|
||||
|
||||
private Set<String> roleIds = new HashSet<>();
|
||||
private boolean rolesChanged;
|
||||
private Set<String> groupIds = new HashSet<>();
|
||||
private boolean groupsChanged;
|
||||
|
||||
private MultivaluedHashMap<String, String> attributes = new MultivaluedHashMap<>();
|
||||
private boolean attributesChanged;
|
||||
private Set<String> requiredActions = new HashSet<>();
|
||||
private boolean requiredActionsChanged;
|
||||
private List<UserCredentialValueModel> credentials = new LinkedList<>();
|
||||
private boolean credentialsChanged;
|
||||
|
||||
public void rememberState() {
|
||||
original = new UserData();
|
||||
original.id = id;
|
||||
original.username = username;
|
||||
original.createdTimestamp = createdTimestamp;
|
||||
original.firstName = firstName;
|
||||
original.lastName = lastName;
|
||||
original.email = email;
|
||||
original.emailVerified = emailVerified;
|
||||
original.totp = totp;
|
||||
original.enabled = enabled;
|
||||
original.attributes.putAll(attributes);
|
||||
original.requiredActions.addAll(requiredActions);
|
||||
original.credentials.addAll(credentials);
|
||||
}
|
||||
|
||||
private UserData original = null;
|
||||
|
||||
public void clearChangeFlags() {
|
||||
original = null;
|
||||
idChanged = false;
|
||||
usernameChanged = false;
|
||||
createdTimestampChanged = false;
|
||||
firstNameChanged = false;
|
||||
lastNameChanged = false;
|
||||
emailChanged = false;
|
||||
emailVerifiedChanged = false;
|
||||
totpChanged = false;
|
||||
enabledChanged = false;
|
||||
rolesChanged = false;
|
||||
groupsChanged = false;
|
||||
attributesChanged = false;
|
||||
requiredActionsChanged = false;
|
||||
credentialsChanged = false;
|
||||
}
|
||||
|
||||
public boolean isChanged() {
|
||||
return !idChanged
|
||||
&& !usernameChanged
|
||||
&& !createdTimestampChanged
|
||||
&& !firstNameChanged
|
||||
&& !lastNameChanged
|
||||
&& !emailChanged
|
||||
&& !emailVerifiedChanged
|
||||
&& !totpChanged
|
||||
&& !enabledChanged
|
||||
&& !rolesChanged
|
||||
&& !groupsChanged
|
||||
&& !attributesChanged
|
||||
&& !requiredActionsChanged
|
||||
&& !credentialsChanged;
|
||||
}
|
||||
|
||||
public boolean isIdChanged() {
|
||||
return idChanged;
|
||||
}
|
||||
|
||||
public boolean isUsernameChanged() {
|
||||
return usernameChanged;
|
||||
}
|
||||
|
||||
public boolean isCreatedTimestampChanged() {
|
||||
return createdTimestampChanged;
|
||||
}
|
||||
|
||||
public boolean isFirstNameChanged() {
|
||||
return firstNameChanged;
|
||||
}
|
||||
|
||||
public boolean isLastNameChanged() {
|
||||
return lastNameChanged;
|
||||
}
|
||||
|
||||
public boolean isEmailChanged() {
|
||||
return emailChanged;
|
||||
}
|
||||
|
||||
public boolean isEmailVerifiedChanged() {
|
||||
return emailVerifiedChanged;
|
||||
}
|
||||
|
||||
public boolean isTotpChanged() {
|
||||
return totpChanged;
|
||||
}
|
||||
|
||||
public boolean isEnabledChanged() {
|
||||
return enabledChanged;
|
||||
}
|
||||
|
||||
public boolean isRolesChanged() {
|
||||
return rolesChanged;
|
||||
}
|
||||
|
||||
public boolean isGroupsChanged() {
|
||||
return groupsChanged;
|
||||
}
|
||||
|
||||
public boolean isAttributesChanged() {
|
||||
return attributesChanged;
|
||||
}
|
||||
|
||||
public boolean isRequiredActionsChanged() {
|
||||
return requiredActionsChanged;
|
||||
}
|
||||
|
||||
public boolean isCredentialsChanged() {
|
||||
return credentialsChanged;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
idChanged = true;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
usernameChanged = true;
|
||||
}
|
||||
|
||||
public Long getCreatedTimestamp() {
|
||||
return createdTimestamp;
|
||||
}
|
||||
|
||||
public void setCreatedTimestamp(Long timestamp) {
|
||||
this.createdTimestamp = timestamp;
|
||||
createdTimestampChanged = true;
|
||||
}
|
||||
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
firstNameChanged = true;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
lastNameChanged = true;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
emailChanged = true;
|
||||
}
|
||||
|
||||
public boolean isEmailVerified() {
|
||||
return emailVerified;
|
||||
}
|
||||
|
||||
public void setEmailVerified(boolean emailVerified) {
|
||||
this.emailVerified = emailVerified;
|
||||
emailVerifiedChanged = true;
|
||||
}
|
||||
|
||||
public boolean isTotp() {
|
||||
return totp;
|
||||
}
|
||||
|
||||
public void setTotp(boolean totp) {
|
||||
this.totp = totp;
|
||||
totpChanged = true;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
enabledChanged = true;
|
||||
}
|
||||
|
||||
public Set<String> getRoleMappings() {
|
||||
return Collections.unmodifiableSet(roleIds);
|
||||
}
|
||||
|
||||
public void grantRole(String roleId) {
|
||||
if (roleIds.contains(roleId)) return;
|
||||
roleIds.add(roleId);
|
||||
rolesChanged = true;
|
||||
}
|
||||
|
||||
public void deleteRoleMapping(String roleId) {
|
||||
if (!roleIds.contains(roleId)) return;
|
||||
roleIds.remove(roleId);
|
||||
rolesChanged = true;
|
||||
}
|
||||
|
||||
public MultivaluedHashMap<String, String> getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
public void setSingleAttribute(String name, String value) {
|
||||
attributes.putSingle(name, value);
|
||||
attributesChanged = true;
|
||||
|
||||
}
|
||||
public void setAttribute(String name, List<String> values) {
|
||||
attributes.put(name, values);
|
||||
attributesChanged = true;
|
||||
}
|
||||
public void removeAttribute(String name) {
|
||||
attributes.remove(name);
|
||||
attributesChanged = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Set<String> getRequiredActions() {
|
||||
return Collections.unmodifiableSet(requiredActions);
|
||||
}
|
||||
public void addRequiredAction(String action) {
|
||||
if (requiredActions.contains(action)) return;
|
||||
requiredActions.add(action);
|
||||
requiredActionsChanged = true;
|
||||
}
|
||||
public void removeRequiredAction(String action) {
|
||||
if (!requiredActions.contains(action)) return;
|
||||
requiredActions.remove(action);
|
||||
requiredActionsChanged = true;
|
||||
}
|
||||
|
||||
public List<UserCredentialValueModel> getCredentials() {
|
||||
return Collections.unmodifiableList(credentials);
|
||||
}
|
||||
|
||||
public void removeCredentialType(String type) {
|
||||
Iterator<UserCredentialValueModel> it = credentials.iterator();
|
||||
while (it.hasNext()) {
|
||||
if (it.next().getType().equals(type)) {
|
||||
it.remove();
|
||||
credentialsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void removeCredentialDevice(String type, String device) {
|
||||
Iterator<UserCredentialValueModel> it = credentials.iterator();
|
||||
while (it.hasNext()) {
|
||||
UserCredentialValueModel next = it.next();
|
||||
if (next.getType().equals(type) && next.getDevice().equals(device)) {
|
||||
it.remove();
|
||||
credentialsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setCredential(UserCredentialValueModel cred) {
|
||||
removeCredentialType(cred.getType());
|
||||
addCredential(cred);
|
||||
}
|
||||
public void addCredential(UserCredentialValueModel cred) {
|
||||
credentials.add(cred);
|
||||
credentialsChanged = true;
|
||||
}
|
||||
|
||||
public Set<String> getGroupIds() {
|
||||
return Collections.unmodifiableSet(groupIds);
|
||||
}
|
||||
|
||||
public void joinGroup(String groupId) {
|
||||
if (groupIds.contains(groupId)) return;
|
||||
groupIds.add(groupId);
|
||||
groupsChanged = true;
|
||||
}
|
||||
|
||||
public void leaveGroup(String groupId) {
|
||||
if (!groupIds.contains(groupId)) return;
|
||||
groupIds.remove(groupId);
|
||||
groupsChanged = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) return true;
|
||||
|
||||
if (this.id == null) return false;
|
||||
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
AbstractIdentifiableEntity that = (AbstractIdentifiableEntity) o;
|
||||
|
||||
if (!getId().equals(that.getId())) return false;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id!=null ? id.hashCode() : super.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s [ id=%s ]", getClass().getSimpleName(), getId());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,340 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage.changeset;
|
||||
|
||||
import org.keycloak.common.util.Time;
|
||||
import org.keycloak.hash.PasswordHashManager;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.OTPPolicy;
|
||||
import org.keycloak.models.PasswordPolicy;
|
||||
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.utils.KeycloakModelUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
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 UserDataAdapter implements UserModel {
|
||||
protected UserData userData;
|
||||
protected RealmModel realm;
|
||||
protected KeycloakSession session;
|
||||
protected Set<String> managedCredentialTypes;
|
||||
protected List<UserCredentialModel> updatedManagedCredentials = new LinkedList<>();
|
||||
|
||||
public UserDataAdapter(KeycloakSession session, RealmModel realm, UserData userData) {
|
||||
this.session = session;
|
||||
this.realm = realm;
|
||||
this.userData = userData;
|
||||
this.userData.rememberState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return userData.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return userData.getUsername();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUsername(String username) {
|
||||
userData.setUsername(username);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getCreatedTimestamp() {
|
||||
return userData.getCreatedTimestamp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCreatedTimestamp(Long timestamp) {
|
||||
userData.setCreatedTimestamp(timestamp);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return userData.isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOtpEnabled() {
|
||||
return userData.isTotp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled) {
|
||||
userData.setEnabled(enabled);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSingleAttribute(String name, String value) {
|
||||
userData.setSingleAttribute(name, value);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String name, List<String> values) {
|
||||
userData.setAttribute(name, values);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(String name) {
|
||||
userData.removeAttribute(name);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFirstAttribute(String name) {
|
||||
return userData.getAttributes().getFirst(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAttribute(String name) {
|
||||
return userData.getAttributes().get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getAttributes() {
|
||||
return userData.getAttributes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getRequiredActions() {
|
||||
return userData.getRequiredActions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRequiredAction(String action) {
|
||||
userData.addRequiredAction(action);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRequiredAction(String action) {
|
||||
userData.removeRequiredAction(action);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRequiredAction(RequiredAction action) {
|
||||
userData.addRequiredAction(action.name());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRequiredAction(RequiredAction action) {
|
||||
userData.removeRequiredAction(action.name());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFirstName() {
|
||||
return userData.getFirstName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFirstName(String firstName) {
|
||||
userData.setFirstName(firstName);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLastName() {
|
||||
return userData.getLastName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastName(String lastName) {
|
||||
userData.setLastName(lastName);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEmail() {
|
||||
return userData.getEmail();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmail(String email) {
|
||||
userData.setEmail(email);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmailVerified() {
|
||||
return userData.isEmailVerified();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmailVerified(boolean verified) {
|
||||
userData.setEmailVerified(verified);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOtpEnabled(boolean totp) {
|
||||
userData.setTotp(totp);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCredential(UserCredentialModel cred) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserCredentialValueModel> getCredentialsDirectly() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCredentialDirectly(UserCredentialValueModel cred) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<GroupModel> getGroups() {
|
||||
Set<String> groups = userData.getGroupIds();
|
||||
Set<GroupModel> set = new HashSet<>();
|
||||
for (String id : groups) {
|
||||
GroupModel group = realm.getGroupById(id);
|
||||
if (group != null) set.add(group);
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void joinGroup(GroupModel group) {
|
||||
userData.joinGroup(group.getId());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leaveGroup(GroupModel group) {
|
||||
userData.leaveGroup(group.getId());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMemberOf(GroupModel group) {
|
||||
Set<GroupModel> roles = getGroups();
|
||||
return KeycloakModelUtils.isMember(roles, group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFederationLink() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFederationLink(String link) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServiceAccountClientLink() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setServiceAccountClientLink(String clientInternalId) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRealmRoleMappings() {
|
||||
Set<RoleModel> roleMappings = getRoleMappings();
|
||||
|
||||
Set<RoleModel> realmRoles = new HashSet<RoleModel>();
|
||||
for (RoleModel role : roleMappings) {
|
||||
RoleContainerModel container = role.getContainer();
|
||||
if (container instanceof RealmModel) {
|
||||
realmRoles.add(role);
|
||||
}
|
||||
}
|
||||
return realmRoles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getClientRoleMappings(ClientModel app) {
|
||||
Set<RoleModel> roleMappings = getRoleMappings();
|
||||
|
||||
Set<RoleModel> roles = new HashSet<RoleModel>();
|
||||
for (RoleModel role : roleMappings) {
|
||||
RoleContainerModel container = role.getContainer();
|
||||
if (container instanceof ClientModel) {
|
||||
ClientModel appModel = (ClientModel)container;
|
||||
if (appModel.getId().equals(app.getId())) {
|
||||
roles.add(role);
|
||||
}
|
||||
}
|
||||
}
|
||||
return roles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRole(RoleModel role) {
|
||||
Set<RoleModel> roles = getRoleMappings();
|
||||
return KeycloakModelUtils.hasRole(roles, role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void grantRole(RoleModel role) {
|
||||
userData.grantRole(role.getId());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRoleMappings() {
|
||||
Set<String> roles = userData.getRoleMappings();
|
||||
Set<RoleModel> set = new HashSet<>();
|
||||
for (String id : roles) {
|
||||
RoleModel role = realm.getRoleById(id);
|
||||
if (role != null) set.add(role);
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteRoleMapping(RoleModel role) {
|
||||
userData.deleteRoleMapping(role.getId());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage.changeset;
|
||||
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserDataCredentialValidator {
|
||||
boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, List<UserCredentialModel> input);
|
||||
boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, UserCredentialModel... input);
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage.changeset;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.entities.UserEntity;
|
||||
import org.keycloak.storage.StorageId;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserDataLookup {
|
||||
UserData getUserById(RealmModel realm, StorageId id);
|
||||
UserData getUserByUsername(RealmModel realm, String username);
|
||||
UserData getUserByEmail(RealmModel realm, String email);
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage.changeset;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.entities.UserEntity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserDataQuery {
|
||||
|
||||
// Service account is included for counts
|
||||
int getUsersCount(RealmModel realm);
|
||||
|
||||
List<UserData> getUsers(RealmModel realm);
|
||||
List<UserData> searchForUser(String search, RealmModel realm);
|
||||
List<UserData> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm);
|
||||
|
||||
List<UserData> getUsers(RealmModel realm, int firstResult, int maxResults);
|
||||
List<UserData> searchForUser(String search, RealmModel realm, int firstResult, int maxResults);
|
||||
List<UserData> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults);
|
||||
|
||||
|
||||
|
||||
// Searching by UserModel.attribute (not property)
|
||||
List<UserData> searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm);
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage.changeset;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.entities.UserEntity;
|
||||
import org.keycloak.storage.StorageId;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserDataStore {
|
||||
void updateUser(RealmModel realm, UserData user);
|
||||
void addUser(RealmModel realm, UserData user);
|
||||
boolean removeUser(RealmModel realm, StorageId store);
|
||||
}
|
341
server-spi/src/main/java/org/keycloak/storage/changeset/UserStorageManager.java
Executable file
341
server-spi/src/main/java/org/keycloak/storage/changeset/UserStorageManager.java
Executable file
|
@ -0,0 +1,341 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.storage.changeset;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.CredentialValidationOutput;
|
||||
import org.keycloak.models.FederatedIdentityModel;
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ModelException;
|
||||
import org.keycloak.models.ProtocolMapperModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserConsentModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserProvider;
|
||||
import org.keycloak.models.UserUpdateProvider;
|
||||
import org.keycloak.storage.StorageId;
|
||||
import org.keycloak.storage.StorageProvider;
|
||||
import org.keycloak.storage.StorageProviderFactory;
|
||||
import org.keycloak.storage.StorageProviderModel;
|
||||
import org.keycloak.storage.federated.UserFederatedStorageProvider;
|
||||
|
||||
import java.util.HashMap;
|
||||
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 UserStorageManager implements UserProvider {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(UserStorageManager.class);
|
||||
|
||||
protected KeycloakSession session;
|
||||
|
||||
// Set of already validated/proxied federation users during this session. Key is user ID
|
||||
private Map<String, UserModel> managedUsers = new HashMap<>();
|
||||
private UserProvider localStorage = null;
|
||||
|
||||
public UserStorageManager(KeycloakSession session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
protected UserProvider localStorage() {
|
||||
if (localStorage == null) {
|
||||
localStorage = session.getProvider(UserProvider.class);
|
||||
}
|
||||
return localStorage;
|
||||
}
|
||||
|
||||
protected List<StorageProviderModel> getStorageProviders(RealmModel realm) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected <T> T getFirstStorageProvider(RealmModel realm, Class<T> type) {
|
||||
for (StorageProviderModel model : getStorageProviders(realm)) {
|
||||
StorageProviderFactory factory = (StorageProviderFactory)session.getKeycloakSessionFactory().getProviderFactory(StorageProvider.class, model.getProviderName());
|
||||
if (factory.supports(type)) {
|
||||
return type.cast(factory.getInstance(session, model));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected <T> List<T> getStorageProviders(RealmModel realm, Class<T> type) {
|
||||
List<T> list = new LinkedList<>();
|
||||
for (StorageProviderModel model : getStorageProviders(realm)) {
|
||||
StorageProviderFactory factory = (StorageProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(StorageProvider.class, model.getProviderName());
|
||||
if (factory.supports(type)) {
|
||||
list.add(type.cast(factory.getInstance(session, model)));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions) {
|
||||
UserDataStore store = getFirstStorageProvider(realm, UserDataStore.class);
|
||||
if (store != null) {
|
||||
UserData data = new UserData();
|
||||
}
|
||||
return localStorage().addUser(realm, id, username.toLowerCase(), addDefaultRoles, addDefaultRequiredActions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel addUser(RealmModel realm, String username) {
|
||||
UserUpdateProvider registry = getFirstStorageProvider(realm, UserUpdateProvider.class);
|
||||
if (registry != null) {
|
||||
return registry.addUser(realm, username);
|
||||
}
|
||||
return localStorage().addUser(realm, username.toLowerCase());
|
||||
}
|
||||
|
||||
public StorageProvider getStorageProvider(StorageProviderModel model) {
|
||||
StorageProviderFactory factory = (StorageProviderFactory)session.getKeycloakSessionFactory().getProviderFactory(StorageProvider.class, model.getProviderName());
|
||||
return factory.getInstance(session, model);
|
||||
}
|
||||
|
||||
public StorageProvider getStorageProvider(String providerId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeUser(RealmModel realm, UserModel user) {
|
||||
StorageId storageId = new StorageId(user.getId());
|
||||
if (storageId.getProviderId() == null) {
|
||||
return localStorage().removeUser(realm, user);
|
||||
}
|
||||
UserUpdateProvider registry = (UserUpdateProvider)getStorageProvider(storageId.getProviderId());
|
||||
if (registry == null) {
|
||||
throw new ModelException("Could not resolve StorageProvider: " + storageId.getProviderId());
|
||||
}
|
||||
return registry.removeUser(realm, user);
|
||||
|
||||
}
|
||||
|
||||
public UserFederatedStorageProvider getFederatedStorage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel socialLink) {
|
||||
getFederatedStorage().addFederatedIdentity(realm, user, socialLink);
|
||||
}
|
||||
|
||||
public void updateFederatedIdentity(RealmModel realm, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel) {
|
||||
getFederatedStorage().updateFederatedIdentity(realm, federatedUser, federatedIdentityModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeFederatedIdentity(RealmModel realm, UserModel user, String socialProvider) {
|
||||
return getFederatedStorage().removeFederatedIdentity(realm, user, socialProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
|
||||
getFederatedStorage().addConsent(realm, user, consent);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserConsentModel getConsentByClient(RealmModel realm, UserModel user, String clientInternalId) {
|
||||
return getFederatedStorage().getConsentByClient(realm, user, clientInternalId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserConsentModel> getConsents(RealmModel realm, UserModel user) {
|
||||
return getFederatedStorage().getConsents(realm, user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
|
||||
getFederatedStorage().updateConsent(realm, user, consent);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean revokeConsentForClient(RealmModel realm, UserModel user, String clientInternalId) {
|
||||
return getFederatedStorage().revokeConsentForClient(realm, user, clientInternalId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserByFederatedIdentity(FederatedIdentityModel socialLink, RealmModel realm) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getServiceAccount(ClientModel client) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getUsers(RealmModel realm, boolean includeServiceAccounts) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults, boolean includeServiceAccounts) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void grantToAllUsers(RealmModel realm, RoleModel role) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, UserFederationProviderModel link) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, RoleModel role) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, GroupModel group) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, ClientModel client) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(ProtocolMapperModel protocolMapper) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, StorageProviderModel link) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CredentialValidationOutput validCredentials(KeycloakSession session, RealmModel realm, UserCredentialModel... input) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, List<UserCredentialModel> input) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, UserCredentialModel... input) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserById(String id, RealmModel realm) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserByUsername(String username, RealmModel realm) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserByEmail(String email, RealmModel realm) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUsersCount(RealmModel realm) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getUsers(RealmModel realm) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUser(String search, RealmModel realm) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm) {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage.federated;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class CredentialModel {
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage.federated;
|
||||
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserAttributeFederatedStorage {
|
||||
void setSingleAttribute(RealmModel realm, UserModel user, String name, String value);
|
||||
void setAttribute(RealmModel realm, UserModel user, String name, List<String> values);
|
||||
void removeAttribute(RealmModel realm, UserModel user, String name);
|
||||
MultivaluedHashMap<String, String> getAttributes(RealmModel realm, UserModel user);
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage.federated;
|
||||
|
||||
import org.keycloak.models.FederatedIdentityModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserBrokerLinkFederatedStorage {
|
||||
String getUserByFederatedIdentity(FederatedIdentityModel socialLink, RealmModel realm);
|
||||
public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel socialLink);
|
||||
public boolean removeFederatedIdentity(RealmModel realm, UserModel user, String socialProvider);
|
||||
void updateFederatedIdentity(RealmModel realm, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel);
|
||||
Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm);
|
||||
FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm);
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage.federated;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserConsentModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserConsentFederatedStorage {
|
||||
void addConsent(RealmModel realm, UserModel user, UserConsentModel consent);
|
||||
UserConsentModel getConsentByClient(RealmModel realm, UserModel user, String clientInternalId);
|
||||
List<UserConsentModel> getConsents(RealmModel realm, UserModel user);
|
||||
void updateConsent(RealmModel realm, UserModel user, UserConsentModel consent);
|
||||
boolean revokeConsentForClient(RealmModel realm, UserModel user, String clientInternalId);
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage.federated;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserCredentialValueModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserCredentialsFederatedStorage {
|
||||
void updateCredential(RealmModel realm, UserModel user, UserCredentialModel cred);
|
||||
void updateCredential(RealmModel realm, UserModel user, UserCredentialValueModel cred);
|
||||
void removeCredential(RealmModel realm, UserModel user, UserCredentialValueModel cred);
|
||||
List<UserCredentialValueModel> getCredentials(RealmModel realm, UserModel user);
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.storage.federated;
|
||||
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.ProtocolMapperModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.provider.Provider;
|
||||
import org.keycloak.storage.StorageProviderModel;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserFederatedStorageProvider extends Provider,
|
||||
UserAttributeFederatedStorage,
|
||||
UserBrokerLinkFederatedStorage,
|
||||
UserConsentFederatedStorage,
|
||||
UserCredentialsFederatedStorage,
|
||||
UserGroupMembershipFederatedStorage,
|
||||
UserRequiredActionsFederatedStorage,
|
||||
UserRoleMappingsFederatedStorage {
|
||||
|
||||
void preRemove(RealmModel realm);
|
||||
|
||||
void preRemove(RealmModel realm, UserFederationProviderModel link);
|
||||
|
||||
public void preRemove(RealmModel realm, GroupModel group);
|
||||
|
||||
void preRemove(RealmModel realm, RoleModel role);
|
||||
|
||||
void preRemove(RealmModel realm, ClientModel client);
|
||||
|
||||
void preRemove(ProtocolMapperModel protocolMapper);
|
||||
|
||||
void preRemove(RealmModel realm, UserModel user);
|
||||
|
||||
void preRemove(RealmModel realm, StorageProviderModel model);
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage.federated;
|
||||
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserFederatedStorageProviderFactory extends ProviderFactory<UserFederatedStorageProvider> {
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.storage.federated;
|
||||
|
||||
import org.keycloak.provider.Provider;
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
import org.keycloak.provider.Spi;
|
||||
import org.keycloak.storage.StorageProvider;
|
||||
import org.keycloak.storage.StorageProviderFactory;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class UserFederatedStorageProviderSpi implements Spi {
|
||||
|
||||
@Override
|
||||
public boolean isInternal() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "userFederatedStorage";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Provider> getProviderClass() {
|
||||
return UserFederatedStorageProvider.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends ProviderFactory> getProviderFactoryClass() {
|
||||
return UserFederatedStorageProviderFactory.class;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage.federated;
|
||||
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserGroupMembershipFederatedStorage {
|
||||
Set<GroupModel> getGroups(RealmModel realm, UserModel user);
|
||||
|
||||
void joinGroup(RealmModel realm,UserModel user, GroupModel group);
|
||||
|
||||
void leaveGroup(RealmModel realm,UserModel user, GroupModel group);
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage.federated;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserRequiredActionsFederatedStorage {
|
||||
Set<String> getRequiredActions(RealmModel realm, UserModel user);
|
||||
void addRequiredAction(RealmModel realm,UserModel user, String action);
|
||||
void removeRequiredAction(RealmModel realm,UserModel user, String action);
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage.federated;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserRoleMappingsFederatedStorage {
|
||||
|
||||
void grantRole(RealmModel realm,UserModel user, RoleModel role);
|
||||
|
||||
Set<RoleModel> getRoleMappings(RealmModel realm,UserModel user);
|
||||
|
||||
void deleteRoleMapping(RealmModel realm, UserModel user, RoleModel role);
|
||||
}
|
|
@ -16,6 +16,7 @@
|
|||
#
|
||||
|
||||
org.keycloak.models.UserFederationSpi
|
||||
org.keycloak.storage.federated.UserFederatedStorageProviderSpi
|
||||
org.keycloak.mappers.UserFederationMapperSpi
|
||||
org.keycloak.models.RealmSpi
|
||||
org.keycloak.models.UserSessionSpi
|
||||
|
|
|
@ -319,7 +319,7 @@ public class ExportUtils {
|
|||
userRep.setFederationLink(user.getFederationLink());
|
||||
|
||||
// Grants
|
||||
List<UserConsentModel> consents = user.getConsents();
|
||||
List<UserConsentModel> consents = session.users().getConsents(realm, user);
|
||||
LinkedList<UserConsentRepresentation> consentReps = new LinkedList<UserConsentRepresentation>();
|
||||
for (UserConsentModel consent : consents) {
|
||||
UserConsentRepresentation consentRep = ModelToRepresentation.toRepresentation(consent);
|
||||
|
|
|
@ -64,7 +64,7 @@ public class ApplicationsBean {
|
|||
MultivaluedHashMap<String, ClientRoleEntry> resourceRolesGranted = new MultivaluedHashMap<String, ClientRoleEntry>();
|
||||
List<String> claimsGranted = new LinkedList<String>();
|
||||
if (client.isConsentRequired()) {
|
||||
UserConsentModel consent = user.getConsentByClient(client.getId());
|
||||
UserConsentModel consent = session.users().getConsentByClient(realm, user, client.getId());
|
||||
|
||||
if (consent != null) {
|
||||
processRoles(consent.getGrantedRoles(), realmRolesGranted, resourceRolesGranted);
|
||||
|
|
|
@ -420,13 +420,13 @@ public class TokenEndpoint {
|
|||
throw new ErrorResponseException("unauthorized_client", "Client not enabled to retrieve service account", Response.Status.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
UserModel clientUser = session.users().getUserByServiceAccountClient(client);
|
||||
UserModel clientUser = session.users().getServiceAccount(client);
|
||||
|
||||
if (clientUser == null || client.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, ServiceAccountConstants.CLIENT_ID_PROTOCOL_MAPPER) == null) {
|
||||
// May need to handle bootstrap here as well
|
||||
logger.debugf("Service account user for client '%s' not found or default protocol mapper for service account not found. Creating now", client.getClientId());
|
||||
new ClientManager(new RealmManager(session)).enableServiceAccount(client);
|
||||
clientUser = session.users().getUserByServiceAccountClient(client);
|
||||
clientUser = session.users().getServiceAccount(client);
|
||||
}
|
||||
|
||||
String clientUsername = clientUser.getUsername();
|
||||
|
|
|
@ -22,6 +22,8 @@ import org.keycloak.models.cache.CacheUserProvider;
|
|||
import org.keycloak.provider.Provider;
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
import org.keycloak.scripting.ScriptingProvider;
|
||||
import org.keycloak.storage.UserStorageManager;
|
||||
import org.keycloak.storage.federated.UserFederatedStorageProvider;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
@ -36,6 +38,7 @@ public class DefaultKeycloakSession implements KeycloakSession {
|
|||
private final DefaultKeycloakTransactionManager transactionManager;
|
||||
private RealmProvider model;
|
||||
private UserProvider userModel;
|
||||
private UserStorageManager userStorageManager;
|
||||
private ScriptingProvider scriptingProvider;
|
||||
private UserSessionProvider sessionProvider;
|
||||
private UserFederationManager federationManager;
|
||||
|
@ -86,6 +89,22 @@ public class DefaultKeycloakSession implements KeycloakSession {
|
|||
return factory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserFederatedStorageProvider userFederatedStorage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserProvider userLocalStorage() {
|
||||
return getProvider(UserProvider.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserProvider userStorageManager() {
|
||||
if (userStorageManager == null) userStorageManager = new UserStorageManager(this);
|
||||
return userStorageManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserProvider userStorage() {
|
||||
if (userModel == null) {
|
||||
|
|
|
@ -443,7 +443,7 @@ public class AuthenticationManager {
|
|||
|
||||
if (client.isConsentRequired()) {
|
||||
|
||||
UserConsentModel grantedConsent = user.getConsentByClient(client.getId());
|
||||
UserConsentModel grantedConsent = session.users().getConsentByClient(realm, user, client.getId());
|
||||
|
||||
ClientSessionCode accessCode = new ClientSessionCode(realm, clientSession);
|
||||
for (RoleModel r : accessCode.getRequestedRoles()) {
|
||||
|
@ -497,7 +497,7 @@ public class AuthenticationManager {
|
|||
|
||||
if (client.isConsentRequired()) {
|
||||
|
||||
UserConsentModel grantedConsent = user.getConsentByClient(client.getId());
|
||||
UserConsentModel grantedConsent = session.users().getConsentByClient(realm, user, client.getId());
|
||||
|
||||
List<RoleModel> realmRoles = new LinkedList<>();
|
||||
MultivaluedMap<String, RoleModel> resourceRoles = new MultivaluedMapImpl<>();
|
||||
|
|
|
@ -102,7 +102,7 @@ public class ClientManager {
|
|||
sessionsPersister.onClientRemoved(realm, client);
|
||||
}
|
||||
|
||||
UserModel serviceAccountUser = realmManager.getSession().users().getUserByServiceAccountClient(client);
|
||||
UserModel serviceAccountUser = realmManager.getSession().users().getServiceAccount(client);
|
||||
if (serviceAccountUser != null) {
|
||||
new UserManager(realmManager.getSession()).removeUser(realm, serviceAccountUser);
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ public class ClientManager {
|
|||
client.setServiceAccountsEnabled(true);
|
||||
|
||||
// Add dedicated user for this service account
|
||||
if (realmManager.getSession().users().getUserByServiceAccountClient(client) == null) {
|
||||
if (realmManager.getSession().users().getServiceAccount(client) == null) {
|
||||
String username = ServiceAccountConstants.SERVICE_ACCOUNT_USER_PREFIX + client.getClientId();
|
||||
logger.debugf("Creating service account user '%s'", username);
|
||||
|
||||
|
|
|
@ -500,7 +500,7 @@ public class AccountService extends AbstractSecuredLocalService {
|
|||
|
||||
// Revoke grant in UserModel
|
||||
UserModel user = auth.getUser();
|
||||
user.revokeConsentForClient(client.getId());
|
||||
session.users().revokeConsentForClient(realm, user, client.getId());
|
||||
new UserSessionManager(session).revokeOfflineToken(user, client);
|
||||
|
||||
// Logout clientSessions for this user and client
|
||||
|
|
|
@ -667,10 +667,10 @@ public class LoginActionsService {
|
|||
return response;
|
||||
}
|
||||
|
||||
UserConsentModel grantedConsent = user.getConsentByClient(client.getId());
|
||||
UserConsentModel grantedConsent = session.users().getConsentByClient(realm, user, client.getId());
|
||||
if (grantedConsent == null) {
|
||||
grantedConsent = new UserConsentModel(client);
|
||||
user.addConsent(grantedConsent);
|
||||
session.users().addConsent(realm, user, grantedConsent);
|
||||
}
|
||||
for (RoleModel role : accessCode.getRequestedRoles()) {
|
||||
grantedConsent.addGrantedRole(role);
|
||||
|
@ -680,7 +680,7 @@ public class LoginActionsService {
|
|||
grantedConsent.addGrantedProtocolMapper(protocolMapper);
|
||||
}
|
||||
}
|
||||
user.updateConsent(grantedConsent);
|
||||
session.users().updateConsent(realm, user, grantedConsent);
|
||||
|
||||
event.detail(Details.CONSENT, Details.CONSENT_VALUE_CONSENT_GRANTED);
|
||||
event.success();
|
||||
|
|
|
@ -304,11 +304,11 @@ public class ClientResource {
|
|||
throw new NotFoundException("Could not find client");
|
||||
}
|
||||
|
||||
UserModel user = session.users().getUserByServiceAccountClient(client);
|
||||
UserModel user = session.users().getServiceAccount(client);
|
||||
if (user == null) {
|
||||
if (client.isServiceAccountsEnabled()) {
|
||||
new ClientManager(new RealmManager(session)).enableServiceAccount(client);
|
||||
user = session.users().getUserByServiceAccountClient(client);
|
||||
user = session.users().getServiceAccount(client);
|
||||
} else {
|
||||
throw new BadRequestException("Service account not enabled for the client '" + client.getClientId() + "'");
|
||||
}
|
||||
|
|
|
@ -527,7 +527,7 @@ public class UsersResource {
|
|||
Set<ClientModel> offlineClients = new UserSessionManager(session).findClientsWithOfflineToken(realm, user);
|
||||
|
||||
for (ClientModel client : realm.getClients()) {
|
||||
UserConsentModel consent = user.getConsentByClient(client.getId());
|
||||
UserConsentModel consent = session.users().getConsentByClient(realm, user, client.getId());
|
||||
boolean hasOfflineToken = offlineClients.contains(client);
|
||||
|
||||
if (consent == null && !hasOfflineToken) {
|
||||
|
@ -576,7 +576,7 @@ public class UsersResource {
|
|||
}
|
||||
|
||||
ClientModel client = realm.getClientByClientId(clientId);
|
||||
boolean revokedConsent = user.revokeConsentForClient(client.getId());
|
||||
boolean revokedConsent = session.users().revokeConsentForClient(realm, user, client.getId());
|
||||
boolean revokedOfflineToken = new UserSessionManager(session).revokeOfflineToken(user, client);
|
||||
|
||||
if (revokedConsent) {
|
||||
|
|
|
@ -351,15 +351,15 @@ public class ImportTest extends AbstractModelTest {
|
|||
|
||||
// Test user consents
|
||||
admin = session.users().getUserByUsername("admin", realm);
|
||||
Assert.assertEquals(2, admin.getConsents().size());
|
||||
Assert.assertEquals(2, session.users().getConsents(realm, admin).size());
|
||||
|
||||
UserConsentModel appAdminConsent = admin.getConsentByClient(application.getId());
|
||||
UserConsentModel appAdminConsent = session.users().getConsentByClient(realm, admin, application.getId());
|
||||
Assert.assertEquals(2, appAdminConsent.getGrantedRoles().size());
|
||||
Assert.assertTrue(appAdminConsent.getGrantedProtocolMappers() == null || appAdminConsent.getGrantedProtocolMappers().isEmpty());
|
||||
Assert.assertTrue(appAdminConsent.isRoleGranted(realm.getRole("admin")));
|
||||
Assert.assertTrue(appAdminConsent.isRoleGranted(application.getRole("app-admin")));
|
||||
|
||||
UserConsentModel otherAppAdminConsent = admin.getConsentByClient(otherApp.getId());
|
||||
UserConsentModel otherAppAdminConsent = session.users().getConsentByClient(realm, admin, otherApp.getId());
|
||||
Assert.assertEquals(1, otherAppAdminConsent.getGrantedRoles().size());
|
||||
Assert.assertEquals(1, otherAppAdminConsent.getGrantedProtocolMappers().size());
|
||||
Assert.assertTrue(otherAppAdminConsent.isRoleGranted(realm.getRole("admin")));
|
||||
|
@ -376,8 +376,8 @@ public class ImportTest extends AbstractModelTest {
|
|||
// Test service accounts
|
||||
Assert.assertFalse(application.isServiceAccountsEnabled());
|
||||
Assert.assertTrue(otherApp.isServiceAccountsEnabled());
|
||||
Assert.assertNull(session.users().getUserByServiceAccountClient(application));
|
||||
UserModel linked = session.users().getUserByServiceAccountClient(otherApp);
|
||||
Assert.assertNull(session.users().getServiceAccount(application));
|
||||
UserModel linked = session.users().getServiceAccount(otherApp);
|
||||
Assert.assertNotNull(linked);
|
||||
Assert.assertEquals("my-service-user", linked.getUsername());
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ public class UserConsentModelTest extends AbstractModelTest {
|
|||
johnFooGrant.addGrantedRole(realmRole);
|
||||
johnFooGrant.addGrantedRole(barClientRole);
|
||||
johnFooGrant.addGrantedProtocolMapper(fooMapper);
|
||||
john.addConsent(johnFooGrant);
|
||||
realmManager.getSession().users().addConsent(realm, john, johnFooGrant);
|
||||
|
||||
UserConsentModel johnBarGrant = new UserConsentModel(barClient);
|
||||
johnBarGrant.addGrantedProtocolMapper(barMapper);
|
||||
|
@ -75,17 +75,17 @@ public class UserConsentModelTest extends AbstractModelTest {
|
|||
|
||||
// Update should fail as grant doesn't yet exists
|
||||
try {
|
||||
john.updateConsent(johnBarGrant);
|
||||
realmManager.getSession().users().updateConsent(realm, john, johnBarGrant);
|
||||
Assert.fail("Not expected to end here");
|
||||
} catch (ModelException expected) {
|
||||
}
|
||||
|
||||
john.addConsent(johnBarGrant);
|
||||
realmManager.getSession().users().addConsent(realm, john, johnBarGrant);
|
||||
|
||||
UserConsentModel maryFooGrant = new UserConsentModel(fooClient);
|
||||
maryFooGrant.addGrantedRole(realmRole);
|
||||
maryFooGrant.addGrantedProtocolMapper(fooMapper);
|
||||
mary.addConsent(maryFooGrant);
|
||||
realmManager.getSession().users().addConsent(realm, mary, maryFooGrant);
|
||||
|
||||
commit();
|
||||
}
|
||||
|
@ -99,27 +99,27 @@ public class UserConsentModelTest extends AbstractModelTest {
|
|||
UserModel john = session.users().getUserByUsername("john", realm);
|
||||
UserModel mary = session.users().getUserByUsername("mary", realm);
|
||||
|
||||
UserConsentModel johnFooConsent = john.getConsentByClient(fooClient.getId());
|
||||
UserConsentModel johnFooConsent = realmManager.getSession().users().getConsentByClient(realm, john, fooClient.getId());
|
||||
Assert.assertEquals(johnFooConsent.getGrantedRoles().size(), 2);
|
||||
Assert.assertEquals(johnFooConsent.getGrantedProtocolMappers().size(), 1);
|
||||
Assert.assertTrue(isRoleGranted(realm, "realm-role", johnFooConsent));
|
||||
Assert.assertTrue(isRoleGranted(barClient, "bar-client-role", johnFooConsent));
|
||||
Assert.assertTrue(isMapperGranted(fooClient, "foo", johnFooConsent));
|
||||
|
||||
UserConsentModel johnBarConsent = john.getConsentByClient(barClient.getId());
|
||||
UserConsentModel johnBarConsent = realmManager.getSession().users().getConsentByClient(realm, john, barClient.getId());
|
||||
Assert.assertEquals(johnBarConsent.getGrantedRoles().size(), 1);
|
||||
Assert.assertEquals(johnBarConsent.getGrantedProtocolMappers().size(), 1);
|
||||
Assert.assertTrue(isRoleGranted(realm, "realm-role", johnBarConsent));
|
||||
Assert.assertTrue(isMapperGranted(barClient, "bar", johnBarConsent));
|
||||
|
||||
UserConsentModel maryConsent = mary.getConsentByClient(fooClient.getId());
|
||||
UserConsentModel maryConsent = realmManager.getSession().users().getConsentByClient(realm, mary, fooClient.getId());
|
||||
Assert.assertEquals(maryConsent.getGrantedRoles().size(), 1);
|
||||
Assert.assertEquals(maryConsent.getGrantedProtocolMappers().size(), 1);
|
||||
Assert.assertTrue(isRoleGranted(realm, "realm-role", maryConsent));
|
||||
Assert.assertFalse(isRoleGranted(barClient, "bar-client-role", maryConsent));
|
||||
Assert.assertTrue(isMapperGranted(fooClient, "foo", maryConsent));
|
||||
|
||||
Assert.assertNull(mary.getConsentByClient(barClient.getId()));
|
||||
Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, mary, barClient.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -130,10 +130,10 @@ public class UserConsentModelTest extends AbstractModelTest {
|
|||
UserModel john = session.users().getUserByUsername("john", realm);
|
||||
UserModel mary = session.users().getUserByUsername("mary", realm);
|
||||
|
||||
List<UserConsentModel> johnConsents = john.getConsents();
|
||||
List<UserConsentModel> johnConsents = realmManager.getSession().users().getConsents(realm, john);
|
||||
Assert.assertEquals(2, johnConsents.size());
|
||||
|
||||
List<UserConsentModel> maryConsents = mary.getConsents();
|
||||
List<UserConsentModel> maryConsents = realmManager.getSession().users().getConsents(realm, mary);
|
||||
Assert.assertEquals(1, maryConsents.size());
|
||||
UserConsentModel maryConsent = maryConsents.get(0);
|
||||
Assert.assertEquals(maryConsent.getClient().getId(), fooClient.getId());
|
||||
|
@ -149,7 +149,7 @@ public class UserConsentModelTest extends AbstractModelTest {
|
|||
ClientModel fooClient = realm.getClientByClientId("foo-client");
|
||||
UserModel john = session.users().getUserByUsername("john", realm);
|
||||
|
||||
UserConsentModel johnConsent = john.getConsentByClient(fooClient.getId());
|
||||
UserConsentModel johnConsent = realmManager.getSession().users().getConsentByClient(realm, john, fooClient.getId());
|
||||
|
||||
// Remove foo protocol mapper from johnConsent
|
||||
ProtocolMapperModel protMapperModel = fooClient.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, "foo");
|
||||
|
@ -162,14 +162,14 @@ public class UserConsentModelTest extends AbstractModelTest {
|
|||
RoleModel newRealmRole = realm.addRole("new-realm-role");
|
||||
johnConsent.addGrantedRole(newRealmRole);
|
||||
|
||||
john.updateConsent(johnConsent);
|
||||
realmManager.getSession().users().updateConsent(realm, john, johnConsent);
|
||||
|
||||
commit();
|
||||
|
||||
realm = realmManager.getRealm("original");
|
||||
fooClient = realm.getClientByClientId("foo-client");
|
||||
john = session.users().getUserByUsername("john", realm);
|
||||
johnConsent = john.getConsentByClient(fooClient.getId());
|
||||
johnConsent = realmManager.getSession().users().getConsentByClient(realm, john, fooClient.getId());
|
||||
|
||||
Assert.assertEquals(johnConsent.getGrantedRoles().size(), 2);
|
||||
Assert.assertEquals(johnConsent.getGrantedProtocolMappers().size(), 0);
|
||||
|
@ -184,13 +184,13 @@ public class UserConsentModelTest extends AbstractModelTest {
|
|||
ClientModel fooClient = realm.getClientByClientId("foo-client");
|
||||
UserModel john = session.users().getUserByUsername("john", realm);
|
||||
|
||||
john.revokeConsentForClient(fooClient.getId());
|
||||
realmManager.getSession().users().revokeConsentForClient(realm, john, fooClient.getId());
|
||||
|
||||
commit();
|
||||
|
||||
realm = realmManager.getRealm("original");
|
||||
john = session.users().getUserByUsername("john", realm);
|
||||
Assert.assertNull(john.getConsentByClient(fooClient.getId()));
|
||||
Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john, fooClient.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -213,7 +213,7 @@ public class UserConsentModelTest extends AbstractModelTest {
|
|||
realm = realmManager.getRealm("original");
|
||||
fooClient = realm.getClientByClientId("foo-client");
|
||||
UserModel john = session.users().getUserByUsername("john", realm);
|
||||
UserConsentModel johnConsent = john.getConsentByClient(fooClient.getId());
|
||||
UserConsentModel johnConsent = realmManager.getSession().users().getConsentByClient(realm, john, fooClient.getId());
|
||||
|
||||
Assert.assertEquals(johnConsent.getGrantedRoles().size(), 2);
|
||||
Assert.assertEquals(johnConsent.getGrantedProtocolMappers().size(), 0);
|
||||
|
@ -232,7 +232,7 @@ public class UserConsentModelTest extends AbstractModelTest {
|
|||
ClientModel fooClient = realm.getClientByClientId("foo-client");
|
||||
ClientModel barClient = realm.getClientByClientId("bar-client");
|
||||
UserModel john = session.users().getUserByUsername("john", realm);
|
||||
UserConsentModel johnConsent = john.getConsentByClient(fooClient.getId());
|
||||
UserConsentModel johnConsent = realmManager.getSession().users().getConsentByClient(realm, john, fooClient.getId());
|
||||
|
||||
Assert.assertEquals(johnConsent.getGrantedRoles().size(), 1);
|
||||
Assert.assertEquals(johnConsent.getGrantedProtocolMappers().size(), 1);
|
||||
|
@ -254,13 +254,13 @@ public class UserConsentModelTest extends AbstractModelTest {
|
|||
|
||||
UserModel john = session.users().getUserByUsername("john", realm);
|
||||
|
||||
UserConsentModel johnFooConsent = john.getConsentByClient(fooClient.getId());
|
||||
UserConsentModel johnFooConsent = realmManager.getSession().users().getConsentByClient(realm, john, fooClient.getId());
|
||||
Assert.assertEquals(johnFooConsent.getGrantedRoles().size(), 1);
|
||||
Assert.assertEquals(johnFooConsent.getGrantedProtocolMappers().size(), 1);
|
||||
Assert.assertTrue(isRoleGranted(realm, "realm-role", johnFooConsent));
|
||||
Assert.assertTrue(isMapperGranted(fooClient, "foo", johnFooConsent));
|
||||
|
||||
Assert.assertNull(john.getConsentByClient(barClient.getId()));
|
||||
Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john, barClient.getId()));
|
||||
}
|
||||
|
||||
private boolean isRoleGranted(RoleContainerModel roleContainer, String roleName, UserConsentModel consentModel) {
|
||||
|
|
|
@ -271,7 +271,7 @@ public class UserModelTest extends AbstractModelTest {
|
|||
user2.setLastName("Doe");
|
||||
|
||||
// Search
|
||||
Assert.assertNull(session.users().getUserByServiceAccountClient(client));
|
||||
Assert.assertNull(session.users().getServiceAccount(client));
|
||||
List<UserModel> users = session.users().searchForUser("John Doe", realm);
|
||||
Assert.assertEquals(2, users.size());
|
||||
Assert.assertTrue(users.contains(user1));
|
||||
|
@ -284,7 +284,7 @@ public class UserModelTest extends AbstractModelTest {
|
|||
|
||||
// Search and assert service account user not found
|
||||
realm = realmManager.getRealmByName("original");
|
||||
UserModel searched = session.users().getUserByServiceAccountClient(client);
|
||||
UserModel searched = session.users().getServiceAccount(client);
|
||||
Assert.assertEquals(searched, user1);
|
||||
users = session.users().searchForUser("John Doe", realm);
|
||||
Assert.assertEquals(1, users.size());
|
||||
|
|
Loading…
Reference in a new issue