lastSync value into COMPONENT_CONFIG is always updated

Closes https://github.com/keycloak/keycloak/issues/17022
This commit is contained in:
rmartinc 2023-02-13 09:42:22 +01:00 committed by Marek Posolda
parent cb78ea06b0
commit 9995a3cdd4
4 changed files with 103 additions and 6 deletions

View file

@ -105,8 +105,12 @@ public class UserStorageSyncManager {
@Override
public SynchronizationResult call() throws Exception {
updateLastSyncInterval(sessionFactory, provider, realmId);
return ((ImportSynchronization)factory).sync(sessionFactory, realmId, provider);
int lastSync = Time.currentTime();
SynchronizationResult result = ((ImportSynchronization)factory).sync(sessionFactory, realmId, provider);
if (!result.isIgnored()) {
updateLastSyncInterval(sessionFactory, provider, realmId, lastSync);
}
return result;
}
});
@ -147,8 +151,12 @@ public class UserStorageSyncManager {
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);
int lastSync = Time.currentTime();
SynchronizationResult result = ((ImportSynchronization)factory).syncSince(Time.toDate(oldLastSync), sessionFactory, realmId, provider);
if (!result.isIgnored()) {
updateLastSyncInterval(sessionFactory, provider, realmId, lastSync);
}
return result;
}
});
@ -262,7 +270,7 @@ public class UserStorageSyncManager {
}
// Update interval of last sync for given UserFederationProviderModel. Do it in separate transaction
private static void updateLastSyncInterval(final KeycloakSessionFactory sessionFactory, UserStorageProviderModel provider, final String realmId) {
private static void updateLastSyncInterval(final KeycloakSessionFactory sessionFactory, UserStorageProviderModel provider, final String realmId, final int lastSync) {
KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
@Override
@ -272,7 +280,6 @@ public class UserStorageSyncManager {
.filter(persistentFedProvider -> Objects.equals(provider.getId(), persistentFedProvider.getId()))
.forEachOrdered(persistentFedProvider -> {
// Update persistent provider in DB
int lastSync = Time.currentTime();
persistentFedProvider.setLastSync(lastSync);
persistentRealm.updateComponent(persistentFedProvider);

View file

@ -0,0 +1,49 @@
/*
* Copyright 2023 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.sync;
import java.util.Date;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.user.SynchronizationResult;
import org.keycloak.testsuite.federation.DummyUserFederationProviderFactory;
/**
* <p>Test UserStorageProviderFactory in which sync methods are always ignored.</p>
*
* @author rmartinc
*/
public class IgnoredDummyUserFederationProviderFactory extends DummyUserFederationProviderFactory {
public static final String IGNORED_PROVIDER_ID = "ignored-dummy";
@Override
public String getId() {
return IGNORED_PROVIDER_ID;
}
@Override
public SynchronizationResult sync(KeycloakSessionFactory sessionFactory, String realmId, UserStorageProviderModel model) {
return SynchronizationResult.ignored();
}
@Override
public SynchronizationResult syncSince(Date lastSync, KeycloakSessionFactory sessionFactory, String realmId, UserStorageProviderModel model) {
return SynchronizationResult.ignored();
}
}

View file

@ -5,3 +5,4 @@ org.keycloak.testsuite.federation.UserMapStorageFactory
org.keycloak.testsuite.federation.UserPropertyFileStorageFactory
org.keycloak.testsuite.federation.PassThroughFederatedUserStorageProviderFactory
org.keycloak.testsuite.federation.sync.SyncDummyUserFederationProviderFactory
org.keycloak.testsuite.federation.sync.IgnoredDummyUserFederationProviderFactory

View file

@ -320,6 +320,46 @@ public class SyncFederationTest extends AbstractAuthTest {
});
}
@Test
public void test04IgnoredSync() throws Exception {
// Add IgnoredDummyUserFederationProviderFactory provider
testingClient.server().run(session -> {
RealmModel appRealm = session.realms().getRealmByName(AuthRealm.TEST);
UserStorageProviderModel model = new UserStorageProviderModel();
model.setProviderId(IgnoredDummyUserFederationProviderFactory.IGNORED_PROVIDER_ID);
model.setPriority(1);
model.setName("test-sync-dummy");
model.setFullSyncPeriod(-1);
model.setChangedSyncPeriod(-1);
model.setLastSync(0);
appRealm.addComponentModel(model);
});
// run both sync methods that will be ignored
testingClient.server().run(session -> {
RealmModel appRealm = session.realms().getRealmByName(AuthRealm.TEST);
UserStorageProviderModel dummyModel = findDummyProviderModel(appRealm);
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
SynchronizationResult syncResult = UserStorageSyncManager.syncAllUsers(sessionFactory, appRealm.getId(), dummyModel);
Assert.assertTrue(syncResult.isIgnored());
syncResult = UserStorageSyncManager.syncChangedUsers(sessionFactory, appRealm.getId(), dummyModel);
Assert.assertTrue(syncResult.isIgnored());
});
// assert the last sync is not updated
testingClient.server().run(session -> {
RealmModel appRealm = session.realms().getRealmByName(AuthRealm.TEST);
UserStorageProviderModel dummyModel = findDummyProviderModel(appRealm);
Assert.assertEquals(0, dummyModel.getLastSync());
});
// remove provider
testingClient.server().run(session -> {
RealmModel appRealm = session.realms().getRealmByName(AuthRealm.TEST);
UserStorageProviderModel dummyModel = findDummyProviderModel(appRealm);
appRealm.removeComponent(dummyModel);
});
}
private static void sleep(long ms) {
try {