Details
diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProvider.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProvider.java
index ebde5d3..c772d36 100755
--- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProvider.java
+++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProvider.java
@@ -174,8 +174,9 @@ public class LDAPStorageProvider implements UserStorageProvider,
@Override
public UserModel addUser(RealmModel realm, String username) {
- if (editMode == UserStorageProvider.EditMode.READ_ONLY || editMode == UserStorageProvider.EditMode.UNSYNCED) throw new IllegalStateException("Registration is not supported by this ldap server");
- if (!synchronizeRegistrations()) throw new IllegalStateException("Registration is not supported by this ldap server");
+ if (!synchronizeRegistrations()) {
+ return null;
+ }
UserModel user = session.userLocalStorage().addUser(realm, username);
user.setFederationLink(model.getId());
LDAPObject ldapUser = LDAPUtils.addUserToLDAP(this, realm, user);
diff --git a/server-spi/src/main/java/org/keycloak/storage/user/UserRegistrationProvider.java b/server-spi/src/main/java/org/keycloak/storage/user/UserRegistrationProvider.java
index b3ec00d..650f8b0 100644
--- a/server-spi/src/main/java/org/keycloak/storage/user/UserRegistrationProvider.java
+++ b/server-spi/src/main/java/org/keycloak/storage/user/UserRegistrationProvider.java
@@ -29,8 +29,35 @@ import org.keycloak.models.UserModel;
*/
public interface UserRegistrationProvider {
+ /**
+ * All storage providers that implement this interface will be looped through.
+ * If this method returns null, then the next storage provider's addUser() method will be called.
+ * If no storage providers handle the add, then the user will be created in local storage.
+ *
+ * Returning null is useful when you want optional support for adding users. For example,
+ * our LDAP provider can enable and disable the ability to add users.
+ *
+ * @param realm
+ * @param username
+ * @return
+ */
UserModel addUser(RealmModel realm, String username);
+ /**
+ * Called if user originated from this provider.
+ *
+ *
+ * If a local user is linked to this provider, this method will be called before
+ * local storage's removeUser() method is invoked.
+
+ * If you are using an import strategy, and this is a local user linked to this provider,
+ * this method will be called before local storage's removeUser() method is invoked. Also,
+ * you DO NOT need to remove the imported user. The runtime will handle this for you.
+ *
+ * @param realm
+ * @param user
+ * @return
+ */
boolean removeUser(RealmModel realm, UserModel user);
diff --git a/services/src/main/java/org/keycloak/storage/UserStorageManager.java b/services/src/main/java/org/keycloak/storage/UserStorageManager.java
index 906e225..4924f19 100755
--- a/services/src/main/java/org/keycloak/storage/UserStorageManager.java
+++ b/services/src/main/java/org/keycloak/storage/UserStorageManager.java
@@ -116,10 +116,11 @@ public class UserStorageManager implements UserProvider, OnUserCache {
@Override
public UserModel addUser(RealmModel realm, String username) {
- UserRegistrationProvider registry = getFirstStorageProvider(session, realm, UserRegistrationProvider.class);
- if (registry != null) {
- return registry.addUser(realm, username);
+ for (UserRegistrationProvider provider : getStorageProviders(session, realm, UserRegistrationProvider.class)) {
+ UserModel user = provider.addUser(realm, username);
+ if (user != null) return user;
}
+
return localStorage().addUser(realm, username.toLowerCase());
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPProvidersIntegrationTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPProvidersIntegrationTest.java
index 8881e42..fdb73d7 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPProvidersIntegrationTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPProvidersIntegrationTest.java
@@ -149,6 +149,27 @@ public class LDAPProvidersIntegrationTest {
//
// }
+ /**
+ * KEYCLOAK-3986
+ *
+ */
+ @Test
+ public void testSyncRegistrationOff() {
+ KeycloakSession session = keycloakRule.startSession();
+ try {
+ RealmManager manager = new RealmManager(session);
+ RealmModel appRealm = manager.getRealm("test");
+ UserStorageProviderModel newModel = new UserStorageProviderModel(ldapModel);
+ newModel.getConfig().putSingle(LDAPConstants.SYNC_REGISTRATIONS, "false");
+ appRealm.updateComponent(newModel);
+ UserModel newUser1 = session.users().addUser(appRealm, "newUser1");
+ Assert.assertNull(newUser1.getFederationLink());
+ } finally {
+ keycloakRule.stopSession(session, false);
+ }
+
+
+ }
@Test
public void caseInSensitiveImport() {