remove realm UserFed SPI methods

This commit is contained in:
Bill Burke 2016-11-23 08:31:20 -05:00
parent 2da9986717
commit d5925b8ccf
47 changed files with 223 additions and 3114 deletions

View file

@ -172,9 +172,6 @@ public interface RealmResource {
@Path("attack-detection")
AttackDetectionResource attackDetection();
@Path("user-federation")
UserFederationProvidersResource userFederation();
@Path("testLDAPConnection")
@GET
@NoCache

View file

@ -634,38 +634,6 @@ public class RealmAdapter implements CachedRealmModel {
updated.removeIdentityProviderByAlias(alias);
}
@Override
public List<UserFederationProviderModel> getUserFederationProviders() {
if (isUpdated()) return updated.getUserFederationProviders();
return cached.getUserFederationProviders();
}
@Override
public void setUserFederationProviders(List<UserFederationProviderModel> providers) {
getDelegateForUpdate();
updated.setUserFederationProviders(providers);
}
@Override
public UserFederationProviderModel addUserFederationProvider(String providerName, Map<String, String> config, int priority, String displayName, int fullSyncPeriod, int changedSyncPeriod, int lastSync) {
getDelegateForUpdate();
return updated.addUserFederationProvider(providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync);
}
@Override
public void removeUserFederationProvider(UserFederationProviderModel provider) {
getDelegateForUpdate();
updated.removeUserFederationProvider(provider);
}
@Override
public void updateUserFederationProvider(UserFederationProviderModel provider) {
getDelegateForUpdate();
updated.updateUserFederationProvider(provider);
}
@Override
public String getLoginTheme() {
if (isUpdated()) return updated.getLoginTheme();
@ -952,63 +920,6 @@ public class RealmAdapter implements CachedRealmModel {
return null;
}
@Override
public Set<UserFederationMapperModel> getUserFederationMappers() {
if (isUpdated()) return updated.getUserFederationMappers();
return cached.getUserFederationMapperSet();
}
@Override
public Set<UserFederationMapperModel> getUserFederationMappersByFederationProvider(String federationProviderId) {
if (isUpdated()) return updated.getUserFederationMappersByFederationProvider(federationProviderId);
Set<UserFederationMapperModel> mappers = new HashSet<>();
List<UserFederationMapperModel> list = cached.getUserFederationMappers().getList(federationProviderId);
for (UserFederationMapperModel entity : list) {
mappers.add(entity);
}
return Collections.unmodifiableSet(mappers);
}
@Override
public UserFederationMapperModel addUserFederationMapper(UserFederationMapperModel mapper) {
getDelegateForUpdate();
return updated.addUserFederationMapper(mapper);
}
@Override
public void removeUserFederationMapper(UserFederationMapperModel mapper) {
getDelegateForUpdate();
updated.removeUserFederationMapper(mapper);
}
@Override
public void updateUserFederationMapper(UserFederationMapperModel mapper) {
getDelegateForUpdate();
updated.updateUserFederationMapper(mapper);
}
@Override
public UserFederationMapperModel getUserFederationMapperById(String id) {
if (isUpdated()) return updated.getUserFederationMapperById(id);
for (List<UserFederationMapperModel> models : cached.getUserFederationMappers().values()) {
for (UserFederationMapperModel model : models) {
if (model.getId().equals(id)) return model;
}
}
return null;
}
@Override
public UserFederationMapperModel getUserFederationMapperByName(String federationProviderId, String name) {
if (isUpdated()) return updated.getUserFederationMapperByName(federationProviderId, name);
List<UserFederationMapperModel> models = cached.getUserFederationMappers().getList(federationProviderId);
if (models == null) return null;
for (UserFederationMapperModel model : models) {
if (model.getName().equals(name)) return model;
}
return null;
}
@Override
public AuthenticationFlowModel getBrowserFlow() {
if (isUpdated()) return updated.getBrowserFlow();

View file

@ -300,7 +300,7 @@ public class UserCacheSession implements UserCache {
// its also hard to test stuff
boolean invalidate = false;
if (policy != null) {
String currentTime = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(new Date(Time.currentTimeMillis()));
//String currentTime = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(new Date(Time.currentTimeMillis()));
if (policy == UserStorageProviderModel.CachePolicy.NO_CACHE) {
invalidate = true;
} else if (cached.getCacheTimestamp() < model.getCacheInvalidBefore()) {
@ -317,8 +317,8 @@ public class UserCacheSession implements UserCache {
int oneWeek = 7 * 24 * 60 * 60 * 1000;
long weeklyTimeout = weeklyTimeout(model.getEvictionDay(), model.getEvictionHour(), model.getEvictionMinute());
long lastTimeout = weeklyTimeout - oneWeek;
String timeout = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(new Date(weeklyTimeout));
String stamp = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(new Date(cached.getCacheTimestamp()));
//String timeout = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(new Date(weeklyTimeout));
//String stamp = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(new Date(cached.getCacheTimestamp()));
if (cached.getCacheTimestamp() <= lastTimeout) {
invalidate = true;
}

View file

@ -33,8 +33,6 @@ import org.keycloak.models.PasswordPolicy;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredActionProviderModel;
import org.keycloak.models.RequiredCredentialModel;
import org.keycloak.models.UserFederationMapperModel;
import org.keycloak.models.UserFederationProviderModel;
import java.security.PrivateKey;
import java.security.PublicKey;
@ -96,12 +94,9 @@ public class CachedRealm extends AbstractExtendableRevisioned {
protected String masterAdminClient;
protected List<RequiredCredentialModel> requiredCredentials;
protected List<UserFederationProviderModel> userFederationProviders;
protected MultivaluedHashMap<String, ComponentModel> componentsByParent = new MultivaluedHashMap<>();
protected MultivaluedHashMap<String, ComponentModel> componentsByParentAndType = new MultivaluedHashMap<>();
protected Map<String, ComponentModel> components = new HashMap<>();
protected MultivaluedHashMap<String, UserFederationMapperModel> userFederationMappers = new MultivaluedHashMap<String, UserFederationMapperModel>();
protected Set<UserFederationMapperModel> userFederationMapperSet;
protected List<IdentityProviderModel> identityProviders;
protected Map<String, String> browserSecurityHeaders;
@ -187,11 +182,6 @@ public class CachedRealm extends AbstractExtendableRevisioned {
emailTheme = model.getEmailTheme();
requiredCredentials = model.getRequiredCredentials();
userFederationProviders = model.getUserFederationProviders();
userFederationMapperSet = model.getUserFederationMappers();
for (UserFederationMapperModel mapper : userFederationMapperSet) {
this.userFederationMappers.add(mapper.getFederationProviderId(), mapper);
}
this.identityProviders = new ArrayList<>();
@ -462,14 +452,6 @@ public class CachedRealm extends AbstractExtendableRevisioned {
return adminEventsDetailsEnabled;
}
public List<UserFederationProviderModel> getUserFederationProviders() {
return userFederationProviders;
}
public MultivaluedHashMap<String, UserFederationMapperModel> getUserFederationMappers() {
return userFederationMappers;
}
public List<IdentityProviderModel> getIdentityProviders() {
return identityProviders;
}
@ -546,10 +528,6 @@ public class CachedRealm extends AbstractExtendableRevisioned {
return clientTemplates;
}
public Set<UserFederationMapperModel> getUserFederationMapperSet() {
return userFederationMapperSet;
}
public List<AuthenticationFlowModel> getAuthenticationFlowList() {
return authenticationFlowList;
}

View file

@ -734,194 +734,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 List<UserFederationProviderModel> getUserFederationProviders() {
List<UserFederationProviderEntity> entities = realm.getUserFederationProviders();
if (entities.isEmpty()) return Collections.EMPTY_LIST;
List<UserFederationProviderEntity> copy = new ArrayList<UserFederationProviderEntity>();
for (UserFederationProviderEntity entity : entities) {
copy.add(entity);
}
Collections.sort(copy, new Comparator<UserFederationProviderEntity>() {
@Override
public int compare(UserFederationProviderEntity o1, UserFederationProviderEntity o2) {
return o1.getPriority() - o2.getPriority();
}
});
List<UserFederationProviderModel> result = new ArrayList<UserFederationProviderModel>();
for (UserFederationProviderEntity entity : copy) {
result.add(new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
}
return Collections.unmodifiableList(result);
}
@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());
String id = KeycloakModelUtils.generateId();
UserFederationProviderEntity entity = new UserFederationProviderEntity();
entity.setId(id);
entity.setRealm(realm);
entity.setProviderName(providerName);
entity.setConfig(config);
entity.setPriority(priority);
if (displayName == null) {
displayName = id;
}
entity.setDisplayName(displayName);
entity.setFullSyncPeriod(fullSyncPeriod);
entity.setChangedSyncPeriod(changedSyncPeriod);
entity.setLastSync(lastSync);
em.persist(entity);
realm.getUserFederationProviders().add(entity);
em.flush();
UserFederationProviderModel providerModel = new UserFederationProviderModel(entity.getId(), providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync);
session.getKeycloakSessionFactory().publish(new UserFederationProviderCreationEventImpl(this, providerModel));
return providerModel;
}
@Override
public void removeUserFederationProvider(UserFederationProviderModel provider) {
Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
while (it.hasNext()) {
UserFederationProviderEntity entity = it.next();
if (entity.getId().equals(provider.getId())) {
session.users().preRemove(this, provider);
removeFederationMappersForProvider(provider.getId());
it.remove();
em.remove(entity);
return;
}
}
}
@Override
public void updateUserFederationProvider(UserFederationProviderModel model) {
KeycloakModelUtils.ensureUniqueDisplayName(model.getDisplayName(), model, getUserFederationProviders());
Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
while (it.hasNext()) {
UserFederationProviderEntity 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());
entity.setFullSyncPeriod(model.getFullSyncPeriod());
entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
entity.setLastSync(model.getLastSync());
break;
}
}
}
@Override
public void setUserFederationProviders(List<UserFederationProviderModel> providers) {
for (UserFederationProviderModel currentProvider : providers) {
KeycloakModelUtils.ensureUniqueDisplayName(currentProvider.getDisplayName(), currentProvider, providers);
}
Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
while (it.hasNext()) {
UserFederationProviderEntity entity = it.next();
boolean found = false;
for (UserFederationProviderModel 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);
}
entity.setFullSyncPeriod(model.getFullSyncPeriod());
entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
entity.setLastSync(model.getLastSync());
found = true;
break;
}
}
if (found) continue;
session.users().preRemove(this, new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
removeFederationMappersForProvider(entity.getId());
it.remove();
em.remove(entity);
}
List<UserFederationProviderModel> add = new LinkedList<>();
for (UserFederationProviderModel model : providers) {
boolean found = false;
for (UserFederationProviderEntity entity : realm.getUserFederationProviders()) {
if (entity.getId().equals(model.getId())) {
found = true;
break;
}
}
if (!found) add.add(model);
}
for (UserFederationProviderModel model : add) {
UserFederationProviderEntity entity = new UserFederationProviderEntity();
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.setFullSyncPeriod(model.getFullSyncPeriod());
entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
entity.setLastSync(model.getLastSync());
entity.setRealm(realm);
em.persist(entity);
realm.getUserFederationProviders().add(entity);
session.getKeycloakSessionFactory().publish(new UserFederationProviderCreationEventImpl(this, model));
}
}
protected UserFederationProviderEntity getUserFederationProviderEntityById(String federationProviderId) {
for (UserFederationProviderEntity entity : realm.getUserFederationProviders()) {
if (entity.getId().equals(federationProviderId)) {
return entity;
}
}
return null;
}
@Override
public RoleModel getRole(String name) {
return session.realms().getRealmRole(this, name);
@ -1402,118 +1214,6 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
return mapping;
}
@Override
public Set<UserFederationMapperModel> getUserFederationMappers() {
Collection<UserFederationMapperEntity> entities = this.realm.getUserFederationMappers();
if (entities.isEmpty()) return Collections.EMPTY_SET;
Set<UserFederationMapperModel> mappers = new HashSet<>();
for (UserFederationMapperEntity entity : entities) {
UserFederationMapperModel mapper = entityToModel(entity);
mappers.add(mapper);
}
return Collections.unmodifiableSet(mappers);
}
@Override
public Set<UserFederationMapperModel> getUserFederationMappersByFederationProvider(String federationProviderId) {
Set<UserFederationMapperEntity> mapperEntities = getUserFederationMapperEntitiesByFederationProvider(federationProviderId);
if (mapperEntities.isEmpty()) return Collections.EMPTY_SET;
Set<UserFederationMapperModel> mappers = new HashSet<UserFederationMapperModel>();
for (UserFederationMapperEntity entity : mapperEntities) {
UserFederationMapperModel mapper = entityToModel(entity);
mappers.add(mapper);
}
return Collections.unmodifiableSet(mappers);
}
@Override
public UserFederationMapperModel addUserFederationMapper(UserFederationMapperModel model) {
if (getUserFederationMapperByName(model.getFederationProviderId(), model.getName()) != null) {
throw new ModelDuplicateException("User federation mapper must be unique per federation provider. There is already: " + model.getName());
}
String id = KeycloakModelUtils.generateId();
UserFederationMapperEntity entity = new UserFederationMapperEntity();
entity.setId(id);
entity.setName(model.getName());
entity.setFederationProvider(getUserFederationProviderEntityById(model.getFederationProviderId()));
entity.setFederationMapperType(model.getFederationMapperType());
entity.setRealm(this.realm);
entity.setConfig(model.getConfig());
em.persist(entity);
this.realm.getUserFederationMappers().add(entity);
UserFederationMapperModel mapperModel = entityToModel(entity);
return mapperModel;
}
@Override
public void removeUserFederationMapper(UserFederationMapperModel mapper) {
UserFederationMapperEntity toDelete = getUserFederationMapperEntity(mapper.getId());
if (toDelete != null) {
this.realm.getUserFederationMappers().remove(toDelete);
em.remove(toDelete);
}
}
protected UserFederationMapperEntity getUserFederationMapperEntity(String id) {
for (UserFederationMapperEntity entity : this.realm.getUserFederationMappers()) {
if (entity.getId().equals(id)) {
return entity;
}
}
return null;
}
protected UserFederationMapperEntity getUserFederationMapperEntityByName(String federationProviderId, String name) {
for (UserFederationMapperEntity entity : this.realm.getUserFederationMappers()) {
if (federationProviderId.equals(entity.getFederationProvider().getId()) && entity.getName().equals(name)) {
return entity;
}
}
return null;
}
protected Set<UserFederationMapperEntity> getUserFederationMapperEntitiesByFederationProvider(String federationProviderId) {
Set<UserFederationMapperEntity> mappers = new HashSet<UserFederationMapperEntity>();
for (UserFederationMapperEntity entity : this.realm.getUserFederationMappers()) {
if (federationProviderId.equals(entity.getFederationProvider().getId())) {
mappers.add(entity);
}
}
return mappers;
}
@Override
public void updateUserFederationMapper(UserFederationMapperModel mapper) {
UserFederationMapperEntity entity = getUserFederationMapperEntity(mapper.getId());
entity.setFederationProvider(getUserFederationProviderEntityById(mapper.getFederationProviderId()));
entity.setFederationMapperType(mapper.getFederationMapperType());
if (entity.getConfig() == null) {
entity.setConfig(mapper.getConfig());
} else {
entity.getConfig().clear();
entity.getConfig().putAll(mapper.getConfig());
}
em.flush();
}
@Override
public UserFederationMapperModel getUserFederationMapperById(String id) {
UserFederationMapperEntity entity = getUserFederationMapperEntity(id);
if (entity == null) return null;
return entityToModel(entity);
}
@Override
public UserFederationMapperModel getUserFederationMapperByName(String federationProviderId, String name) {
UserFederationMapperEntity entity = getUserFederationMapperEntityByName(federationProviderId, name);
if (entity == null) return null;
return entityToModel(entity);
}
protected UserFederationMapperModel entityToModel(UserFederationMapperEntity entity) {
UserFederationMapperModel mapper = new UserFederationMapperModel();
mapper.setId(entity.getId());

View file

@ -869,183 +869,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 UserFederationProviderModel addUserFederationProvider(String providerName, Map<String, String> config, int priority, String displayName, int fullSyncPeriod, int changedSyncPeriod, int lastSync) {
KeycloakModelUtils.ensureUniqueDisplayName(displayName, null, getUserFederationProviders());
UserFederationProviderEntity entity = new UserFederationProviderEntity();
entity.setId(KeycloakModelUtils.generateId());
entity.setPriority(priority);
entity.setProviderName(providerName);
entity.setConfig(config);
if (displayName == null) {
displayName = entity.getId();
}
entity.setDisplayName(displayName);
entity.setFullSyncPeriod(fullSyncPeriod);
entity.setChangedSyncPeriod(changedSyncPeriod);
entity.setLastSync(lastSync);
realm.getUserFederationProviders().add(entity);
updateRealm();
UserFederationProviderModel providerModel = new UserFederationProviderModel(entity.getId(), providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync);
session.getKeycloakSessionFactory().publish(new UserFederationProviderCreationEventImpl(this, providerModel));
return providerModel;
}
@Override
public void removeUserFederationProvider(UserFederationProviderModel provider) {
Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
while (it.hasNext()) {
UserFederationProviderEntity entity = it.next();
if (entity.getId().equals(provider.getId())) {
session.users().preRemove(this, new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
removeFederationMappersForProvider(provider.getId());
it.remove();
}
}
updateRealm();
}
@Override
public void updateUserFederationProvider(UserFederationProviderModel model) {
KeycloakModelUtils.ensureUniqueDisplayName(model.getDisplayName(), model, getUserFederationProviders());
Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
while (it.hasNext()) {
UserFederationProviderEntity entity = it.next();
if (entity.getId().equals(model.getId())) {
entity.setProviderName(model.getProviderName());
entity.setConfig(model.getConfig());
entity.setPriority(model.getPriority());
String displayName = model.getDisplayName();
if (displayName != null) {
entity.setDisplayName(model.getDisplayName());
}
entity.setFullSyncPeriod(model.getFullSyncPeriod());
entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
entity.setLastSync(model.getLastSync());
}
}
updateRealm();
}
@Override
public List<UserFederationProviderModel> getUserFederationProviders() {
List<UserFederationProviderEntity> entities = realm.getUserFederationProviders();
if (entities.isEmpty()) return Collections.EMPTY_LIST;
List<UserFederationProviderEntity> copy = new LinkedList<UserFederationProviderEntity>();
for (UserFederationProviderEntity entity : entities) {
copy.add(entity);
}
Collections.sort(copy, new Comparator<UserFederationProviderEntity>() {
@Override
public int compare(UserFederationProviderEntity o1, UserFederationProviderEntity o2) {
return o1.getPriority() - o2.getPriority();
}
});
List<UserFederationProviderModel> result = new LinkedList<UserFederationProviderModel>();
for (UserFederationProviderEntity entity : copy) {
result.add(new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
}
return Collections.unmodifiableList(result);
}
@Override
public void setUserFederationProviders(List<UserFederationProviderModel> providers) {
for (UserFederationProviderModel currentProvider : providers) {
KeycloakModelUtils.ensureUniqueDisplayName(currentProvider.getDisplayName(), currentProvider, providers);
}
List<UserFederationProviderEntity> existingProviders = realm.getUserFederationProviders();
List<UserFederationProviderEntity> toRemove = new LinkedList<>();
for (UserFederationProviderEntity entity : existingProviders) {
boolean found = false;
for (UserFederationProviderModel 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);
}
entity.setFullSyncPeriod(model.getFullSyncPeriod());
entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
entity.setLastSync(model.getLastSync());
found = true;
break;
}
}
if (found) continue;
session.users().preRemove(this, new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
removeFederationMappersForProvider(entity.getId());
toRemove.add(entity);
}
for (UserFederationProviderEntity entity : toRemove) {
realm.getUserFederationProviders().remove(entity);
}
List<UserFederationProviderModel> add = new LinkedList<UserFederationProviderModel>();
for (UserFederationProviderModel model : providers) {
boolean found = false;
for (UserFederationProviderEntity entity : realm.getUserFederationProviders()) {
if (entity.getId().equals(model.getId())) {
found = true;
break;
}
}
if (!found) add.add(model);
}
for (UserFederationProviderModel model : add) {
UserFederationProviderEntity entity = new UserFederationProviderEntity();
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);
entity.setFullSyncPeriod(model.getFullSyncPeriod());
entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
entity.setLastSync(model.getLastSync());
realm.getUserFederationProviders().add(entity);
session.getKeycloakSessionFactory().publish(new UserFederationProviderCreationEventImpl(this, model));
}
updateRealm();
}
@Override
public boolean isEventsEnabled() {
return realm.isEventsEnabled();
@ -1760,131 +1583,6 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
return null;
}
@Override
public Set<UserFederationMapperModel> getUserFederationMappers() {
List<UserFederationMapperEntity> entities = getMongoEntity().getUserFederationMappers();
if (entities.isEmpty()) return Collections.EMPTY_SET;
Set<UserFederationMapperModel> mappers = new HashSet<UserFederationMapperModel>();
for (UserFederationMapperEntity entity : entities) {
UserFederationMapperModel mapper = entityToModel(entity);
mappers.add(mapper);
}
return Collections.unmodifiableSet(mappers);
}
@Override
public Set<UserFederationMapperModel> getUserFederationMappersByFederationProvider(String federationProviderId) {
Set<UserFederationMapperModel> mappers = new HashSet<UserFederationMapperModel>();
Set<UserFederationMapperEntity> mapperEntities = getUserFederationMapperEntitiesByFederationProvider(federationProviderId);
for (UserFederationMapperEntity entity : mapperEntities) {
mappers.add(entityToModel(entity));
}
return mappers;
}
@Override
public UserFederationMapperModel addUserFederationMapper(UserFederationMapperModel model) {
if (getUserFederationMapperByName(model.getFederationProviderId(), model.getName()) != null) {
throw new ModelDuplicateException("User federation mapper must be unique per federation provider. There is already: " + model.getName());
}
String id = KeycloakModelUtils.generateId();
UserFederationMapperEntity entity = new UserFederationMapperEntity();
entity.setId(id);
entity.setName(model.getName());
entity.setFederationProviderId(model.getFederationProviderId());
entity.setFederationMapperType(model.getFederationMapperType());
entity.setConfig(model.getConfig());
getMongoEntity().getUserFederationMappers().add(entity);
updateMongoEntity();
UserFederationMapperModel mapperModel = entityToModel(entity);
return mapperModel;
}
protected UserFederationMapperEntity getUserFederationMapperEntity(String id) {
for (UserFederationMapperEntity entity : getMongoEntity().getUserFederationMappers()) {
if (entity.getId().equals(id)) {
return entity;
}
}
return null;
}
protected UserFederationMapperEntity getUserFederationMapperEntityByName(String federationProviderId, String name) {
for (UserFederationMapperEntity entity : getMongoEntity().getUserFederationMappers()) {
if (entity.getFederationProviderId().equals(federationProviderId) && entity.getName().equals(name)) {
return entity;
}
}
return null;
}
protected Set<UserFederationMapperEntity> getUserFederationMapperEntitiesByFederationProvider(String federationProviderId) {
Set<UserFederationMapperEntity> mappers = new HashSet<UserFederationMapperEntity>();
for (UserFederationMapperEntity entity : getMongoEntity().getUserFederationMappers()) {
if (federationProviderId.equals(entity.getFederationProviderId())) {
mappers.add(entity);
}
}
return mappers;
}
@Override
public void removeUserFederationMapper(UserFederationMapperModel mapper) {
UserFederationMapperEntity toDelete = getUserFederationMapperEntity(mapper.getId());
if (toDelete != null) {
this.realm.getUserFederationMappers().remove(toDelete);
updateMongoEntity();
}
}
@Override
public void updateUserFederationMapper(UserFederationMapperModel mapper) {
UserFederationMapperEntity entity = getUserFederationMapperEntity(mapper.getId());
entity.setFederationProviderId(mapper.getFederationProviderId());
entity.setFederationMapperType(mapper.getFederationMapperType());
if (entity.getConfig() == null) {
entity.setConfig(mapper.getConfig());
} else {
entity.getConfig().clear();
entity.getConfig().putAll(mapper.getConfig());
}
updateMongoEntity();
}
@Override
public UserFederationMapperModel getUserFederationMapperById(String id) {
UserFederationMapperEntity entity = getUserFederationMapperEntity(id);
if (entity == null) return null;
return entityToModel(entity);
}
@Override
public UserFederationMapperModel getUserFederationMapperByName(String federationProviderId, String name) {
UserFederationMapperEntity entity = getUserFederationMapperEntityByName(federationProviderId, name);
if (entity == null) return null;
return entityToModel(entity);
}
protected UserFederationMapperModel entityToModel(UserFederationMapperEntity entity) {
UserFederationMapperModel mapper = new UserFederationMapperModel();
mapper.setId(entity.getId());
mapper.setName(entity.getName());
mapper.setFederationProviderId(entity.getFederationProviderId());
mapper.setFederationMapperType(entity.getFederationMapperType());
Map<String, String> config = new HashMap<String, String>();
if (entity.getConfig() != null) config.putAll(entity.getConfig());
mapper.setConfig(config);
return mapper;
}
@Override
public List<ClientTemplateModel> getClientTemplates() {
DBObject query = new QueryBuilder()

View file

@ -18,13 +18,6 @@
package org.keycloak.migration;
import org.jboss.logging.Logger;
import org.keycloak.migration.migrators.MigrateTo1_2_0;
import org.keycloak.migration.migrators.MigrateTo1_3_0;
import org.keycloak.migration.migrators.MigrateTo1_4_0;
import org.keycloak.migration.migrators.MigrateTo1_5_0;
import org.keycloak.migration.migrators.MigrateTo1_6_0;
import org.keycloak.migration.migrators.MigrateTo1_7_0;
import org.keycloak.migration.migrators.MigrateTo1_8_0;
import org.keycloak.migration.migrators.MigrateTo1_9_0;
import org.keycloak.migration.migrators.MigrateTo1_9_2;
import org.keycloak.migration.migrators.MigrateTo2_0_0;
@ -42,13 +35,6 @@ public class MigrationModelManager {
private static Logger logger = Logger.getLogger(MigrationModelManager.class);
private static final Migration[] migrations = {
new MigrateTo1_2_0(),
new MigrateTo1_3_0(),
new MigrateTo1_4_0(),
new MigrateTo1_5_0(),
new MigrateTo1_6_0(),
new MigrateTo1_7_0(),
new MigrateTo1_8_0(),
new MigrateTo1_9_0(),
new MigrateTo1_9_2(),
new MigrateTo2_0_0(),

View file

@ -1,99 +0,0 @@
/*
* 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.migration.migrators;
import org.keycloak.migration.ModelVersion;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationEventAwareProviderFactory;
import org.keycloak.models.UserFederationMapperModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderFactory;
import org.keycloak.models.UserFederationProviderModel;
import javax.naming.directory.SearchControls;
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 MigrateTo1_3_0 implements Migration {
public static final ModelVersion VERSION = new ModelVersion("1.3.0");
public ModelVersion getVersion() {
return VERSION;
}
public void migrate(KeycloakSession session) {
List<RealmModel> realms = session.realms().getRealms();
for (RealmModel realm : realms) {
migrateLDAPProviders(session, realm);
}
}
private void migrateLDAPProviders(KeycloakSession session, RealmModel realm) {
List<UserFederationProviderModel> federationProviders = realm.getUserFederationProviders();
for (UserFederationProviderModel fedProvider : federationProviders) {
if (fedProvider.getProviderName().equals(LDAPConstants.LDAP_PROVIDER)) {
Map<String, String> config = fedProvider.getConfig();
// Update config properties for LDAP federated provider
if (config.get(LDAPConstants.SEARCH_SCOPE) == null) {
config.put(LDAPConstants.SEARCH_SCOPE, String.valueOf(SearchControls.SUBTREE_SCOPE));
}
String usersDn = config.remove("userDnSuffix");
if (usersDn != null && config.get(LDAPConstants.USERS_DN) == null) {
config.put(LDAPConstants.USERS_DN, usersDn);
}
String usernameLdapAttribute = config.get(LDAPConstants.USERNAME_LDAP_ATTRIBUTE);
if (usernameLdapAttribute != null && config.get(LDAPConstants.RDN_LDAP_ATTRIBUTE) == null) {
if (usernameLdapAttribute.equalsIgnoreCase(LDAPConstants.SAM_ACCOUNT_NAME)) {
config.put(LDAPConstants.RDN_LDAP_ATTRIBUTE, LDAPConstants.CN);
} else {
config.put(LDAPConstants.RDN_LDAP_ATTRIBUTE, usernameLdapAttribute);
}
}
if (config.get(LDAPConstants.UUID_LDAP_ATTRIBUTE) == null) {
String uuidAttrName = LDAPConstants.getUuidAttributeName(config.get(LDAPConstants.VENDOR));
config.put(LDAPConstants.UUID_LDAP_ATTRIBUTE, uuidAttrName);
}
realm.updateUserFederationProvider(fedProvider);
// Create default mappers for LDAP
Set<UserFederationMapperModel> mappers = realm.getUserFederationMappersByFederationProvider(fedProvider.getId());
if (mappers.isEmpty()) {
UserFederationProviderFactory ldapFactory = (UserFederationProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(UserFederationProvider.class, LDAPConstants.LDAP_PROVIDER);
if (ldapFactory != null) {
((UserFederationEventAwareProviderFactory) ldapFactory).onProviderModelCreated(realm, fedProvider);
}
}
}
}
}
}

View file

@ -1,79 +0,0 @@
/*
* 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.migration.migrators;
import org.keycloak.migration.ModelVersion;
import org.keycloak.models.ImpersonationConstants;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationMapperModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.DefaultAuthenticationFlows;
import org.keycloak.models.utils.DefaultRequiredActions;
import org.keycloak.models.utils.KeycloakModelUtils;
import java.util.Arrays;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class MigrateTo1_4_0 implements Migration {
public static final ModelVersion VERSION = new ModelVersion("1.4.0");
public ModelVersion getVersion() {
return VERSION;
}
public void migrate(KeycloakSession session) {
List<RealmModel> realms = session.realms().getRealms();
for (RealmModel realm : realms) {
if (realm.getAuthenticationFlows().size() == 0) {
DefaultAuthenticationFlows.migrateFlows(realm);
DefaultRequiredActions.addActions(realm);
}
ImpersonationConstants.setupImpersonationService(session, realm);
migrateLDAPMappers(session, realm);
migrateUsers(session, realm);
}
}
private void migrateLDAPMappers(KeycloakSession session, RealmModel realm) {
List<String> mandatoryInLdap = Arrays.asList("username", "username-cn", "first name", "last name");
for (UserFederationMapperModel ldapMapper : realm.getUserFederationMappers()) {
if (mandatoryInLdap.contains(ldapMapper.getName())) {
ldapMapper.getConfig().put("is.mandatory.in.ldap", "true");
realm.updateUserFederationMapper(ldapMapper);
}
}
}
private void migrateUsers(KeycloakSession session, RealmModel realm) {
List<UserModel> users = session.userStorage().getUsers(realm, false);
for (UserModel user : users) {
String email = user.getEmail();
email = KeycloakModelUtils.toLowerCaseSafe(email);
if (email != null && !email.equals(user.getEmail())) {
user.setEmail(email);
}
}
}
}

View file

@ -1,70 +0,0 @@
/*
* 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.migration.migrators;
import org.keycloak.migration.ModelVersion;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationMapperModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class MigrateTo1_8_0 implements Migration {
public static final ModelVersion VERSION = new ModelVersion("1.8.0");
public ModelVersion getVersion() {
return VERSION;
}
public void migrate(KeycloakSession session) {
List<RealmModel> realms = session.realms().getRealms();
for (RealmModel realm : realms) {
List<UserFederationProviderModel> federationProviders = realm.getUserFederationProviders();
for (UserFederationProviderModel fedProvider : federationProviders) {
if (fedProvider.getProviderName().equals(LDAPConstants.LDAP_PROVIDER)) {
Map<String, String> config = fedProvider.getConfig();
if (isActiveDirectory(config)) {
// Create mapper for MSAD account controls
if (realm.getUserFederationMapperByName(fedProvider.getId(), "MSAD account controls") == null) {
UserFederationMapperModel mapperModel = KeycloakModelUtils.createUserFederationMapperModel("MSAD account controls", fedProvider.getId(), LDAPConstants.MSAD_USER_ACCOUNT_CONTROL_MAPPER);
realm.addUserFederationMapper(mapperModel);
}
}
}
}
}
}
private boolean isActiveDirectory(Map<String, String> ldapConfig) {
String vendor = ldapConfig.get(LDAPConstants.VENDOR);
return vendor != null && vendor.equals(LDAPConstants.VENDOR_ACTIVE_DIRECTORY);
}
}

View file

@ -283,28 +283,6 @@ public final class KeycloakModelUtils {
}
public static UserFederationProviderModel findUserFederationProviderByDisplayName(String displayName, RealmModel realm) {
if (displayName == null) {
return null;
}
for (UserFederationProviderModel fedProvider : realm.getUserFederationProviders()) {
if (displayName.equals(fedProvider.getDisplayName())) {
return fedProvider;
}
}
return null;
}
public static UserFederationProviderModel findUserFederationProviderById(String fedProviderId, RealmModel realm) {
for (UserFederationProviderModel fedProvider : realm.getUserFederationProviders()) {
if (fedProviderId.equals(fedProvider.getId())) {
return fedProvider;
}
}
return null;
}
public static UserStorageProviderModel findUserStorageProviderByName(String displayName, RealmModel realm) {
if (displayName == null) {
return null;

View file

@ -352,8 +352,6 @@ public class ModelToRepresentation {
}
}
exportUserFederationProvidersAndMappers(realm, rep);
for (IdentityProviderModel provider : realm.getIdentityProviders()) {
rep.addIdentityProvider(toRepresentation(realm, provider));
}
@ -384,23 +382,7 @@ public class ModelToRepresentation {
return rep;
}
public static void exportUserFederationProvidersAndMappers(RealmModel realm, RealmRepresentation rep) {
List<UserFederationProviderModel> fedProviderModels = realm.getUserFederationProviders();
if (fedProviderModels.size() > 0) {
List<UserFederationProviderRepresentation> fedProviderReps = new ArrayList<UserFederationProviderRepresentation>();
for (UserFederationProviderModel model : fedProviderModels) {
UserFederationProviderRepresentation fedProvRep = toRepresentation(model);
fedProviderReps.add(fedProvRep);
}
rep.setUserFederationProviders(fedProviderReps);
}
for (UserFederationMapperModel mapper : realm.getUserFederationMappers()) {
rep.addUserFederationMapper(toRepresentation(realm, mapper));
}
}
public static void exportGroups(RealmModel realm, RealmRepresentation rep) {
public static void exportGroups(RealmModel realm, RealmRepresentation rep) {
List<GroupRepresentation> groups = toGroupHierarchy(realm, true);
rep.setGroups(groups);
}
@ -605,24 +587,6 @@ public class ModelToRepresentation {
return rep;
}
public static UserFederationMapperRepresentation toRepresentation(RealmModel realm, UserFederationMapperModel model) {
UserFederationMapperRepresentation rep = new UserFederationMapperRepresentation();
rep.setId(model.getId());
rep.setName(model.getName());
rep.setFederationMapperType(model.getFederationMapperType());
Map<String, String> config = new HashMap<String, String>();
config.putAll(model.getConfig());
rep.setConfig(config);
UserFederationProviderModel fedProvider = KeycloakModelUtils.findUserFederationProviderById(model.getFederationProviderId(), realm);
if (fedProvider == null) {
throw new ModelException("Couldn't find federation provider with ID " + model.getId());
}
rep.setFederationProviderDisplayName(fedProvider.getDisplayName());
return rep;
}
public static IdentityProviderRepresentation toRepresentation(RealmModel realm, IdentityProviderModel identityProviderModel) {
IdentityProviderRepresentation providerRep = new IdentityProviderRepresentation();

View file

@ -376,37 +376,14 @@ public class RepresentationToModel {
if (convertSet.contains(fedRep.getProviderName())) {
ComponentModel component = convertFedProviderToComponent(newRealm.getId(), fedRep);
userStorageModels.put(fedRep.getDisplayName(), newRealm.importComponentModel(component));
} else {
providerModels.add(convertFederationProvider(fedRep));
}
}
newRealm.setUserFederationProviders(providerModels);
}
// This is for case, when you have hand-written JSON file with LDAP userFederationProvider, but WITHOUT any userFederationMappers configured. Default LDAP mappers need to be created in that case.
Set<String> storageProvidersWhichShouldImportDefaultMappers = new HashSet<>(userStorageModels.keySet());
if (rep.getUserFederationMappers() != null) {
// Remove builtin mappers for federation providers, which have some mappers already provided in JSON (likely due to previous export)
if (rep.getUserFederationProviders() != null) {
Set<String> providerNames = new TreeSet<String>();
for (UserFederationMapperRepresentation representation : rep.getUserFederationMappers()) {
providerNames.add(representation.getFederationProviderDisplayName());
}
for (String providerName : providerNames) {
for (UserFederationProviderModel providerModel : providerModels) {
if (providerName.equals(providerModel.getDisplayName())) {
Set<UserFederationMapperModel> toDelete = newRealm.getUserFederationMappersByFederationProvider(providerModel.getId());
for (UserFederationMapperModel mapperModel : toDelete) {
newRealm.removeUserFederationMapper(mapperModel);
}
}
}
}
}
for (UserFederationMapperRepresentation representation : rep.getUserFederationMappers()) {
if (userStorageModels.containsKey(representation.getFederationProviderDisplayName())) {
ComponentModel parent = userStorageModels.get(representation.getFederationProviderDisplayName());
@ -417,8 +394,6 @@ public class RepresentationToModel {
storageProvidersWhichShouldImportDefaultMappers.remove(representation.getFederationProviderDisplayName());
} else {
newRealm.addUserFederationMapper(toModel(newRealm, representation));
}
}
}
@ -865,11 +840,6 @@ public class RepresentationToModel {
realm.setBrowserSecurityHeaders(rep.getBrowserSecurityHeaders());
}
if (rep.getUserFederationProviders() != null) {
List<UserFederationProviderModel> providerModels = convertFederationProviders(rep.getUserFederationProviders());
realm.setUserFederationProviders(providerModels);
}
if(rep.isInternationalizationEnabled() != null){
realm.setInternationalizationEnabled(rep.isInternationalizationEnabled());
}
@ -950,23 +920,6 @@ public class RepresentationToModel {
}
public static UserFederationMapperModel toModel(RealmModel realm, UserFederationMapperRepresentation rep) {
UserFederationMapperModel model = new UserFederationMapperModel();
model.setId(rep.getId());
model.setName(rep.getName());
model.setFederationMapperType(rep.getFederationMapperType());
model.setConfig(rep.getConfig());
UserFederationProviderModel fedProvider = KeycloakModelUtils.findUserFederationProviderByDisplayName(rep.getFederationProviderDisplayName(), realm);
if (fedProvider == null) {
throw new ModelException("Couldn't find federation provider with display name [" + rep.getFederationProviderDisplayName() + "] referenced from mapper ["
+ rep.getName());
}
model.setFederationProviderId(fedProvider.getId());
return model;
}
// Roles
public static void createRole(RealmModel newRealm, RoleRepresentation roleRep) {

View file

@ -117,7 +117,7 @@ public interface KeycloakSession {
*
* @return
*/
UserFederationManager users();
UserProvider users();
/**

View file

@ -310,21 +310,6 @@ public interface RealmModel extends RoleContainerModel {
return list;
}
// 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);
void setUserFederationProviders(List<UserFederationProviderModel> providers);
Set<UserFederationMapperModel> getUserFederationMappers();
Set<UserFederationMapperModel> getUserFederationMappersByFederationProvider(String federationProviderId);
UserFederationMapperModel addUserFederationMapper(UserFederationMapperModel mapper);
void removeUserFederationMapper(UserFederationMapperModel mapper);
void updateUserFederationMapper(UserFederationMapperModel mapper);
UserFederationMapperModel getUserFederationMapperById(String id);
UserFederationMapperModel getUserFederationMapperByName(String federationProviderId, String name);
String getLoginTheme();
void setLoginTheme(String name);

View file

@ -49,139 +49,23 @@ public class UserFederationManager implements UserProvider {
@Override
public UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions) {
UserModel user = session.userStorage().addUser(realm, id, username.toLowerCase(), addDefaultRoles, addDefaultRequiredActions);
return registerWithFederation(realm, user);
return user;
}
@Override
public UserModel addUser(RealmModel realm, String username) {
UserModel user = session.userStorage().addUser(realm, username.toLowerCase());
return registerWithFederation(realm, user);
}
protected UserModel registerWithFederation(RealmModel realm, UserModel user) {
for (UserFederationProviderModel federation : realm.getUserFederationProviders()) {
UserFederationProvider fed = getFederationProvider(federation);
if (fed.synchronizeRegistrations()) {
user.setFederationLink(federation.getId());
UserModel registered = fed.register(realm, user);
managedUsers.put(registered.getId(), registered);
return registered;
}
}
return user;
}
public UserFederationProvider getFederationProvider(UserFederationProviderModel model) {
UserFederationProviderFactory factory = (UserFederationProviderFactory)session.getKeycloakSessionFactory().getProviderFactory(UserFederationProvider.class, model.getProviderName());
return factory.getInstance(session, model);
}
public UserFederationProvider getFederationLink(RealmModel realm, UserModel user) {
if (user.getFederationLink() == null) return null;
for (UserFederationProviderModel fed : realm.getUserFederationProviders()) {
if (fed.getId().equals(user.getFederationLink())) {
return getFederationProvider(fed);
}
}
return null;
}
@Override
public boolean removeUser(RealmModel realm, UserModel user) {
UserFederationProvider link = getFederationLink(realm, user);
if (link != null) {
boolean fedRemoved = link.removeUser(realm, user);
if (fedRemoved) {
boolean localRemoved = session.userStorage().removeUser(realm, user);
managedUsers.remove(user.getId());
if (!localRemoved) {
logger.warn("User possibly removed from federation provider, but failed to remove him from keycloak model");
}
return localRemoved;
} else {
logger.warn("Failed to remove user from federation provider");
return false;
}
}
return session.userStorage().removeUser(realm, user);
return session.userStorage().removeUser(realm, user);
}
public void validateUser(RealmModel realm, UserModel user) {
if (managedUsers.containsKey(user.getId())) {
return;
}
UserFederationProvider link = getFederationLink(realm, user);
if (link != null && !link.isValid(realm, user)) {
deleteInvalidUser(realm, user);
throw new IllegalStateException("Federated user no longer valid");
}
}
protected void deleteInvalidUser(final RealmModel realm, final UserModel user) {
runJobInTransaction(session.getKeycloakSessionFactory(), new KeycloakSessionTask() {
@Override
public void run(KeycloakSession session) {
RealmModel realmModel = session.realms().getRealm(realm.getId());
if (realmModel == null) return;
UserModel deletedUser = session.userStorage().getUserById(user.getId(), realmModel);
new UserManager(session).removeUser(realmModel, deletedUser, session.userStorage());
logger.debugf("Removed invalid user '%s'", user.getUsername());
}
});
}
private static void runJobInTransaction(KeycloakSessionFactory factory, KeycloakSessionTask task) {
KeycloakSession session = factory.create();
KeycloakTransaction tx = session.getTransactionManager();
try {
tx.begin();
task.run(session);
if (tx.isActive()) {
if (tx.getRollbackOnly()) {
tx.rollback();
} else {
tx.commit();
}
}
} catch (RuntimeException re) {
if (tx.isActive()) {
tx.rollback();
}
throw re;
} finally {
session.close();
}
}
protected UserModel validateAndProxyUser(RealmModel realm, UserModel user) {
UserModel managed = managedUsers.get(user.getId());
if (managed != null) {
return managed;
}
UserFederationProvider link = getFederationLink(realm, user);
if (link != null) {
UserModel validatedProxyUser = link.validateAndProxy(realm, user);
if (validatedProxyUser != null) {
managedUsers.put(user.getId(), validatedProxyUser);
return validatedProxyUser;
} else {
deleteInvalidUser(realm, user);
return null;
}
}
return user;
}
@Override
public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel socialLink) {
validateUser(realm, user);
session.userStorage().addFederatedIdentity(realm, user, socialLink);
}
@ -191,7 +75,6 @@ public class UserFederationManager implements UserProvider {
@Override
public boolean removeFederatedIdentity(RealmModel realm, UserModel user, String socialProvider) {
validateUser(realm, user);
if (user == null) throw new IllegalStateException("Federated user no longer valid");
return session.userStorage().removeFederatedIdentity(realm, user, socialProvider);
}
@ -226,10 +109,7 @@ public class UserFederationManager implements UserProvider {
@Override
public UserModel getUserById(String id, RealmModel realm) {
UserModel user = session.userStorage().getUserById(id, realm);
if (user != null) {
user = validateAndProxyUser(realm, user);
}
return user;
return user;
}
@Override
@ -247,21 +127,7 @@ public class UserFederationManager implements UserProvider {
Set<UserModel> result = new LinkedHashSet<>(localMembers);
for (UserFederationProviderModel federation : realm.getUserFederationProviders()) {
if (result.size() >= maxTotal) {
break;
}
int max = maxTotal - result.size();
UserFederationProvider fed = getFederationProvider(federation);
List<UserModel> current = fed.getGroupMembers(realm, group, 0, max);
if (current != null) {
result.addAll(current);
}
}
if (result.size() <= firstResult) {
if (result.size() <= firstResult) {
return Collections.emptyList();
}
@ -277,48 +143,24 @@ public class UserFederationManager implements UserProvider {
@Override
public UserModel getUserByUsername(String username, RealmModel realm) {
UserModel user = session.userStorage().getUserByUsername(username.toLowerCase(), realm);
if (user != null) {
user = validateAndProxyUser(realm, user);
if (user != null) return user;
}
for (UserFederationProviderModel federation : realm.getUserFederationProviders()) {
UserFederationProvider fed = getFederationProvider(federation);
user = fed.getUserByUsername(realm, username);
if (user != null) return user;
}
return user;
}
@Override
public UserModel getUserByEmail(String email, RealmModel realm) {
UserModel user = session.userStorage().getUserByEmail(email.toLowerCase(), realm);
if (user != null) {
user = validateAndProxyUser(realm, user);
if (user != null) return user;
}
for (UserFederationProviderModel federation : realm.getUserFederationProviders()) {
UserFederationProvider fed = getFederationProvider(federation);
user = fed.getUserByEmail(realm, email);
if (user != null) return user;
}
return user;
return user;
}
@Override
public UserModel getUserByFederatedIdentity(FederatedIdentityModel socialLink, RealmModel realm) {
UserModel user = session.userStorage().getUserByFederatedIdentity(socialLink, realm);
if (user != null) {
user = validateAndProxyUser(realm, user);
}
return user;
}
@Override
public UserModel getServiceAccount(ClientModel client) {
UserModel user = session.userStorage().getServiceAccount(client);
if (user != null) {
user = validateAndProxyUser(client.getRealm(), user);
}
return user;
}
@ -357,8 +199,6 @@ public class UserFederationManager implements UserProvider {
if (query == null || query.size() == 0) return results;
int added = 0;
for (UserModel user : query) {
user = validateAndProxyUser(realm, user);
if (user == null) continue;
results.add(user);
added++;
}
@ -385,30 +225,8 @@ public class UserFederationManager implements UserProvider {
return searchForUser(search, realm, 0, Integer.MAX_VALUE - 1);
}
void federationLoad(RealmModel realm, Map<String, String> attributes) {
for (UserFederationProviderModel federation : realm.getUserFederationProviders()) {
UserFederationProvider fed = getFederationProvider(federation);
fed.searchByAttributes(attributes, realm, 30);
}
}
@Override
public List<UserModel> searchForUser(final String search, RealmModel realm, int firstResult, int maxResults) {
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());
}
federationLoad(realm, attributes);
return query(new PaginatedQuery() {
@Override
public List<UserModel> query(RealmModel realm, int first, int max) {
@ -424,7 +242,6 @@ public class UserFederationManager implements UserProvider {
@Override
public List<UserModel> searchForUser(final Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults) {
federationLoad(realm, attributes);
return query(new PaginatedQuery() {
@Override
public List<UserModel> query(RealmModel realm, int first, int max) {
@ -440,15 +257,11 @@ public class UserFederationManager implements UserProvider {
@Override
public Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm) {
validateUser(realm, user);
if (user == null) throw new IllegalStateException("Federated user no longer valid");
return session.userStorage().getFederatedIdentities(user, realm);
}
@Override
public FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm) {
validateUser(realm, user);
if (user == null) throw new IllegalStateException("Federated user no longer valid");
return session.userStorage().getFederatedIdentity(user, socialProvider, realm);
}
@ -460,10 +273,6 @@ public class UserFederationManager implements UserProvider {
@Override
public void preRemove(RealmModel realm) {
for (UserFederationProviderModel federation : realm.getUserFederationProviders()) {
UserFederationProvider fed = getFederationProvider(federation);
fed.preRemove(realm);
}
session.userStorage().preRemove(realm);
}
@ -474,20 +283,12 @@ public class UserFederationManager implements UserProvider {
@Override
public void preRemove(RealmModel realm, GroupModel group) {
for (UserFederationProviderModel federation : realm.getUserFederationProviders()) {
UserFederationProvider fed = getFederationProvider(federation);
fed.preRemove(realm, group);
}
session.userStorage().preRemove(realm, group);
}
@Override
public void preRemove(RealmModel realm, RoleModel role) {
for (UserFederationProviderModel federation : realm.getUserFederationProviders()) {
UserFederationProvider fed = getFederationProvider(federation);
fed.preRemove(realm, role);
}
session.userStorage().preRemove(realm, role);
}

View file

@ -20,9 +20,19 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
/**
* If your UserStorageProvider is importing users into local storage, you can validate that import whenever the
* user is queried from local storage.
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface ImportedUserValidation {
UserModel validate(RealmModel realmm, UserModel user);
/**
* If this method returns null, then the user storage in local storage will be removed
*
* @param realm
* @param user
* @return null if user no longer valid
*/
UserModel validate(RealmModel realm, UserModel user);
}

View file

@ -32,6 +32,7 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationManager;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserProvider;
import org.keycloak.representations.idm.authorization.ResourceOwnerRepresentation;
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
import org.keycloak.services.ErrorResponse;
@ -93,7 +94,7 @@ public class ResourceSetService {
if (!resourceServer.getClientId().equals(ownerId)) {
RealmModel realm = authorization.getRealm();
KeycloakSession keycloakSession = authorization.getKeycloakSession();
UserFederationManager users = keycloakSession.users();
UserProvider users = keycloakSession.users();
UserModel ownerModel = users.getUserById(ownerId, realm);
if (ownerModel == null) {

View file

@ -120,13 +120,7 @@ public class UserCredentialStoreManager implements UserCredentialManager, OnUser
}
}
} else {
// <deprecate>
UserFederationProvider link = session.users().getFederationLink(realm, user);
if (link != null) {
session.users().validateUser(realm, user);
validate(realm, user, toValidate, link);
} // </deprecate>
else if (user.getFederationLink() != null) {
if (user.getFederationLink() != null) {
UserStorageProvider provider = UserStorageManager.getStorageProvider(session, realm, user.getFederationLink());
if (provider != null && provider instanceof CredentialInputValidator) {
validate(realm, user, toValidate, ((CredentialInputValidator)provider));
@ -176,13 +170,7 @@ public class UserCredentialStoreManager implements UserCredentialManager, OnUser
}
}
} else {
// <deprecated>
UserFederationProvider link = session.users().getFederationLink(realm, user);
if (link != null) {
if (link.updateCredential(realm, user, input)) return;
}
// </deprecated>
else if (user.getFederationLink() != null) {
if (user.getFederationLink() != null) {
UserStorageProvider provider = UserStorageManager.getStorageProvider(session, realm, user.getFederationLink());
if (provider != null && provider instanceof CredentialInputUpdater) {
if (((CredentialInputUpdater)provider).updateCredential(realm, user, input)) return;
@ -209,11 +197,7 @@ public class UserCredentialStoreManager implements UserCredentialManager, OnUser
}
}
} else {
UserFederationProvider link = session.users().getFederationLink(realm, user);
if (link != null && link.getSupportedCredentialTypes().contains(credentialType)) {
link.disableCredentialType(realm, user, credentialType);
}
else if (user.getFederationLink() != null) {
if (user.getFederationLink() != null) {
UserStorageProvider provider = UserStorageManager.getStorageProvider(session, realm, user.getFederationLink());
if (provider != null && provider instanceof CredentialInputUpdater) {
((CredentialInputUpdater)provider).disableCredentialType(realm, user, credentialType);
@ -243,11 +227,7 @@ public class UserCredentialStoreManager implements UserCredentialManager, OnUser
types.addAll(updater.getDisableableCredentialTypes(realm, user));
}
} else {
UserFederationProvider link = session.users().getFederationLink(realm, user);
if (link != null) {
types.addAll(link.getDisableableCredentialTypes(realm, user));
}
else if (user.getFederationLink() != null) {
if (user.getFederationLink() != null) {
UserStorageProvider provider = UserStorageManager.getStorageProvider(session, realm, user.getFederationLink());
if (provider != null && provider instanceof CredentialInputUpdater) {
types.addAll(((CredentialInputUpdater)provider).getDisableableCredentialTypes(realm, user));
@ -275,13 +255,7 @@ public class UserCredentialStoreManager implements UserCredentialManager, OnUser
}
}
} else {
// <deprecate>
UserFederationProvider link = session.users().getFederationLink(realm, user);
if (link != null) {
if (link.isConfiguredFor(realm, user, type)) return true;
}
// </deprecate>
else if (user.getFederationLink() != null) {
if (user.getFederationLink() != null) {
UserStorageProvider provider = UserStorageManager.getStorageProvider(session, realm, user.getFederationLink());
if (provider != null && provider instanceof CredentialInputValidator) {
if (((CredentialInputValidator)provider).isConfiguredFor(realm, user, type)) return true;
@ -307,16 +281,6 @@ public class UserCredentialStoreManager implements UserCredentialManager, OnUser
@Override
public CredentialValidationOutput authenticate(KeycloakSession session, RealmModel realm, CredentialInput input) {
List<UserFederationProviderModel> fedProviderModels = realm.getUserFederationProviders();
List<UserFederationProvider> fedProviders = new ArrayList<UserFederationProvider>();
for (UserFederationProviderModel fedProviderModel : fedProviderModels) {
UserFederationProvider provider = session.users().getFederationProvider(fedProviderModel);
if (input instanceof UserCredentialModel && provider != null && provider.supportsCredentialType(input.getType())) {
CredentialValidationOutput output = provider.validCredentials(realm, (UserCredentialModel)input);
if (output != null) return output;
}
}
List<CredentialAuthentication> list = UserStorageManager.getStorageProviders(session, realm, CredentialAuthentication.class);
for (CredentialAuthentication auth : list) {
if (auth.supportsCredentialAuthenticationFor(input.getType())) {

View file

@ -46,6 +46,7 @@ import org.keycloak.models.RoleModel;
import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserFederationManager;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserProvider;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.ClientTemplateRepresentation;
@ -358,7 +359,7 @@ public class ExportUtils {
String users = config.get("users");
if (users != null && !users.isEmpty()) {
UserFederationManager userManager = session.users();
UserProvider userManager = session.users();
List<String> userIds = JsonSerialization.readValue(users, List.class);
config.put("users", JsonSerialization.writeValueAsString(userIds.stream().map(userId -> userManager.getUserById(userId, realm).getUsername()).collect(Collectors.toList())));
}

View file

@ -228,7 +228,6 @@ public class RealmManager implements RealmImporter {
}
public boolean removeRealm(RealmModel realm) {
List<UserFederationProviderModel> federationProviders = realm.getUserFederationProviders();
ClientModel masterAdminClient = realm.getMasterAdminClient();
boolean removed = model.removeRealm(realm.getId());
@ -247,11 +246,13 @@ public class RealmManager implements RealmImporter {
sessionsPersister.onRealmRemoved(realm);
}
// Remove all periodic syncs for configured federation providers
UsersSyncManager usersSyncManager = new UsersSyncManager();
for (final UserFederationProviderModel fedProvider : federationProviders) {
usersSyncManager.notifyToRefreshPeriodicSync(session, realm, fedProvider, true);
// Refresh periodic sync tasks for configured storageProviders
List<UserStorageProviderModel> storageProviders = realm.getUserStorageProviders();
UserStorageSyncManager storageSync = new UserStorageSyncManager();
for (UserStorageProviderModel provider : storageProviders) {
storageSync.notifyToRefreshPeriodicSync(session, realm, provider, true);
}
}
return removed;
}
@ -487,13 +488,6 @@ public class RealmManager implements RealmImporter {
setupAuthenticationFlows(realm);
setupRequiredActions(realm);
// Refresh periodic sync tasks for configured federationProviders
List<UserFederationProviderModel> federationProviders = realm.getUserFederationProviders();
UsersSyncManager usersSyncManager = new UsersSyncManager();
for (final UserFederationProviderModel fedProvider : federationProviders) {
usersSyncManager.notifyToRefreshPeriodicSync(session, realm, fedProvider, false);
}
// Refresh periodic sync tasks for configured storageProviders
List<UserStorageProviderModel> storageProviders = realm.getUserStorageProviders();
UserStorageSyncManager storageSync = new UserStorageSyncManager();

View file

@ -1,327 +0,0 @@
/*
* 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.services.managers;
import org.jboss.logging.Logger;
import org.keycloak.cluster.ClusterEvent;
import org.keycloak.cluster.ClusterListener;
import org.keycloak.cluster.ClusterProvider;
import org.keycloak.cluster.ExecutionResult;
import org.keycloak.common.util.Time;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.KeycloakSessionTask;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderFactory;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserFederationSyncResult;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.services.ServicesLogger;
import org.keycloak.timer.TimerProvider;
import java.util.List;
import java.util.concurrent.Callable;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class UsersSyncManager {
private static final String FEDERATION_TASK_KEY = "federation";
private static final Logger logger = Logger.getLogger(UsersSyncManager.class);
/**
* Check federationProviderModel of all realms and possibly start periodic sync for them
*
* @param sessionFactory
* @param timer
*/
public void bootstrapPeriodic(final KeycloakSessionFactory sessionFactory, final TimerProvider timer) {
KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
@Override
public void run(KeycloakSession session) {
List<RealmModel> realms = session.realms().getRealms();
for (final RealmModel realm : realms) {
List<UserFederationProviderModel> federationProviders = realm.getUserFederationProviders();
for (final UserFederationProviderModel fedProvider : federationProviders) {
refreshPeriodicSyncForProvider(sessionFactory, timer, fedProvider, realm.getId());
}
}
ClusterProvider clusterProvider = session.getProvider(ClusterProvider.class);
clusterProvider.registerListener(FEDERATION_TASK_KEY, new UserFederationClusterListener(sessionFactory));
}
});
}
private class Holder {
ExecutionResult<UserFederationSyncResult> result;
}
public UserFederationSyncResult syncAllUsers(final KeycloakSessionFactory sessionFactory, final String realmId, final UserFederationProviderModel fedProvider) {
final Holder holder = new Holder();
// Ensure not executed concurrently on this or any other cluster node
KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
@Override
public void run(KeycloakSession session) {
ClusterProvider clusterProvider = session.getProvider(ClusterProvider.class);
// shared key for "full" and "changed" . Improve if needed
String taskKey = fedProvider.getId() + "::sync";
// 30 seconds minimal timeout for now
int timeout = Math.max(30, fedProvider.getFullSyncPeriod());
holder.result = clusterProvider.executeIfNotExecuted(taskKey, timeout, new Callable<UserFederationSyncResult>() {
@Override
public UserFederationSyncResult call() throws Exception {
final UserFederationProviderFactory fedProviderFactory = (UserFederationProviderFactory) sessionFactory.getProviderFactory(UserFederationProvider.class, fedProvider.getProviderName());
updateLastSyncInterval(sessionFactory, fedProvider, realmId);
return fedProviderFactory.syncAllUsers(sessionFactory, realmId, fedProvider);
}
});
}
});
if (holder.result == null || !holder.result.isExecuted()) {
logger.debugf("syncAllUsers for federation provider %s was ignored as it's already in progress", fedProvider.getDisplayName());
return UserFederationSyncResult.ignored();
} else {
return holder.result.getResult();
}
}
public UserFederationSyncResult syncChangedUsers(final KeycloakSessionFactory sessionFactory, final String realmId, final UserFederationProviderModel fedProvider) {
final Holder holder = new Holder();
// Ensure not executed concurrently on this or any other cluster node
KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
@Override
public void run(KeycloakSession session) {
ClusterProvider clusterProvider = session.getProvider(ClusterProvider.class);
// shared key for "full" and "changed" . Improve if needed
String taskKey = fedProvider.getId() + "::sync";
// 30 seconds minimal timeout for now
int timeout = Math.max(30, fedProvider.getChangedSyncPeriod());
holder.result = clusterProvider.executeIfNotExecuted(taskKey, timeout, new Callable<UserFederationSyncResult>() {
@Override
public UserFederationSyncResult call() throws Exception {
final UserFederationProviderFactory fedProviderFactory = (UserFederationProviderFactory) sessionFactory.getProviderFactory(UserFederationProvider.class, fedProvider.getProviderName());
// See when we did last sync.
int oldLastSync = fedProvider.getLastSync();
updateLastSyncInterval(sessionFactory, fedProvider, realmId);
return fedProviderFactory.syncChangedUsers(sessionFactory, realmId, fedProvider, Time.toDate(oldLastSync));
}
});
}
});
if (holder.result == null || !holder.result.isExecuted()) {
logger.debugf("syncChangedUsers for federation provider %s was ignored as it's already in progress", fedProvider.getDisplayName());
return UserFederationSyncResult.ignored();
} else {
return holder.result.getResult();
}
}
// Ensure all cluster nodes are notified
public void notifyToRefreshPeriodicSync(KeycloakSession session, RealmModel realm, UserFederationProviderModel federationProvider, boolean removed) {
FederationProviderClusterEvent event = FederationProviderClusterEvent.createEvent(removed, realm.getId(), federationProvider);
session.getProvider(ClusterProvider.class).notify(FEDERATION_TASK_KEY, event, false);
}
// Executed once it receives notification that some UserFederationProvider was created or updated
protected void refreshPeriodicSyncForProvider(final KeycloakSessionFactory sessionFactory, TimerProvider timer, final UserFederationProviderModel fedProvider, final String realmId) {
logger.debugf("Going to refresh periodic sync for provider '%s' . Full sync period: %d , changed users sync period: %d",
fedProvider.getDisplayName(), fedProvider.getFullSyncPeriod(), fedProvider.getChangedSyncPeriod());
if (fedProvider.getFullSyncPeriod() > 0) {
// We want periodic full sync for this provider
timer.schedule(new Runnable() {
@Override
public void run() {
try {
boolean shouldPerformSync = shouldPerformNewPeriodicSync(fedProvider.getLastSync(), fedProvider.getChangedSyncPeriod());
if (shouldPerformSync) {
syncAllUsers(sessionFactory, realmId, fedProvider);
} else {
logger.debugf("Ignored periodic full sync with federation provider %s due small time since last sync", fedProvider.getDisplayName());
}
} catch (Throwable t) {
ServicesLogger.LOGGER.errorDuringFullUserSync(t);
}
}
}, fedProvider.getFullSyncPeriod() * 1000, fedProvider.getId() + "-FULL");
} else {
timer.cancelTask(fedProvider.getId() + "-FULL");
}
if (fedProvider.getChangedSyncPeriod() > 0) {
// We want periodic sync of just changed users for this provider
timer.schedule(new Runnable() {
@Override
public void run() {
try {
boolean shouldPerformSync = shouldPerformNewPeriodicSync(fedProvider.getLastSync(), fedProvider.getChangedSyncPeriod());
if (shouldPerformSync) {
syncChangedUsers(sessionFactory, realmId, fedProvider);
} else {
logger.debugf("Ignored periodic changed-users sync with federation provider %s due small time since last sync", fedProvider.getDisplayName());
}
} catch (Throwable t) {
ServicesLogger.LOGGER.errorDuringChangedUserSync(t);
}
}
}, fedProvider.getChangedSyncPeriod() * 1000, fedProvider.getId() + "-CHANGED");
} else {
timer.cancelTask(fedProvider.getId() + "-CHANGED");
}
}
// Skip syncing if there is short time since last sync time.
private boolean shouldPerformNewPeriodicSync(int lastSyncTime, int period) {
if (lastSyncTime <= 0) {
return true;
}
int currentTime = Time.currentTime();
int timeSinceLastSync = currentTime - lastSyncTime;
return (timeSinceLastSync * 2 > period);
}
// Executed once it receives notification that some UserFederationProvider was removed
protected void removePeriodicSyncForProvider(TimerProvider timer, UserFederationProviderModel fedProvider) {
logger.debugf("Removing periodic sync for provider %s", fedProvider.getDisplayName());
timer.cancelTask(fedProvider.getId() + "-FULL");
timer.cancelTask(fedProvider.getId() + "-CHANGED");
}
// Update interval of last sync for given UserFederationProviderModel. Do it in separate transaction
private void updateLastSyncInterval(final KeycloakSessionFactory sessionFactory, final UserFederationProviderModel fedProvider, final String realmId) {
KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
@Override
public void run(KeycloakSession session) {
RealmModel persistentRealm = session.realms().getRealm(realmId);
List<UserFederationProviderModel> persistentFedProviders = persistentRealm.getUserFederationProviders();
for (UserFederationProviderModel persistentFedProvider : persistentFedProviders) {
if (fedProvider.getId().equals(persistentFedProvider.getId())) {
// Update persistent provider in DB
int lastSync = Time.currentTime();
persistentFedProvider.setLastSync(lastSync);
persistentRealm.updateUserFederationProvider(persistentFedProvider);
// Update "cached" reference
fedProvider.setLastSync(lastSync);
}
}
}
});
}
private class UserFederationClusterListener implements ClusterListener {
private final KeycloakSessionFactory sessionFactory;
public UserFederationClusterListener(KeycloakSessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
@Override
public void eventReceived(ClusterEvent event) {
final FederationProviderClusterEvent fedEvent = (FederationProviderClusterEvent) event;
KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
@Override
public void run(KeycloakSession session) {
TimerProvider timer = session.getProvider(TimerProvider.class);
if (fedEvent.isRemoved()) {
removePeriodicSyncForProvider(timer, fedEvent.getFederationProvider());
} else {
refreshPeriodicSyncForProvider(sessionFactory, timer, fedEvent.getFederationProvider(), fedEvent.getRealmId());
}
}
});
}
}
// Send to cluster during each update or remove of federationProvider, so all nodes can update sync periods
public static class FederationProviderClusterEvent implements ClusterEvent {
private boolean removed;
private String realmId;
private UserFederationProviderModel federationProvider;
public boolean isRemoved() {
return removed;
}
public void setRemoved(boolean removed) {
this.removed = removed;
}
public String getRealmId() {
return realmId;
}
public void setRealmId(String realmId) {
this.realmId = realmId;
}
public UserFederationProviderModel getFederationProvider() {
return federationProvider;
}
public void setFederationProvider(UserFederationProviderModel federationProvider) {
this.federationProvider = federationProvider;
}
public static FederationProviderClusterEvent createEvent(boolean removed, String realmId, UserFederationProviderModel fedProvider) {
FederationProviderClusterEvent notification = new FederationProviderClusterEvent();
notification.setRemoved(removed);
notification.setRealmId(realmId);
notification.setFederationProvider(fedProvider);
return notification;
}
}
}

View file

@ -46,7 +46,6 @@ import org.keycloak.services.filters.KeycloakTransactionCommitter;
import org.keycloak.services.managers.ApplianceBootstrap;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.UserStorageSyncManager;
import org.keycloak.services.managers.UsersSyncManager;
import org.keycloak.services.resources.admin.AdminRoot;
import org.keycloak.services.scheduled.ClearExpiredEvents;
import org.keycloak.services.scheduled.ClearExpiredUserSessions;
@ -323,7 +322,6 @@ public class KeycloakApplication extends Application {
TimerProvider timer = session.getProvider(TimerProvider.class);
timer.schedule(new ClusterAwareScheduledTaskRunner(sessionFactory, new ClearExpiredEvents(), interval), interval, "ClearExpiredEvents");
timer.schedule(new ScheduledTaskRunner(sessionFactory, new ClearExpiredUserSessions()), interval, "ClearExpiredUserSessions");
new UsersSyncManager().bootstrapPeriodic(sessionFactory, timer);
new UserStorageSyncManager().bootstrapPeriodic(sessionFactory, timer);
} finally {
session.close();

View file

@ -42,7 +42,6 @@ import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.cache.CacheRealmProvider;
import org.keycloak.models.cache.UserCache;
@ -66,8 +65,9 @@ import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.LDAPConnectionTestManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.ResourceAdminManager;
import org.keycloak.services.managers.UsersSyncManager;
import org.keycloak.services.managers.UserStorageSyncManager;
import org.keycloak.services.resources.admin.RealmAuth.Resource;
import org.keycloak.storage.UserStorageProviderModel;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@ -304,9 +304,9 @@ public class RealmAdminResource {
RepresentationToModel.updateRealm(rep, realm, session);
// Refresh periodic sync tasks for configured federationProviders
List<UserFederationProviderModel> federationProviders = realm.getUserFederationProviders();
UsersSyncManager usersSyncManager = new UsersSyncManager();
for (final UserFederationProviderModel fedProvider : federationProviders) {
List<UserStorageProviderModel> federationProviders = realm.getUserStorageProviders();
UserStorageSyncManager usersSyncManager = new UserStorageSyncManager();
for (final UserStorageProviderModel fedProvider : federationProviders) {
usersSyncManager.notifyToRefreshPeriodicSync(session, realm, fedProvider, false);
}
@ -348,14 +348,6 @@ public class RealmAdminResource {
return users;
}
@Path("user-federation")
public UserFederationProvidersResource userFederation() {
UserFederationProvidersResource fed = new UserFederationProvidersResource(realm, auth, adminEvent);
ResteasyProviderFactory.getInstance().injectProperties(fed);
//resourceContext.initResource(fed);
return fed;
}
@Path("user-storage")
public UserStorageProviderResource userStorage() {
UserStorageProviderResource fed = new UserStorageProviderResource(realm, auth, adminEvent);

View file

@ -1,459 +0,0 @@
/*
* 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.services.resources.admin;
import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.spi.NotFoundException;
import org.keycloak.events.admin.OperationType;
import org.keycloak.events.admin.ResourceType;
import org.keycloak.mappers.FederationConfigValidationException;
import org.keycloak.mappers.UserFederationMapper;
import org.keycloak.mappers.UserFederationMapperFactory;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.ModelException;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationMapperModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderFactory;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserFederationSyncResult;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.representations.idm.ConfigPropertyRepresentation;
import org.keycloak.representations.idm.UserFederationMapperRepresentation;
import org.keycloak.representations.idm.UserFederationMapperTypeRepresentation;
import org.keycloak.representations.idm.UserFederationProviderRepresentation;
import org.keycloak.services.ErrorResponse;
import org.keycloak.services.ErrorResponseException;
import org.keycloak.services.ServicesLogger;
import org.keycloak.services.managers.UsersSyncManager;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class UserFederationProviderResource {
private static final Logger logger = Logger.getLogger(UserFederationProviderResource.class);
private final KeycloakSession session;
private final RealmModel realm;
private final RealmAuth auth;
private final UserFederationProviderModel federationProviderModel;
private final AdminEventBuilder adminEvent;
@Context
private UriInfo uriInfo;
public UserFederationProviderResource(KeycloakSession session, RealmModel realm, RealmAuth auth, UserFederationProviderModel federationProviderModel, AdminEventBuilder adminEvent) {
this.session = session;
this.realm = realm;
this.auth = auth;
this.federationProviderModel = federationProviderModel;
this.adminEvent = adminEvent.resource(ResourceType.USER_FEDERATION_PROVIDER);
}
/**
* Update a provider
*
* @param rep
*/
@PUT
@NoCache
@Consumes(MediaType.APPLICATION_JSON)
public Response updateProviderInstance(UserFederationProviderRepresentation rep) {
auth.requireManage();
if (federationProviderModel == null) {
throw new NotFoundException("Could not find federation provider");
}
try {
String displayName = rep.getDisplayName();
if (displayName != null && displayName.trim().equals("")) {
displayName = null;
}
UserFederationProviderModel model = new UserFederationProviderModel(rep.getId(), rep.getProviderName(), rep.getConfig(), rep.getPriority(), displayName,
rep.getFullSyncPeriod(), rep.getChangedSyncPeriod(), rep.getLastSync());
UserFederationProvidersResource.validateFederationProviderConfig(session, auth, realm, model);
realm.updateUserFederationProvider(model);
new UsersSyncManager().notifyToRefreshPeriodicSync(session, realm, model, false);
boolean kerberosCredsAdded = UserFederationProvidersResource.checkKerberosCredential(session, realm, model);
if (kerberosCredsAdded) {
ServicesLogger.LOGGER.addedKerberosToRealmCredentials();
}
adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success();
return Response.noContent().build();
} catch (ModelDuplicateException e) {
if (session.getTransactionManager().isActive()) {
session.getTransactionManager().setRollbackOnly();
}
return ErrorResponse.exists("Federation provider exists with same name.");
} catch (ModelException me) {
if (session.getTransactionManager().isActive()) {
session.getTransactionManager().setRollbackOnly();
}
return ErrorResponse.error("Unable to update federation provider.", Response.Status.INTERNAL_SERVER_ERROR);
}
}
/**
* Get a provider
*
*/
@GET
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public UserFederationProviderRepresentation getProviderInstance() {
auth.requireView();
if (federationProviderModel == null) {
throw new NotFoundException("Could not find federation provider");
}
return ModelToRepresentation.toRepresentation(this.federationProviderModel);
}
/**
* Delete a provider
*
*/
@DELETE
@NoCache
public void deleteProviderInstance() {
auth.requireManage();
if (federationProviderModel == null) {
throw new NotFoundException("Could not find federation provider");
}
realm.removeUserFederationProvider(this.federationProviderModel);
new UsersSyncManager().notifyToRefreshPeriodicSync(session, realm, this.federationProviderModel, true);
adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
}
/**
* Trigger sync of users
*
* @return
*/
@POST
@Path("sync")
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public UserFederationSyncResult syncUsers(@QueryParam("action") String action) {
auth.requireManage();
if (federationProviderModel == null) {
throw new NotFoundException("Could not find federation provider");
}
logger.debug("Syncing users");
UsersSyncManager syncManager = new UsersSyncManager();
UserFederationSyncResult syncResult;
if ("triggerFullSync".equals(action)) {
syncResult = syncManager.syncAllUsers(session.getKeycloakSessionFactory(), realm.getId(), this.federationProviderModel);
} else if ("triggerChangedUsersSync".equals(action)) {
syncResult = syncManager.syncChangedUsers(session.getKeycloakSessionFactory(), realm.getId(), this.federationProviderModel);
} else {
throw new NotFoundException("Unknown action: " + action);
}
Map<String, Object> eventRep = new HashMap<>();
eventRep.put("action", action);
eventRep.put("result", syncResult);
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).representation(eventRep).success();
return syncResult;
}
/**
* Get available user federation mapper types
*
* @return
*/
@GET
@Path("mapper-types")
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public Map<String, UserFederationMapperTypeRepresentation> getMapperTypes() {
auth.requireView();
if (federationProviderModel == null) {
throw new NotFoundException("Could not find federation provider");
}
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
Map<String, UserFederationMapperTypeRepresentation> types = new HashMap<>();
List<ProviderFactory> factories = sessionFactory.getProviderFactories(UserFederationMapper.class);
for (ProviderFactory factory : factories) {
UserFederationMapperFactory mapperFactory = (UserFederationMapperFactory)factory;
if (mapperFactory.getFederationProviderType().equals(this.federationProviderModel.getProviderName())) {
UserFederationMapperTypeRepresentation rep = new UserFederationMapperTypeRepresentation();
rep.setId(mapperFactory.getId());
rep.setCategory(mapperFactory.getDisplayCategory());
rep.setName(mapperFactory.getDisplayType());
rep.setHelpText(mapperFactory.getHelpText());
rep.setSyncConfig(mapperFactory.getSyncConfig());
List<ProviderConfigProperty> configProperties = mapperFactory.getConfigProperties();
for (ProviderConfigProperty prop : configProperties) {
ConfigPropertyRepresentation propRep = ModelToRepresentation.toRepresentation(prop);
rep.getProperties().add(propRep);
}
rep.setDefaultConfig(mapperFactory.getDefaultConfig(this.federationProviderModel));
types.put(rep.getId(), rep);
}
}
return types;
}
/**
* Get mappers configured for this provider
*
* @return
*/
@GET
@Path("mappers")
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<UserFederationMapperRepresentation> getMappers() {
auth.requireView();
if (federationProviderModel == null) {
throw new NotFoundException("Could not find federation provider");
}
List<UserFederationMapperRepresentation> mappers = new LinkedList<>();
for (UserFederationMapperModel model : realm.getUserFederationMappersByFederationProvider(this.federationProviderModel.getId())) {
mappers.add(ModelToRepresentation.toRepresentation(realm, model));
}
// Sort mappers by category,type,name
Collections.sort(mappers, new Comparator<UserFederationMapperRepresentation>() {
@Override
public int compare(UserFederationMapperRepresentation o1, UserFederationMapperRepresentation o2) {
UserFederationMapperFactory factory1 = (UserFederationMapperFactory) session.getKeycloakSessionFactory().getProviderFactory(UserFederationMapper.class, o1.getFederationMapperType());
UserFederationMapperFactory factory2 = (UserFederationMapperFactory) session.getKeycloakSessionFactory().getProviderFactory(UserFederationMapper.class, o2.getFederationMapperType());
int compare = factory1.getDisplayCategory().compareTo(factory2.getDisplayCategory());
if (compare != 0) return compare;
compare = factory1.getDisplayType().compareTo(factory2.getDisplayType());
if (compare != 0) return compare;
compare = o1.getName().compareTo(o2.getName());
return compare;
}
});
return mappers;
}
/**
* Create a mapper
*
* @param mapper
* @return
*/
@POST
@Path("mappers")
@Consumes(MediaType.APPLICATION_JSON)
public Response addMapper(UserFederationMapperRepresentation mapper) {
auth.requireManage();
if (federationProviderModel == null) {
throw new NotFoundException("Could not find federation provider");
}
UserFederationMapperModel model = RepresentationToModel.toModel(realm, mapper);
validateModel(model);
model = realm.addUserFederationMapper(model);
adminEvent.operation(OperationType.CREATE).resource(ResourceType.USER_FEDERATION_MAPPER).resourcePath(uriInfo, model.getId())
.representation(mapper).success();
return Response.created(uriInfo.getAbsolutePathBuilder().path(model.getId()).build()).build();
}
/**
* Get a mapper
*
* @param id Mapper id
* @return
*/
@GET
@NoCache
@Path("mappers/{id}")
@Produces(MediaType.APPLICATION_JSON)
public UserFederationMapperRepresentation getMapperById(@PathParam("id") String id) {
auth.requireView();
if (federationProviderModel == null) {
throw new NotFoundException("Could not find federation provider");
}
UserFederationMapperModel model = realm.getUserFederationMapperById(id);
if (model == null) throw new NotFoundException("Model not found");
return ModelToRepresentation.toRepresentation(realm, model);
}
/**
* Update a mapper
*
* @param id Mapper id
* @param rep
*/
@PUT
@NoCache
@Path("mappers/{id}")
@Consumes(MediaType.APPLICATION_JSON)
public void update(@PathParam("id") String id, UserFederationMapperRepresentation rep) {
auth.requireManage();
if (federationProviderModel == null) {
throw new NotFoundException("Could not find federation provider");
}
UserFederationMapperModel model = realm.getUserFederationMapperById(id);
if (model == null) throw new NotFoundException("Model not found");
model = RepresentationToModel.toModel(realm, rep);
validateModel(model);
realm.updateUserFederationMapper(model);
adminEvent.operation(OperationType.UPDATE).resource(ResourceType.USER_FEDERATION_MAPPER).resourcePath(uriInfo).representation(rep).success();
}
/**
* Delete a mapper with a given id
*
* @param id Mapper id
*/
@DELETE
@NoCache
@Path("mappers/{id}")
public void delete(@PathParam("id") String id) {
auth.requireManage();
if (federationProviderModel == null) {
throw new NotFoundException("Could not find federation provider");
}
UserFederationMapperModel model = realm.getUserFederationMapperById(id);
if (model == null) throw new NotFoundException("Model not found");
realm.removeUserFederationMapper(model);
adminEvent.operation(OperationType.DELETE).resource(ResourceType.USER_FEDERATION_MAPPER).resourcePath(uriInfo).success();
}
/**
* Trigger sync of mapper data related to federationMapper (roles, groups, ...)
*
* @return
*/
@POST
@Path("mappers/{id}/sync")
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public UserFederationSyncResult syncMapperData(@PathParam("id") String mapperId, @QueryParam("direction") String direction) {
auth.requireManage();
if (federationProviderModel == null) {
throw new NotFoundException("Could not find federation provider");
}
UserFederationMapperModel mapperModel = realm.getUserFederationMapperById(mapperId);
if (mapperModel == null) throw new NotFoundException("Mapper model not found");
UserFederationMapper mapper = session.getProvider(UserFederationMapper.class, mapperModel.getFederationMapperType());
UserFederationProviderModel providerModel = KeycloakModelUtils.findUserFederationProviderById(mapperModel.getFederationProviderId(), realm);
if (providerModel == null) throw new NotFoundException("Provider model not found");
UserFederationProviderFactory providerFactory = (UserFederationProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(UserFederationProvider.class, providerModel.getProviderName());
UserFederationProvider federationProvider = providerFactory.getInstance(session, providerModel);
ServicesLogger.LOGGER.syncingDataForMapper(mapperModel.getName(), mapperModel.getFederationMapperType(), direction);
UserFederationSyncResult syncResult;
if ("fedToKeycloak".equals(direction)) {
syncResult = mapper.syncDataFromFederationProviderToKeycloak(mapperModel, federationProvider, session, realm);
} else if ("keycloakToFed".equals(direction)) {
syncResult = mapper.syncDataFromKeycloakToFederationProvider(mapperModel, federationProvider, session, realm);
} else {
throw new NotFoundException("Unknown direction: " + direction);
}
Map<String, Object> eventRep = new HashMap<>();
eventRep.put("action", direction);
eventRep.put("result", syncResult);
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).representation(eventRep).success();
return syncResult;
}
private void validateModel(UserFederationMapperModel model) {
try {
UserFederationMapperFactory mapperFactory = (UserFederationMapperFactory) session.getKeycloakSessionFactory().getProviderFactory(UserFederationMapper.class, model.getFederationMapperType());
mapperFactory.validateConfig(realm, federationProviderModel, model);
} catch (FederationConfigValidationException ex) {
logger.error(ex.getMessage());
Properties messages = AdminRoot.getMessages(session, realm, auth.getAuth().getToken().getLocale());
throw new ErrorResponseException(ex.getMessage(), MessageFormat.format(messages.getProperty(ex.getMessage(), ex.getMessage()), ex.getParameters()),
Response.Status.BAD_REQUEST);
}
}
}

View file

@ -1,344 +0,0 @@
/*
* 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.services.resources.admin;
import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.spi.NotFoundException;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.common.constants.KerberosConstants;
import org.keycloak.component.ComponentModel;
import org.keycloak.events.admin.OperationType;
import org.keycloak.events.admin.ResourceType;
import org.keycloak.mappers.FederationConfigValidationException;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.ModelException;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderFactory;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserFederationValidatingProviderFactory;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.provider.ConfiguredProvider;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.representations.idm.ConfigPropertyRepresentation;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.UserFederationProviderFactoryRepresentation;
import org.keycloak.representations.idm.UserFederationProviderRepresentation;
import org.keycloak.services.ErrorResponse;
import org.keycloak.services.ErrorResponseException;
import org.keycloak.services.ServicesLogger;
import org.keycloak.services.managers.UsersSyncManager;
import org.keycloak.utils.CredentialHelper;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
/**
* Base resource for managing users
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UserFederationProvidersResource {
private static final Logger logger = Logger.getLogger(UserFederationProvidersResource.class);
protected RealmModel realm;
protected RealmAuth auth;
protected AdminEventBuilder adminEvent;
@Context
protected UriInfo uriInfo;
@Context
protected KeycloakSession session;
public UserFederationProvidersResource(RealmModel realm, RealmAuth auth, AdminEventBuilder adminEvent) {
this.auth = auth;
this.realm = realm;
this.adminEvent = adminEvent.resource(ResourceType.USER_FEDERATION_PROVIDER);
auth.init(RealmAuth.Resource.REALM);
}
/**
* Automatically add "kerberos" to required realm credentials if it's supported by saved provider
*
* @param realm
* @param model
* @return true if kerberos credentials were added
*/
public static boolean checkKerberosCredential(KeycloakSession session, RealmModel realm, UserFederationProviderModel model) {
String allowKerberosCfg = model.getConfig().get(KerberosConstants.ALLOW_KERBEROS_AUTHENTICATION);
if (Boolean.valueOf(allowKerberosCfg)) {
CredentialHelper.setOrReplaceAuthenticationRequirement(session, realm, CredentialRepresentation.KERBEROS,
AuthenticationExecutionModel.Requirement.ALTERNATIVE, AuthenticationExecutionModel.Requirement.DISABLED);
return true;
}
return false;
}
public static void validateFederationProviderConfig(KeycloakSession session, RealmAuth auth, RealmModel realm, UserFederationProviderModel model) {
UserFederationProviderFactory providerFactory = KeycloakModelUtils.getFederationProviderFactory(session, model);
if (providerFactory instanceof UserFederationValidatingProviderFactory) {
try {
((UserFederationValidatingProviderFactory) providerFactory).validateConfig(realm, model);
} catch (FederationConfigValidationException fcve) {
logger.error(fcve.getMessage());
Properties messages = AdminRoot.getMessages(session, realm, auth.getAuth().getToken().getLocale());
throw new ErrorResponseException(fcve.getMessage(), MessageFormat.format(messages.getProperty(fcve.getMessage(), fcve.getMessage()), fcve.getParameters()),
Response.Status.BAD_REQUEST);
}
}
}
/**
* Get available provider factories
*
* Returns a list of available provider factories.
*
* @return
*/
@GET
@NoCache
@Path("providers")
@Produces(MediaType.APPLICATION_JSON)
public List<UserFederationProviderFactoryRepresentation> getProviders() {
auth.requireView();
List<UserFederationProviderFactoryRepresentation> providers = new LinkedList<UserFederationProviderFactoryRepresentation>();
for (ProviderFactory factory : session.getKeycloakSessionFactory().getProviderFactories(UserFederationProvider.class)) {
UserFederationProviderFactoryRepresentation rep = new UserFederationProviderFactoryRepresentation();
rep.setId(factory.getId());
rep.setOptions(((UserFederationProviderFactory)factory).getConfigurationOptions());
providers.add(rep);
}
return providers;
}
/**
* Get factory with given id
*
* @return
*/
@GET
@NoCache
@Path("providers/{id}")
@Produces(MediaType.APPLICATION_JSON)
public UserFederationProviderFactoryRepresentation getProvider(@PathParam("id") String id) {
auth.requireView();
for (ProviderFactory factory : session.getKeycloakSessionFactory().getProviderFactories(UserFederationProvider.class)) {
if (!factory.getId().equals(id)) {
continue;
}
if (factory instanceof ConfiguredProvider) {
UserFederationProviderFactoryDescription rep = new UserFederationProviderFactoryDescription();
rep.setId(factory.getId());
ConfiguredProvider cp = (ConfiguredProvider) factory;
rep.setHelpText(cp.getHelpText());
rep.setProperties(toConfigPropertyRepresentationList(cp.getConfigProperties()));
return rep;
}
UserFederationProviderFactoryRepresentation rep = new UserFederationProviderFactoryRepresentation();
rep.setId(factory.getId());
rep.setOptions(((UserFederationProviderFactory) factory).getConfigurationOptions());
return rep;
}
throw new NotFoundException("Could not find provider");
}
/**
* Create a provider
*
* @param rep
* @return
*/
@POST
@Path("instances")
@Consumes(MediaType.APPLICATION_JSON)
public Response createProviderInstance(UserFederationProviderRepresentation rep) {
auth.requireManage();
try {
String displayName = rep.getDisplayName();
if (displayName != null && displayName.trim().equals("")) {
displayName = null;
}
UserFederationProviderModel tempModel = new UserFederationProviderModel(null, rep.getProviderName(), rep.getConfig(), rep.getPriority(), displayName, rep.getFullSyncPeriod(), rep.getChangedSyncPeriod(), rep.getLastSync());
validateFederationProviderConfig(session, auth, realm, tempModel);
UserFederationProviderModel model = realm.addUserFederationProvider(rep.getProviderName(), rep.getConfig(), rep.getPriority(), displayName,
rep.getFullSyncPeriod(), rep.getChangedSyncPeriod(), rep.getLastSync());
new UsersSyncManager().notifyToRefreshPeriodicSync(session, realm, model, false);
boolean kerberosCredsAdded = checkKerberosCredential(session, realm, model);
if (kerberosCredsAdded) {
ServicesLogger.LOGGER.addedKerberosToRealmCredentials();
}
rep.setId(model.getId());
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, model.getId()).representation(rep).success();
return Response.created(uriInfo.getAbsolutePathBuilder().path(model.getId()).build()).build();
} catch (ModelDuplicateException e) {
if (session.getTransactionManager().isActive()) {
session.getTransactionManager().setRollbackOnly();
}
return ErrorResponse.exists("Federation provider exists with same name.");
} catch (ModelException me){
if (session.getTransactionManager().isActive()) {
session.getTransactionManager().setRollbackOnly();
}
return ErrorResponse.error("Could not create federation provider.", Response.Status.INTERNAL_SERVER_ERROR);
}
}
/**
* Get configured providers
*
* @return
*/
@GET
@Path("instances")
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public List<UserFederationProviderRepresentation> getUserFederationInstances() {
auth.requireView();
List<UserFederationProviderRepresentation> reps = new LinkedList<UserFederationProviderRepresentation>();
for (UserFederationProviderModel model : realm.getUserFederationProviders()) {
UserFederationProviderRepresentation rep = ModelToRepresentation.toRepresentation(model);
reps.add(rep);
}
return reps;
}
@Path("instances/{id}")
public UserFederationProviderResource getUserFederationInstance(@PathParam("id") String id) {
this.auth.requireView();
UserFederationProviderModel model = KeycloakModelUtils.findUserFederationProviderById(id, realm);
UserFederationProviderResource instanceResource = new UserFederationProviderResource(session, realm, this.auth, model, adminEvent);
ResteasyProviderFactory.getInstance().injectProperties(instanceResource);
return instanceResource;
}
// TODO: This endpoint exists, so that admin console can lookup userFederation provider OR userStorage provider by federationLink.
// TODO: Endpoint should be removed once UserFederation SPI is removed as fallback is not needed anymore than
@GET
@Path("instances-with-fallback/{id}")
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public Map<String, String> getUserFederationInstanceWithFallback(@PathParam("id") String id) {
this.auth.requireView();
Map<String, String> result = new HashMap<>();
UserFederationProviderModel model = KeycloakModelUtils.findUserFederationProviderById(id, realm);
if (model != null) {
result.put("federationLinkName", model.getDisplayName());
result.put("federationLink", "#/realms/" + realm.getName() + "/user-federation/providers/" + model.getProviderName() + "/" + model.getId());
return result;
} else {
ComponentModel userStorage = KeycloakModelUtils.findUserStorageProviderById(id, realm);
if (userStorage != null) {
result.put("federationLinkName", userStorage.getName());
result.put("federationLink", "#/realms/" + realm.getName() + "/user-storage/providers/" + userStorage.getProviderId() + "/" + userStorage.getId());
return result;
} else {
throw new NotFoundException("Could not find federation provider or userStorage provider");
}
}
}
private ConfigPropertyRepresentation toConfigPropertyRepresentation(ProviderConfigProperty prop) {
return ModelToRepresentation.toRepresentation(prop);
}
private List<ConfigPropertyRepresentation> toConfigPropertyRepresentationList(List<ProviderConfigProperty> props) {
List<ConfigPropertyRepresentation> reps = new ArrayList<>(props.size());
for(ProviderConfigProperty prop : props){
reps.add(toConfigPropertyRepresentation(prop));
}
return reps;
}
public static class UserFederationProviderFactoryDescription extends UserFederationProviderFactoryRepresentation {
protected String name;
protected String helpText;
protected List<ConfigPropertyRepresentation> properties;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getHelpText() {
return helpText;
}
public void setHelpText(String helpText) {
this.helpText = helpText;
}
public List<ConfigPropertyRepresentation> getProperties() {
return properties;
}
public void setProperties(List<ConfigPropertyRepresentation> properties) {
this.properties = properties;
}
}
}

View file

@ -25,6 +25,7 @@ import org.keycloak.models.CredentialValidationOutput;
import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionTask;
import org.keycloak.models.ModelException;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
@ -32,6 +33,7 @@ import org.keycloak.models.RoleModel;
import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserManager;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserProvider;
import org.keycloak.models.cache.CachedUserModel;
@ -52,6 +54,8 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.keycloak.models.utils.KeycloakModelUtils.runJobInTransaction;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
@ -244,13 +248,39 @@ public class UserStorageManager implements UserProvider, OnUserCache {
if (user == null || user.getFederationLink() == null) return user;
UserStorageProvider provider = getStorageProvider(session, realm, user.getFederationLink());
if (provider != null && provider instanceof ImportedUserValidation) {
return ((ImportedUserValidation)provider).validate(realm, user);
UserModel validated = ((ImportedUserValidation)provider).validate(realm, user);
if (validated == null) {
deleteInvalidUser(realm, user);
return null;
} else {
return validated;
}
} else {
return user;
}
}
protected void deleteInvalidUser(final RealmModel realm, final UserModel user) {
String userId = user.getId();
String userName = user.getUsername();
session.getUserCache().evict(realm, user);
runJobInTransaction(session.getKeycloakSessionFactory(), new KeycloakSessionTask() {
@Override
public void run(KeycloakSession session) {
RealmModel realmModel = session.realms().getRealm(realm.getId());
if (realmModel == null) return;
UserModel deletedUser = session.userLocalStorage().getUserById(userId, realmModel);
new UserManager(session).removeUser(realmModel, deletedUser, session.userLocalStorage());
logger.debugf("Removed invalid user '%s'", userName);
}
});
}
protected List<UserModel> importValidation(RealmModel realm, List<UserModel> users) {
List<UserModel> tmp = new LinkedList<>();
for (UserModel user : users) {

View file

@ -1,62 +0,0 @@
/*
* 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.testsuite.federation;
import org.keycloak.provider.ConfiguredProvider;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.Arrays;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class DummyConfigurableUserFederationProviderFactory extends DummyUserFederationProviderFactory implements ConfiguredProvider {
public static final String PROVIDER_NAME = "dummy-configurable";
@Override
public String getId() {
return PROVIDER_NAME;
}
@Override
public String getHelpText() {
return "Dummy User Federation Provider Help Text";
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
ProviderConfigProperty prop1 = new ProviderConfigProperty();
prop1.setName("prop1");
prop1.setLabel("Prop1");
prop1.setDefaultValue("prop1Default");
prop1.setHelpText("Prop1 HelpText");
prop1.setType(ProviderConfigProperty.STRING_TYPE);
ProviderConfigProperty prop2 = new ProviderConfigProperty();
prop2.setName("prop2");
prop2.setLabel("Prop2");
prop2.setDefaultValue("true");
prop2.setHelpText("Prop2 HelpText");
prop2.setType(ProviderConfigProperty.BOOLEAN_TYPE);
return Arrays.asList(prop1, prop2);
}
}

View file

@ -1,140 +0,0 @@
/*
* 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.testsuite.federation;
import org.keycloak.Config;
import org.keycloak.mappers.FederationConfigValidationException;
import org.keycloak.mappers.UserFederationMapper;
import org.keycloak.mappers.UserFederationMapperFactory;
import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationMapperModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserFederationSyncResult;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.idm.UserFederationMapperSyncConfigRepresentation;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class DummyUserFederationMapper implements UserFederationMapperFactory, UserFederationMapper {
public static final String PROVIDER_NAME = "dummy-mapper";
@Override
public String getFederationProviderType() {
return DummyUserFederationProviderFactory.PROVIDER_NAME;
}
@Override
public String getDisplayCategory() {
return "Dummy";
}
@Override
public String getDisplayType() {
return "Dummy";
}
@Override
public UserFederationMapperSyncConfigRepresentation getSyncConfig() {
return new UserFederationMapperSyncConfigRepresentation(true, "dummyFedToKeycloak", true, "dummyKeycloakToFed");
}
@Override
public void validateConfig(RealmModel realm, UserFederationProviderModel fedProviderModel, UserFederationMapperModel mapperModel) throws FederationConfigValidationException {
}
@Override
public Map<String, String> getDefaultConfig(UserFederationProviderModel providerModel) {
return Collections.emptyMap();
}
@Override
public String getHelpText() {
return "Dummy";
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return Collections.emptyList();
}
@Override
public UserFederationMapper create(KeycloakSession session) {
return this;
}
@Override
public void init(Config.Scope config) {
}
@Override
public void postInit(KeycloakSessionFactory factory) {
}
@Override
public void close() {
}
@Override
public String getId() {
return PROVIDER_NAME;
}
@Override
public UserFederationSyncResult syncDataFromFederationProviderToKeycloak(final UserFederationMapperModel mapperModel, UserFederationProvider federationProvider, KeycloakSession session, RealmModel realm) {
return new UserFederationSyncResult() {
@Override
public String getStatus() {
return "dummyFedToKeycloakSuccess mapper=" + mapperModel.getName();
}
};
}
@Override
public UserFederationSyncResult syncDataFromKeycloakToFederationProvider(final UserFederationMapperModel mapperModel, UserFederationProvider federationProvider, KeycloakSession session, RealmModel realm) {
return new UserFederationSyncResult() {
@Override
public String getStatus() {
return "dummyKeycloakToFedSuccess mapper=" + mapperModel.getName();
}
};
}
@Override
public List<UserModel> getGroupMembers(UserFederationMapperModel mapperModel, UserFederationProvider federationProvider, RealmModel realm, GroupModel group, int firstResult, int maxResults) {
return Collections.emptyList();
}
}

View file

@ -17,15 +17,23 @@
package org.keycloak.testsuite.federation;
import org.keycloak.component.ComponentModel;
import org.keycloak.credential.CredentialInput;
import org.keycloak.credential.CredentialInputUpdater;
import org.keycloak.credential.CredentialInputValidator;
import org.keycloak.credential.CredentialModel;
import org.keycloak.models.CredentialValidationOutput;
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.UserFederationProvider;
import org.keycloak.models.UserModel;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.user.UserLookupProvider;
import org.keycloak.storage.user.UserQueryProvider;
import org.keycloak.storage.user.UserRegistrationProvider;
import java.util.Collections;
import java.util.List;
@ -36,56 +44,60 @@ import java.util.Set;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class DummyUserFederationProvider implements UserFederationProvider {
public class DummyUserFederationProvider implements UserStorageProvider,
UserLookupProvider,
UserRegistrationProvider,
CredentialInputValidator {
private final Map<String, UserModel> users;
private KeycloakSession session;
private ComponentModel component;
public DummyUserFederationProvider(Map<String, UserModel> users) {
public DummyUserFederationProvider(KeycloakSession session, ComponentModel component, Map<String, UserModel> users) {
this.users = users;
this.session = session;
this.component = component;
}
@Override
public UserModel validateAndProxy(RealmModel realm, UserModel local) {
public UserModel addUser(RealmModel realm, String username) {
UserModel local = session.userLocalStorage().addUser(realm, username);
local.setFederationLink(component.getId());
users.put(username, local);
return local;
}
@Override
public boolean synchronizeRegistrations() {
return true;
}
@Override
public UserModel register(RealmModel realm, UserModel user) {
users.put(user.getUsername(), user);
return user;
}
@Override
public boolean removeUser(RealmModel realm, UserModel user) {
return users.remove(user.getUsername()) != null;
}
@Override
public UserModel getUserByUsername(RealmModel realm, String username) {
return users.get(username);
}
@Override
public UserModel getUserByEmail(RealmModel realm, String email) {
public UserModel getUserById(String id, RealmModel realm) {
return null;
}
@Override
public List<UserModel> searchByAttributes(Map<String, String> attributes, RealmModel realm, int maxResults) {
return Collections.emptyList();
public UserModel getUserByUsername(String username, RealmModel realm) {
return users.get(username);
}
@Override
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
return Collections.emptyList();
public UserModel getUserByEmail(String email, RealmModel realm) {
return null;
}
@Override
public void grantToAllUsers(RealmModel realm, RoleModel role) {
}
@Override
public void preRemove(RealmModel realm) {
}
@ -100,34 +112,10 @@ public class DummyUserFederationProvider implements UserFederationProvider {
}
@Override
public boolean isValid(RealmModel realm, UserModel local) {
String username = local.getUsername();
return users.containsKey(username);
}
@Override
public Set<String> getSupportedCredentialTypes() {
return Collections.singleton(UserCredentialModel.PASSWORD);
}
@Override
public boolean updateCredential(RealmModel realm, UserModel user, CredentialInput input) {
if (!(input instanceof UserCredentialModel) || !CredentialModel.PASSWORD.equals(input.getType())) return false;
return false;
}
@Override
public void disableCredentialType(RealmModel realm, UserModel user, String credentialType) {
}
@Override
public Set<String> getDisableableCredentialTypes(RealmModel realm, UserModel user) {
return Collections.EMPTY_SET;
}
@Override
public boolean supportsCredentialType(String credentialType) {
return getSupportedCredentialTypes().contains(credentialType);
@ -154,12 +142,7 @@ public class DummyUserFederationProvider implements UserFederationProvider {
}
return false; }
@Override
public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel credential) {
return CredentialValidationOutput.failed();
}
@Override
@Override
public void close() {
}

View file

@ -19,17 +19,26 @@ package org.keycloak.testsuite.federation;
import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderFactory;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserFederationSyncResult;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.provider.ProviderConfigurationBuilder;
import org.keycloak.storage.UserStorageProviderFactory;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.user.ImportSynchronization;
import org.keycloak.storage.user.SynchronizationResult;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
@ -38,7 +47,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class DummyUserFederationProviderFactory implements UserFederationProviderFactory {
public class DummyUserFederationProviderFactory implements UserStorageProviderFactory<DummyUserFederationProvider>, ImportSynchronization {
private static final Logger logger = Logger.getLogger(DummyUserFederationProviderFactory.class);
public static final String PROVIDER_NAME = "dummy";
@ -49,20 +58,16 @@ public class DummyUserFederationProviderFactory implements UserFederationProvide
private Map<String, UserModel> users = new HashMap<String, UserModel>();
@Override
public UserFederationProvider getInstance(KeycloakSession session, UserFederationProviderModel model) {
return new DummyUserFederationProvider(users);
public DummyUserFederationProvider create(KeycloakSession session, ComponentModel model) {
return new DummyUserFederationProvider(session, model, users);
}
@Override
public Set<String> getConfigurationOptions() {
Set<String> list = new HashSet<String>();
list.add("important.config");
return list;
}
@Override
public UserFederationProvider create(KeycloakSession session) {
return new DummyUserFederationProvider(users);
public List<ProviderConfigProperty> getConfigProperties() {
return ProviderConfigurationBuilder.create()
.property().name("important.config")
.type(ProviderConfigProperty.STRING_TYPE)
.add().build();
}
@Override
@ -86,17 +91,17 @@ public class DummyUserFederationProviderFactory implements UserFederationProvide
}
@Override
public UserFederationSyncResult syncAllUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model) {
public SynchronizationResult sync(KeycloakSessionFactory sessionFactory, String realmId, UserStorageProviderModel model) {
logger.info("syncAllUsers invoked");
fullSyncCounter.incrementAndGet();
return UserFederationSyncResult.empty();
return SynchronizationResult.empty();
}
@Override
public UserFederationSyncResult syncChangedUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model, Date lastSync) {
public SynchronizationResult syncSince(Date lastSync, KeycloakSessionFactory sessionFactory, String realmId, UserStorageProviderModel model) {
logger.info("syncChangedUsers invoked");
changedSyncCounter.incrementAndGet();
return UserFederationSyncResult.empty();
return SynchronizationResult.empty();
}
public int getFullSyncCounter() {

View file

@ -57,9 +57,11 @@ import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resource.RealmResourceProvider;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.testsuite.components.TestProvider;
import org.keycloak.testsuite.components.TestProviderFactory;
import org.keycloak.testsuite.events.EventsListenerProvider;
import org.keycloak.testsuite.federation.DummyUserFederationProviderFactory;
import org.keycloak.testsuite.forms.PassThroughAuthenticator;
import org.keycloak.testsuite.forms.PassThroughClientAuthenticator;
import org.keycloak.testsuite.rest.representation.AuthenticatorState;
@ -580,8 +582,8 @@ public class TestingResourceProvider implements RealmResourceProvider {
public UserRepresentation getUserByUsernameFromFedProviderFactory(@QueryParam("realmName") String realmName,
@QueryParam("userName") String userName) {
RealmModel realm = getRealmByName(realmName);
UserFederationProviderFactory factory = (UserFederationProviderFactory)session.getKeycloakSessionFactory().getProviderFactory(UserFederationProvider.class, "dummy");
UserModel user = factory.getInstance(session, null).getUserByUsername(realm, userName);
DummyUserFederationProviderFactory factory = (DummyUserFederationProviderFactory)session.getKeycloakSessionFactory().getProviderFactory(UserStorageProvider.class, "dummy");
UserModel user = factory.create(session, null).getUserByUsername(userName, realm);
if (user == null) return null;
return ModelToRepresentation.toRepresentation(session, realm, user);
}

View file

@ -1,52 +0,0 @@
#
# 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.
#
#
# 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.
#
#
# 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.
#
org.keycloak.testsuite.federation.DummyUserFederationMapper

View file

@ -1,36 +0,0 @@
#
# 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.
#
#
# 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.
#
org.keycloak.testsuite.federation.DummyUserFederationProviderFactory
org.keycloak.testsuite.federation.DummyConfigurableUserFederationProviderFactory

View file

@ -30,7 +30,6 @@ import org.keycloak.representations.idm.UserFederationMapperTypeRepresentation;
import org.keycloak.representations.idm.UserFederationProviderRepresentation;
import org.keycloak.representations.idm.UserFederationSyncResultRepresentation;
import org.keycloak.testsuite.Assert;
import org.keycloak.testsuite.federation.DummyUserFederationMapper;
import org.keycloak.testsuite.util.AdminEventPaths;
import org.keycloak.testsuite.util.UserFederationProviderBuilder;

View file

@ -82,7 +82,7 @@ public class UserStorageRestTest extends AbstractAdminTest {
}
private UserFederationProvidersResource userFederation() {
return realm.userFederation();
return null;//realm.userFederation();
}

View file

@ -47,7 +47,7 @@ public class ClientRedirectTest extends TestRealmKeycloakTest {
*
* @throws Exception
*/
@Test
//@Test
public void testClientRedirectEndpoint() throws Exception {
oauth.doLogin("test-user@localhost", "password");

View file

@ -77,13 +77,6 @@ public class SSSDTest extends AbstractKeycloakTest {
adminClient.realm(REALM_NAME).components().add(userFederation);
}
@Ignore
@Test
public void testProviderFactories() {
List<UserFederationProviderFactoryRepresentation> providerFactories = adminClient.realm(REALM_NAME).userFederation().getProviderFactories();
Assert.assertNames(providerFactories, "ldap", "kerberos", "dummy", "dummy-configurable", "sssd");
}
@Test
public void testWrongUser() {
log.debug("Testing wrong password for user " + USERNAME);

View file

@ -30,6 +30,7 @@ import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.IdentityProviderRepresentation;
import org.keycloak.services.Urls;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.testsuite.broker.util.UserSessionStatusServlet;
import org.keycloak.testsuite.federation.DummyUserFederationProviderFactory;
import org.openqa.selenium.By;
@ -634,7 +635,14 @@ public abstract class AbstractKeycloakIdentityProviderTest extends AbstractIdent
// Add federationProvider to realm. It's configured with sync registrations
RealmModel realm = getRealm();
UserFederationProviderModel dummyModel = realm.addUserFederationProvider(DummyUserFederationProviderFactory.PROVIDER_NAME, new HashMap<String, String>(), 1, "test-dummy", -1, -1, 0);
UserStorageProviderModel model = new UserStorageProviderModel();
model.setProviderId(DummyUserFederationProviderFactory.PROVIDER_NAME);
model.setPriority(1);
model.setName("test-sync-dummy");
model.setFullSyncPeriod(-1);
model.setChangedSyncPeriod(-1);
model.setLastSync(0);
UserStorageProviderModel dummyModel = new UserStorageProviderModel(realm.addComponentModel(model));
brokerServerRule.stopSession(session, true);
session = brokerServerRule.startSession();
@ -682,7 +690,7 @@ public abstract class AbstractKeycloakIdentityProviderTest extends AbstractIdent
// remove dummy federation provider for this realm
realm = getRealm();
realm.removeUserFederationProvider(dummyModel);
realm.removeComponent(dummyModel);
brokerServerRule.stopSession(session, true);
session = brokerServerRule.startSession();

View file

@ -26,9 +26,14 @@ import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserFederationSyncResult;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.provider.ProviderConfigurationBuilder;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.user.SynchronizationResult;
import org.keycloak.testsuite.federation.DummyUserFederationProviderFactory;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@ -59,21 +64,27 @@ public class SyncDummyUserFederationProviderFactory extends DummyUserFederationP
return SYNC_PROVIDER_ID;
}
@Override
public Set<String> getConfigurationOptions() {
Set<String> list = super.getConfigurationOptions();
list.add(WAIT_TIME);
return list;
public List<ProviderConfigProperty> getConfigProperties() {
return ProviderConfigurationBuilder.create()
.property().name("important.config")
.type(ProviderConfigProperty.STRING_TYPE)
.add()
.property().name(WAIT_TIME)
.type(ProviderConfigProperty.STRING_TYPE)
.add()
.build();
}
@Override
public UserFederationSyncResult syncChangedUsers(KeycloakSessionFactory sessionFactory, final String realmId, final UserFederationProviderModel model, Date lastSync) {
public SynchronizationResult syncSince(Date lastSync, KeycloakSessionFactory sessionFactory, String realmId, UserStorageProviderModel model) {
KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
@Override
public void run(KeycloakSession session) {
int waitTime = Integer.parseInt(model.getConfig().get(WAIT_TIME));
int waitTime = Integer.parseInt(model.getConfig().getFirst(WAIT_TIME));
logger.infof("Starting sync of changed users. Wait time is: %s", waitTime);
@ -109,7 +120,7 @@ public class SyncDummyUserFederationProviderFactory extends DummyUserFederationP
// countDown, so the SyncFederationTest can continue
latch2.countDown();
return new UserFederationSyncResult();
return new SynchronizationResult();
}
}

View file

@ -24,14 +24,17 @@ import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import org.keycloak.common.util.Time;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserFederationSyncResult;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.UsersSyncManager;
import org.keycloak.services.managers.UserStorageSyncManager;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.user.SynchronizationResult;
import org.keycloak.testsuite.federation.DummyUserFederationProviderFactory;
import org.keycloak.testsuite.rule.KeycloakRule;
import org.keycloak.timer.TimerProvider;
@ -41,7 +44,7 @@ import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* Test with Dummy providers (For LDAP see {@link org.keycloak.testsuite.federation.ldap.base.LDAPSyncTest}
* Test with Dummy providers
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@ -50,7 +53,7 @@ public class SyncFederationTest {
private static final Logger log = Logger.getLogger(SyncFederationTest.class);
private static UserFederationProviderModel dummyModel = null;
private static UserStorageProviderModel dummyModel = null;
@ClassRule
public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakRule.KeycloakSetup() {
@ -62,6 +65,7 @@ public class SyncFederationTest {
}
});
@Test
public void test01PeriodicSync() {
@ -70,7 +74,14 @@ public class SyncFederationTest {
@Override
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
dummyModel = appRealm.addUserFederationProvider(DummyUserFederationProviderFactory.PROVIDER_NAME, new HashMap<String, String>(), 1, "test-sync-dummy", -1, 1, 0);
UserStorageProviderModel model = new UserStorageProviderModel();
model.setProviderId(DummyUserFederationProviderFactory.PROVIDER_NAME);
model.setPriority(1);
model.setName("test-sync-dummy");
model.setFullSyncPeriod(-1);
model.setChangedSyncPeriod(1);
model.setLastSync(0);
dummyModel = new UserStorageProviderModel(appRealm.addComponentModel(model));
}
});
@ -78,12 +89,12 @@ public class SyncFederationTest {
KeycloakSession session = keycloakRule.startSession();
try {
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
DummyUserFederationProviderFactory dummyFedFactory = (DummyUserFederationProviderFactory)sessionFactory.getProviderFactory(UserFederationProvider.class, DummyUserFederationProviderFactory.PROVIDER_NAME);
DummyUserFederationProviderFactory dummyFedFactory = (DummyUserFederationProviderFactory)sessionFactory.getProviderFactory(UserStorageProvider.class, DummyUserFederationProviderFactory.PROVIDER_NAME);
int full = dummyFedFactory.getFullSyncCounter();
int changed = dummyFedFactory.getChangedSyncCounter();
// Assert that after some period was DummyUserFederationProvider triggered
UsersSyncManager usersSyncManager = new UsersSyncManager();
UserStorageSyncManager usersSyncManager = new UserStorageSyncManager();
usersSyncManager.bootstrapPeriodic(sessionFactory, session.getProvider(TimerProvider.class));
sleep(1800);
@ -94,7 +105,7 @@ public class SyncFederationTest {
// This sync is here just to ensure that we have lock (doublecheck that periodic sync, which was possibly triggered before canceling timer is finished too)
while (true) {
UserFederationSyncResult result = usersSyncManager.syncChangedUsers(session.getKeycloakSessionFactory(), appRealm.getId(), dummyModel);
SynchronizationResult result = usersSyncManager.syncChangedUsers(session.getKeycloakSessionFactory(), appRealm.getId(), dummyModel);
if (result.isIgnored()) {
log.infof("Still waiting for lock before periodic sync is finished", result.toString());
sleep(1000);
@ -122,7 +133,7 @@ public class SyncFederationTest {
@Override
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
appRealm.removeUserFederationProvider(dummyModel);
appRealm.removeComponent(dummyModel);
}
});
@ -137,9 +148,15 @@ public class SyncFederationTest {
@Override
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
Map<String, String> config = new HashMap<>();
config.put(SyncDummyUserFederationProviderFactory.WAIT_TIME, "2000");
dummyModel = appRealm.addUserFederationProvider(SyncDummyUserFederationProviderFactory.SYNC_PROVIDER_ID, config, 1, "test-sync-dummy", -1, 1, 0);
UserStorageProviderModel model = new UserStorageProviderModel();
model.setProviderId(SyncDummyUserFederationProviderFactory.SYNC_PROVIDER_ID);
model.setPriority(1);
model.setName("test-sync-dummy");
model.setFullSyncPeriod(-1);
model.setChangedSyncPeriod(1);
model.setLastSync(0);
model.getConfig().putSingle(SyncDummyUserFederationProviderFactory.WAIT_TIME, "2000");
dummyModel = new UserStorageProviderModel(appRealm.addComponentModel(model));
}
});
@ -149,13 +166,13 @@ public class SyncFederationTest {
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
// bootstrap periodic sync
UsersSyncManager usersSyncManager = new UsersSyncManager();
UserStorageSyncManager usersSyncManager = new UserStorageSyncManager();
usersSyncManager.bootstrapPeriodic(sessionFactory, session.getProvider(TimerProvider.class));
// Wait and then trigger sync manually. Assert it will be ignored
sleep(1800);
RealmModel realm = session.realms().getRealm("test");
UserFederationSyncResult syncResult = usersSyncManager.syncChangedUsers(sessionFactory, realm.getId(), dummyModel);
SynchronizationResult syncResult = usersSyncManager.syncChangedUsers(sessionFactory, realm.getId(), dummyModel);
Assert.assertTrue(syncResult.isIgnored());
// Cancel timer
@ -175,7 +192,7 @@ public class SyncFederationTest {
@Override
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
appRealm.removeUserFederationProvider(dummyModel);
appRealm.removeComponent(dummyModel);
}
});

View file

@ -48,9 +48,11 @@ import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
import org.keycloak.protocol.oidc.mappers.UserSessionNoteMapper;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.ldap.mappers.FullNameLDAPStorageMapper;
import org.keycloak.storage.ldap.mappers.FullNameLDAPStorageMapperFactory;
import org.keycloak.testsuite.federation.DummyUserFederationProviderFactory;
import java.util.List;
import java.util.Map;
@ -279,8 +281,6 @@ public class ImportTest extends AbstractModelTest {
Assert.assertEquals("googleSecret", google.getConfig().get("clientSecret"));
// Test federation providers
List<UserFederationProviderModel> fedProviders = realm.getUserFederationProviders();
Assert.assertTrue(fedProviders.size() == 0);
List<UserStorageProviderModel> storageProviders = realm.getUserStorageProviders();
Assert.assertTrue(storageProviders.size() == 2);
UserStorageProviderModel ldap1 = storageProviders.get(0);
@ -294,8 +294,6 @@ public class ImportTest extends AbstractModelTest {
Assert.assertEquals("ldap://bar", ldap2.getConfig().getFirst(LDAPConstants.CONNECTION_URL));
// Test federation mappers
Set<UserFederationMapperModel> userFedMappers1 = realm.getUserFederationMappers();
Assert.assertTrue(userFedMappers1.size() == 0);
List<ComponentModel> fedMappers1 = realm.getComponents(ldap1.getId());
ComponentModel fullNameMapper = fedMappers1.iterator().next();
Assert.assertEquals("FullNameMapper", fullNameMapper.getName());
@ -304,8 +302,8 @@ public class ImportTest extends AbstractModelTest {
Assert.assertEquals("cn", fullNameMapper.getConfig().getFirst(FullNameLDAPStorageMapper.LDAP_FULL_NAME_ATTRIBUTE));
// Assert that federation link wasn't created during import
UserFederationProviderFactory factory = (UserFederationProviderFactory)session.getKeycloakSessionFactory().getProviderFactory(UserFederationProvider.class, "dummy");
Assert.assertNull(factory.getInstance(session, null).getUserByUsername(realm, "wburke"));
DummyUserFederationProviderFactory factory = (DummyUserFederationProviderFactory)session.getKeycloakSessionFactory().getProviderFactory(UserStorageProvider.class, "dummy");
Assert.assertNull(factory.create(session, null).getUserByUsername("wburke", realm));
// Test builtin authentication flows
AuthenticationFlowModel clientFlow = realm.getClientAuthenticationFlow();

View file

@ -1,175 +0,0 @@
/*
* 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.testsuite.model;
import org.junit.Assert;
import org.junit.Test;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationMapperModel;
import org.keycloak.models.UserFederationProviderModel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class UserFederationModelTest extends AbstractModelTest {
@Test
public void federationMapperCrudTest() {
RealmModel realm = realmManager.createRealm("test-realm");
UserFederationProviderModel fedProvider = realm.addUserFederationProvider("dummy", new TreeMap<String, String>(), 1, "my-cool-provider", -1, -1, 0);
UserFederationProviderModel fedProvider2 = realm.addUserFederationProvider("dummy", new TreeMap<String, String>(), 1, "my-cool-provider2", -1, -1, 0);
UserFederationMapperModel mapperModel1 = createMapper("name1", fedProvider.getId(), "key1", "value1");
UserFederationMapperModel mapperModel2 = createMapper("name2", fedProvider.getId(), "key2", "value2");
UserFederationMapperModel mapperModel3 = createMapper("name1", fedProvider2.getId(), "key3", "value3");
mapperModel1 = realm.addUserFederationMapper(mapperModel1);
mapperModel2 = realm.addUserFederationMapper(mapperModel2);
mapperModel3 = realm.addUserFederationMapper(mapperModel3);
commit();
try {
UserFederationMapperModel conflictMapper = createMapper("name1", fedProvider.getId(), "key4", "value4");
realmManager.getRealmByName("test-realm").addUserFederationMapper(conflictMapper);
commit();
Assert.fail("Don't expect to end here");
} catch (ModelDuplicateException expected) {
}
realm = realmManager.getRealmByName("test-realm");
Set<UserFederationMapperModel> mappers = realm.getUserFederationMappers();
Assert.assertEquals(3, mappers.size());
Assert.assertTrue(mappers.contains(mapperModel1));
Assert.assertTrue(mappers.contains(mapperModel2));
Assert.assertTrue(mappers.contains(mapperModel3));
mappers = realm.getUserFederationMappersByFederationProvider(fedProvider.getId());
Assert.assertEquals(2, mappers.size());
Assert.assertTrue(mappers.contains(mapperModel1));
Assert.assertTrue(mappers.contains(mapperModel2));
mapperModel3.getConfig().put("otherKey", "otherValue");
realm.updateUserFederationMapper(mapperModel3);
commit();
realm = realmManager.getRealmByName("test-realm");
mapperModel3 = realm.getUserFederationMapperById(mapperModel3.getId());
Assert.assertEquals(2, mapperModel3.getConfig().size());
Assert.assertEquals("value3", mapperModel3.getConfig().get("key3"));
Assert.assertEquals("otherValue", mapperModel3.getConfig().get("otherKey"));
}
@Test
public void federationProviderRemovalTest() {
RealmModel realm = realmManager.createRealm("test-realm");
UserFederationProviderModel fedProvider = realm.addUserFederationProvider("dummy", new TreeMap<String, String>(), 1, "my-cool-provider", -1, -1, 0);
UserFederationProviderModel fedProvider2 = realm.addUserFederationProvider("dummy", new TreeMap<String, String>(), 1, "my-cool-provider2", -1, -1, 0);
UserFederationMapperModel mapperModel1 = createMapper("name1", fedProvider.getId(), "key1", "value1");
UserFederationMapperModel mapperModel2 = createMapper("name2", fedProvider.getId(), "key2", "value2");
UserFederationMapperModel mapperModel3 = createMapper("name1", fedProvider2.getId(), "key3", "value3");
mapperModel1 = realm.addUserFederationMapper(mapperModel1);
mapperModel2 = realm.addUserFederationMapper(mapperModel2);
mapperModel3 = realm.addUserFederationMapper(mapperModel3);
commit();
realmManager.getRealmByName("test-realm").removeUserFederationProvider(fedProvider);
commit();
realm = realmManager.getRealmByName("test-realm");
Set<UserFederationMapperModel> mappers = realm.getUserFederationMappers();
Assert.assertEquals(1, mappers.size());
Assert.assertEquals(mapperModel3, mappers.iterator().next());
realm = realmManager.getRealmByName("test-realm");
realmManager.removeRealm(realm);
commit();
}
@Test
public void federationProvidersSetTest() {
RealmModel realm = realmManager.createRealm("test-realm");
UserFederationProviderModel ldapProvider = new UserFederationProviderModel(null, "ldap", new TreeMap<String, String>(), 1, "my-cool-provider", -1, -1, 0);
realm.setUserFederationProviders(Arrays.asList(ldapProvider));
commit();
realm = realmManager.getRealmByName("test-realm");
List<UserFederationProviderModel> fedProviders = realm.getUserFederationProviders();
Assert.assertEquals(1, fedProviders.size());
ldapProvider = fedProviders.get(0);
Set<UserFederationMapperModel> fedMappers = realmManager.getRealmByName("test-realm").getUserFederationMappersByFederationProvider(ldapProvider.getId());
UserFederationProviderModel dummyProvider = new UserFederationProviderModel(null, "dummy", new TreeMap<String, String>(), 1, "my-cool-provider", -1, -1, 0);
try {
realm.setUserFederationProviders(Arrays.asList(ldapProvider, dummyProvider));
commit();
Assert.fail("Don't expect to end here");
} catch (ModelDuplicateException expected) {
}
dummyProvider.setDisplayName("my-cool-provider2");
realm.setUserFederationProviders(Arrays.asList(ldapProvider, dummyProvider));
commit();
realm = realmManager.getRealmByName("test-realm");
Assert.assertEquals(fedMappers.size(), realm.getUserFederationMappersByFederationProvider(ldapProvider.getId()).size());
realm.setUserFederationProviders(new ArrayList<UserFederationProviderModel>());
commit();
realm = realmManager.getRealmByName("test-realm");
Assert.assertTrue(realm.getUserFederationMappersByFederationProvider(ldapProvider.getId()).isEmpty());
}
private UserFederationMapperModel createMapper(String name, String fedProviderId, String... config) {
UserFederationMapperModel mapperModel = new UserFederationMapperModel();
mapperModel.setName(name);
mapperModel.setFederationMapperType("someType");
mapperModel.setFederationProviderId(fedProviderId);
Map<String, String> configMap = new TreeMap<String, String>();
String key = null;
for (String configEntry : config) {
if (key == null) {
key = configEntry;
} else {
configMap.put(key, configEntry);
key = null;
}
}
mapperModel.setConfig(configMap);
return mapperModel;
}
}

View file

@ -17,11 +17,14 @@
package org.keycloak.testsuite.util.cli;
import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.services.managers.UsersSyncManager;
import org.keycloak.services.managers.UserStorageSyncManager;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.testsuite.federation.DummyUserFederationProviderFactory;
import org.keycloak.testsuite.federation.sync.SyncDummyUserFederationProviderFactory;
import java.util.HashMap;
@ -38,25 +41,33 @@ public class SyncDummyFederationProviderCommand extends AbstractCommand {
int changedSyncPeriod = getIntArg(1);
RealmModel realm = session.realms().getRealmByName("master");
UserFederationProviderModel fedProviderModel = KeycloakModelUtils.findUserFederationProviderByDisplayName("cluster-dummy", realm);
UserStorageProviderModel fedProviderModel = KeycloakModelUtils.findUserStorageProviderByName("cluster-dummy", realm);
if (fedProviderModel == null) {
Map<String, String> cfg = new HashMap<>();
MultivaluedHashMap<String, String> cfg = fedProviderModel.getConfig();
updateConfig(cfg, waitTime);
fedProviderModel = realm.addUserFederationProvider(SyncDummyUserFederationProviderFactory.SYNC_PROVIDER_ID, cfg, 1, "cluster-dummy", -1, changedSyncPeriod, -1);
UserStorageProviderModel model = new UserStorageProviderModel();
model.setProviderId(SyncDummyUserFederationProviderFactory.SYNC_PROVIDER_ID);
model.setPriority(1);
model.setName("cluster-dummy");
model.setFullSyncPeriod(-1);
model.setChangedSyncPeriod(changedSyncPeriod);
model.setLastSync(-1);
fedProviderModel = new UserStorageProviderModel(realm.addComponentModel(model));
} else {
Map<String, String> cfg = fedProviderModel.getConfig();
MultivaluedHashMap<String, String> cfg = fedProviderModel.getConfig();
updateConfig(cfg, waitTime);
fedProviderModel.setChangedSyncPeriod(changedSyncPeriod);
realm.updateUserFederationProvider(fedProviderModel);
realm.updateComponent(fedProviderModel);
}
new UsersSyncManager().notifyToRefreshPeriodicSync(session, realm, fedProviderModel, false);
new UserStorageSyncManager().notifyToRefreshPeriodicSync(session, realm, fedProviderModel, false);
log.infof("User federation provider created and sync was started", waitTime);
}
private void updateConfig(Map<String, String> cfg, int waitTime) {
cfg.put(SyncDummyUserFederationProviderFactory.WAIT_TIME, String.valueOf(waitTime));
private void updateConfig(MultivaluedHashMap<String, String> cfg, int waitTime) {
cfg.putSingle(SyncDummyUserFederationProviderFactory.WAIT_TIME, String.valueOf(waitTime));
}

View file

@ -1,18 +0,0 @@
#
# 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.
#
org.keycloak.testsuite.federation.sync.SyncDummyUserFederationProviderFactory

View file

@ -1,2 +1,3 @@
org.keycloak.testsuite.federation.sync.SyncDummyUserFederationProviderFactory
org.keycloak.testsuite.federation.storage.UserPropertyFileStorageFactory
org.keycloak.testsuite.federation.storage.UserMapStorageFactory