use of org.keycloak.storage.user.SynchronizationResult in project keycloak by keycloak.
the class LDAPSyncTest method test08LDAPGroupSyncAfterGroupRename.
@Test
public void test08LDAPGroupSyncAfterGroupRename() {
testingClient.server().run(session -> {
LDAPTestContext ctx = LDAPTestContext.init(session);
RealmModel appRealm = ctx.getRealm();
String descriptionAttrName = LDAPTestUtils.getGroupDescriptionLDAPAttrName(ctx.getLdapProvider());
// Add group mapper
LDAPTestUtils.addOrUpdateGroupMapper(appRealm, ctx.getLdapModel(), LDAPGroupMapperMode.READ_ONLY, descriptionAttrName);
LDAPObject group1 = LDAPTestUtils.createLDAPGroup(session, appRealm, ctx.getLdapModel(), "group1", descriptionAttrName, "group1 - description");
LDAPObject group2 = LDAPTestUtils.createLDAPGroup(session, appRealm, ctx.getLdapModel(), "group2", descriptionAttrName, "group2 - description");
LDAPUtils.addMember(ctx.getLdapProvider(), MembershipType.DN, LDAPConstants.MEMBER, "not-used", group2, group1);
ComponentModel mapperModel = LDAPTestUtils.getSubcomponentByName(appRealm, ctx.getLdapModel(), "groupsMapper");
LDAPTestUtils.updateGroupMapperConfigOptions(mapperModel, GroupMapperConfig.PRESERVE_GROUP_INHERITANCE, "false");
ctx.getRealm().updateComponent(mapperModel);
// sync groups to Keycloak
new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(appRealm);
});
testingClient.server().run(session -> {
LDAPTestContext ctx = LDAPTestContext.init(session);
RealmModel appRealm = ctx.getRealm();
GroupModel kcGroup1 = KeycloakModelUtils.findGroupByPath(appRealm, "/group1");
String descriptionAttrName = LDAPTestUtils.getGroupDescriptionLDAPAttrName(ctx.getLdapProvider());
Assert.assertEquals("group1 - description", kcGroup1.getFirstAttribute(descriptionAttrName));
});
testingClient.server().run(session -> {
LDAPTestContext ctx = LDAPTestContext.init(session);
RealmModel appRealm = ctx.getRealm();
String descriptionAttrName = LDAPTestUtils.getGroupDescriptionLDAPAttrName(ctx.getLdapProvider());
// Add group mapper
LDAPTestUtils.addOrUpdateGroupMapper(appRealm, ctx.getLdapModel(), LDAPGroupMapperMode.LDAP_ONLY, descriptionAttrName);
ComponentModel mapperModel = LDAPTestUtils.getSubcomponentByName(appRealm, ctx.getLdapModel(), "groupsMapper");
LDAPStorageProvider ldapProvider = LDAPTestUtils.getLdapProvider(session, ctx.getLdapModel());
GroupLDAPStorageMapper groupMapper = LDAPTestUtils.getGroupMapper(mapperModel, ldapProvider, appRealm);
LDAPObject group1Loaded = groupMapper.loadLDAPGroupByName("group1");
// update group name and description
group1Loaded.setSingleAttribute(group1Loaded.getRdnAttributeNames().get(0), "group5");
group1Loaded.setSingleAttribute(descriptionAttrName, "group5 - description");
LDAPTestUtils.updateLDAPGroup(session, appRealm, ctx.getLdapModel(), group1Loaded);
// sync to Keycloak should pass without an error
SynchronizationResult syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(appRealm);
Assert.assertThat(syncResult.getFailed(), Matchers.is(0));
});
testingClient.server().run(session -> {
LDAPTestContext ctx = LDAPTestContext.init(session);
RealmModel appRealm = ctx.getRealm();
// load previously synced group (a new group has been created in Keycloak)
GroupModel kcGroup5 = KeycloakModelUtils.findGroupByPath(appRealm, "/group5");
String descriptionAttrName = LDAPTestUtils.getGroupDescriptionLDAPAttrName(ctx.getLdapProvider());
Assert.assertEquals("group5 - description", kcGroup5.getFirstAttribute(descriptionAttrName));
});
}
use of org.keycloak.storage.user.SynchronizationResult in project keycloak by keycloak.
the class UserStorageSyncManager method syncChangedUsers.
public SynchronizationResult syncChangedUsers(final KeycloakSessionFactory sessionFactory, final String realmId, final UserStorageProviderModel provider) {
UserStorageProviderFactory factory = (UserStorageProviderFactory) sessionFactory.getProviderFactory(UserStorageProvider.class, provider.getProviderId());
if (!(factory instanceof ImportSynchronization) || !provider.isImportEnabled() || !provider.isEnabled()) {
return SynchronizationResult.ignored();
}
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 = provider.getId() + "::sync";
// 30 seconds minimal timeout for now
int timeout = Math.max(30, provider.getChangedSyncPeriod());
holder.result = clusterProvider.executeIfNotExecuted(taskKey, timeout, new Callable<SynchronizationResult>() {
@Override
public SynchronizationResult call() throws Exception {
// See when we did last sync.
int oldLastSync = provider.getLastSync();
updateLastSyncInterval(sessionFactory, provider, realmId);
return ((ImportSynchronization) factory).syncSince(Time.toDate(oldLastSync), sessionFactory, realmId, provider);
}
});
}
});
if (holder.result == null || !holder.result.isExecuted()) {
logger.debugf("syncChangedUsers for federation provider %s was ignored as it's already in progress", provider.getName());
return SynchronizationResult.ignored();
} else {
return holder.result.getResult();
}
}
use of org.keycloak.storage.user.SynchronizationResult in project keycloak by keycloak.
the class UserStorageSyncManager method syncAllUsers.
public SynchronizationResult syncAllUsers(final KeycloakSessionFactory sessionFactory, final String realmId, final UserStorageProviderModel provider) {
UserStorageProviderFactory factory = (UserStorageProviderFactory) sessionFactory.getProviderFactory(UserStorageProvider.class, provider.getProviderId());
if (!(factory instanceof ImportSynchronization) || !provider.isImportEnabled() || !provider.isEnabled()) {
return SynchronizationResult.ignored();
}
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 = provider.getId() + "::sync";
// 30 seconds minimal timeout for now
int timeout = Math.max(30, provider.getFullSyncPeriod());
holder.result = clusterProvider.executeIfNotExecuted(taskKey, timeout, new Callable<SynchronizationResult>() {
@Override
public SynchronizationResult call() throws Exception {
updateLastSyncInterval(sessionFactory, provider, realmId);
return ((ImportSynchronization) factory).sync(sessionFactory, realmId, provider);
}
});
}
});
if (holder.result == null || !holder.result.isExecuted()) {
logger.debugf("syncAllUsers for federation provider %s was ignored as it's already in progress", provider.getName());
return SynchronizationResult.ignored();
} else {
return holder.result.getResult();
}
}
use of org.keycloak.storage.user.SynchronizationResult in project keycloak by keycloak.
the class LDAPGroupMapperSyncWithGroupsPathTest method test02_syncWithDropNonExistingGroups.
@Test
public void test02_syncWithDropNonExistingGroups() throws Exception {
testingClient.server().run(session -> {
LDAPTestContext ctx = LDAPTestContext.init(session);
RealmModel realm = ctx.getRealm();
ComponentModel mapperModel = LDAPTestUtils.getSubcomponentByName(realm, ctx.getLdapModel(), "groupsMapper");
// KEYCLOAK-11415 - This test requires the group mapper to be configured with preserve group inheritance
// set to 'true' (the default setting). If preservation of group inheritance isn't configured, some of
// the previous test(s) failed to cleanup properly. Check the requirement as part of running the test
Assert.assertEquals(mapperModel.getConfig().getFirst("preserve.group.inheritance"), "true");
// Sync groups with inheritance
SynchronizationResult syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(realm);
LDAPTestAsserts.assertSyncEquals(syncResult, 3, 0, 0, 0);
// Assert groups are imported to keycloak including their inheritance from LDAP
GroupModel kcGroup1 = KeycloakModelUtils.findGroupByPath(realm, LDAP_GROUPS_PATH + "/group1");
Assert.assertNotNull(KeycloakModelUtils.findGroupByPath(realm, LDAP_GROUPS_PATH + "/group1/group11"));
Assert.assertNotNull(KeycloakModelUtils.findGroupByPath(realm, LDAP_GROUPS_PATH + "/group1/group12"));
Assert.assertEquals(2, kcGroup1.getSubGroupsStream().count());
// Create some new groups in keycloak
GroupModel groupsPathGroup = KeycloakModelUtils.findGroupByPath(realm, LDAP_GROUPS_PATH);
realm.createGroup("model1", groupsPathGroup);
realm.createGroup("model2", kcGroup1);
realm.createGroup("outside");
// Sync groups again from LDAP. Nothing deleted
syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(realm);
LDAPTestAsserts.assertSyncEquals(syncResult, 0, 3, 0, 0);
Assert.assertNotNull(KeycloakModelUtils.findGroupByPath(realm, LDAP_GROUPS_PATH + "/group1/group11"));
Assert.assertNotNull(KeycloakModelUtils.findGroupByPath(realm, LDAP_GROUPS_PATH + "/group1/group12"));
Assert.assertNotNull(KeycloakModelUtils.findGroupByPath(realm, LDAP_GROUPS_PATH + "/model1"));
Assert.assertNotNull(KeycloakModelUtils.findGroupByPath(realm, LDAP_GROUPS_PATH + "/group1/model2"));
Assert.assertNotNull(KeycloakModelUtils.findGroupByPath(realm, "/outside"));
// Update group mapper to drop non-existing groups during sync
LDAPTestUtils.updateGroupMapperConfigOptions(mapperModel, GroupMapperConfig.DROP_NON_EXISTING_GROUPS_DURING_SYNC, "true");
realm.updateComponent(mapperModel);
// Sync groups again from LDAP. Assert LDAP non-existing groups deleted
syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(realm);
Assert.assertEquals(3, syncResult.getUpdated());
Assert.assertTrue(syncResult.getRemoved() == 2);
// Sync and assert groups updated
Assert.assertNotNull(KeycloakModelUtils.findGroupByPath(realm, LDAP_GROUPS_PATH + "/group1/group11"));
Assert.assertNotNull(KeycloakModelUtils.findGroupByPath(realm, LDAP_GROUPS_PATH + "/group1/group12"));
Assert.assertNull(KeycloakModelUtils.findGroupByPath(realm, LDAP_GROUPS_PATH + "/model1"));
Assert.assertNull(KeycloakModelUtils.findGroupByPath(realm, LDAP_GROUPS_PATH + "/group1/model2"));
Assert.assertNotNull(KeycloakModelUtils.findGroupByPath(realm, "/outside"));
});
}
use of org.keycloak.storage.user.SynchronizationResult in project keycloak by keycloak.
the class UserStorageProviderResource method syncUsers.
/**
* Trigger sync of users
*
* Action can be "triggerFullSync" or "triggerChangedUsersSync"
*
* @param id
* @param action
* @return
*/
@POST
@Path("{id}/sync")
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public SynchronizationResult syncUsers(@PathParam("id") String id, @QueryParam("action") String action) {
auth.users().requireManage();
ComponentModel model = realm.getComponent(id);
if (model == null) {
throw new NotFoundException("Could not find component");
}
if (!model.getProviderType().equals(UserStorageProvider.class.getName())) {
throw new NotFoundException("found, but not a UserStorageProvider");
}
UserStorageProviderModel providerModel = new UserStorageProviderModel(model);
logger.debug("Syncing users");
UserStorageSyncManager syncManager = new UserStorageSyncManager();
SynchronizationResult syncResult;
if ("triggerFullSync".equals(action)) {
syncResult = syncManager.syncAllUsers(session.getKeycloakSessionFactory(), realm.getId(), providerModel);
} else if ("triggerChangedUsersSync".equals(action)) {
syncResult = syncManager.syncChangedUsers(session.getKeycloakSessionFactory(), realm.getId(), providerModel);
} else if (action == null || action == "") {
logger.debug("Missing action");
throw new BadRequestException("Missing action");
} else {
logger.debug("Unknown action: " + action);
throw new BadRequestException("Unknown action: " + action);
}
Map<String, Object> eventRep = new HashMap<>();
eventRep.put("action", action);
eventRep.put("result", syncResult);
adminEvent.operation(OperationType.ACTION).resourcePath(session.getContext().getUri()).representation(eventRep).success();
return syncResult;
}
Aggregations