| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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.apache.jackrabbit.oak.spi.security.authentication.external.impl.jmx; |
| |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.Map; |
| import javax.jcr.RepositoryException; |
| import javax.jcr.ValueFactory; |
| |
| import com.google.common.collect.ImmutableMap; |
| import com.google.common.collect.ImmutableSet; |
| import org.apache.jackrabbit.api.security.user.Authorizable; |
| import org.apache.jackrabbit.api.security.user.Group; |
| import org.apache.jackrabbit.api.security.user.User; |
| import org.apache.jackrabbit.api.security.user.UserManager; |
| import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalGroup; |
| import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentity; |
| import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityException; |
| import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProvider; |
| import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProviderManager; |
| import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityRef; |
| import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalUser; |
| import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncContext; |
| import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncException; |
| import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncHandler; |
| import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncManager; |
| import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncResult; |
| import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncedIdentity; |
| import org.apache.jackrabbit.oak.spi.security.authentication.external.TestIdentityProvider; |
| import org.apache.jackrabbit.oak.spi.security.authentication.external.basic.DefaultSyncContext; |
| import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DefaultSyncHandler; |
| import org.apache.jackrabbit.oak.spi.security.user.UserConstants; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertNull; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| public class SyncMBeanImplTest extends AbstractJmxTest { |
| |
| private static final String SYNC_NAME = "testSyncName"; |
| |
| private SyncMBeanImpl syncMBean; |
| |
| private SyncManager syncMgr; |
| private ExternalIdentityProviderManager idpMgr; |
| |
| @Before |
| public void before() throws Exception { |
| super.before(); |
| |
| syncMgr = new SyncManager() { |
| @Nullable |
| @Override |
| public SyncHandler getSyncHandler(@NotNull String name) { |
| if (SYNC_NAME.equals(name)) { |
| return new DefaultSyncHandler(syncConfig); |
| } else if (ThrowingSyncHandler.NAME.equals(name)) { |
| return new ThrowingSyncHandler(false); |
| } else if (ThrowingSyncHandler.NAME_ALLOWS_IDENTITY_LISTING.equals(name)) { |
| return new ThrowingSyncHandler(true); |
| } else { |
| return null; |
| } |
| } |
| }; |
| idpMgr = new ExternalIdentityProviderManager() { |
| @Nullable |
| @Override |
| public ExternalIdentityProvider getProvider(@NotNull String name) { |
| if (name.equals(idp.getName())) { |
| return idp; |
| } else { |
| return null; |
| } |
| } |
| }; |
| |
| syncMBean = createSyncMBeanImpl(SYNC_NAME, idp.getName()); |
| } |
| |
| private Map<String, String> getExpectedUserResult(String expectedOp, boolean includeGroups) throws ExternalIdentityException { |
| Map<String, String> expected = new HashMap<>(); |
| Iterator<ExternalUser> it = idp.listUsers(); |
| while (it.hasNext()) { |
| ExternalUser eu = it.next(); |
| expected.put(eu.getId(), expectedOp); |
| if (includeGroups) { |
| for (ExternalIdentityRef ref : eu.getDeclaredGroups()) { |
| expected.put(ref.getId(), expectedOp); |
| } |
| } |
| } |
| return expected; |
| } |
| |
| private SyncMBeanImpl createSyncMBeanImpl(@NotNull String syncHandlerName, @NotNull String idpName) { |
| return new SyncMBeanImpl(getContentRepository(), getSecurityProvider(), syncMgr, syncHandlerName, idpMgr, idpName); |
| } |
| |
| private SyncMBeanImpl createThrowingSyncMBean(boolean allowListIdentities) { |
| String name = (allowListIdentities) ? ThrowingSyncHandler.NAME_ALLOWS_IDENTITY_LISTING : ThrowingSyncHandler.NAME; |
| return new SyncMBeanImpl(getContentRepository(), getSecurityProvider(), syncMgr, name, idpMgr, idp.getName()); |
| } |
| |
| @Test |
| public void testGetSyncHandlerName() { |
| assertEquals(SYNC_NAME, syncMBean.getSyncHandlerName()); |
| } |
| |
| @Test |
| public void testInvalidSyncHandlerName() { |
| SyncMBeanImpl syncMBean = createSyncMBeanImpl("invalid", idp.getName()); |
| assertEquals("invalid", syncMBean.getSyncHandlerName()); |
| |
| // calling any sync-operation must fail due to the invalid configuration |
| try { |
| syncMBean.syncAllExternalUsers(); |
| fail("syncAllExternalUsers with invalid SyncHandlerName must fail"); |
| } catch (IllegalArgumentException e) { |
| //success |
| } |
| } |
| |
| @Test |
| public void testGetIDPName() { |
| assertEquals(idp.getName(), syncMBean.getIDPName()); |
| } |
| |
| @Test |
| public void testInvalidIDPName() { |
| SyncMBeanImpl syncMBean = createSyncMBeanImpl(SYNC_NAME, "invalid"); |
| assertEquals("invalid", syncMBean.getIDPName()); |
| |
| // calling any sync-operation must fail due to the invalid configuration |
| try { |
| syncMBean.syncAllExternalUsers(); |
| fail("syncAllExternalUsers with invalid IDP name must fail"); |
| } catch (IllegalArgumentException e) { |
| //success |
| } |
| } |
| |
| /** |
| * test users have never been synced before => result must be NSA |
| */ |
| @Test |
| public void testSyncUsersBefore() { |
| String[] userIds = new String[] {TestIdentityProvider.ID_TEST_USER, TestIdentityProvider.ID_SECOND_USER}; |
| |
| String[] result = syncMBean.syncUsers(userIds, false); |
| assertResultMessages(result, ImmutableMap.of(TestIdentityProvider.ID_TEST_USER, "nsa", TestIdentityProvider.ID_SECOND_USER, "nsa")); |
| |
| result = syncMBean.syncUsers(userIds, true); |
| assertResultMessages(result, ImmutableMap.of(TestIdentityProvider.ID_TEST_USER, "nsa", TestIdentityProvider.ID_SECOND_USER, "nsa")); |
| } |
| |
| @Test |
| public void testSyncUsers() throws Exception { |
| sync(idp, TestIdentityProvider.ID_TEST_USER, false); |
| |
| String[] userIds = new String[]{TestIdentityProvider.ID_TEST_USER, TestIdentityProvider.ID_SECOND_USER}; |
| String[] result = syncMBean.syncUsers(userIds, false); |
| assertResultMessages(result, ImmutableMap.of(TestIdentityProvider.ID_TEST_USER, "upd", TestIdentityProvider.ID_SECOND_USER, "nsa")); |
| |
| result = syncMBean.syncUsers(userIds, true); |
| assertResultMessages(result, ImmutableMap.of(TestIdentityProvider.ID_TEST_USER, "upd", TestIdentityProvider.ID_SECOND_USER, "nsa")); |
| } |
| |
| @Test |
| public void testSyncUsersAlwaysForcesSync() throws Exception { |
| sync(idp, TestIdentityProvider.ID_TEST_USER, false); |
| |
| String[] userIds = new String[]{TestIdentityProvider.ID_TEST_USER, TestIdentityProvider.ID_SECOND_USER}; |
| syncConfig.user().setExpirationTime(Long.MAX_VALUE); |
| |
| String[]result = syncMBean.syncUsers(userIds, false); |
| assertResultMessages(result, ImmutableMap.of(TestIdentityProvider.ID_TEST_USER, "upd", TestIdentityProvider.ID_SECOND_USER, "nsa")); |
| } |
| |
| @Test |
| public void testSyncGroups() throws Exception { |
| sync(idp, "a", true); |
| |
| Map<String, String> expected = ImmutableMap.of("a", "upd"); |
| syncConfig.group().setExpirationTime(Long.MAX_VALUE); |
| |
| // force group sync is true by default => exp time is ignored |
| String[] result = syncMBean.syncUsers(expected.keySet().toArray(new String[expected.size()]), false); |
| assertResultMessages(result, expected); |
| } |
| |
| @Test |
| public void testSyncUsersPurge() throws Exception { |
| sync(new TestIdentityProvider.TestUser("thirdUser", idp.getName()), idp); |
| sync(new TestIdentityProvider.TestGroup("gr", idp.getName()), idp); |
| |
| UserManager userManager = getUserManager(); |
| Authorizable[] authorizables = new Authorizable[] { |
| userManager.getAuthorizable("thirdUser"), |
| userManager.getAuthorizable("gr") |
| }; |
| |
| for (Authorizable a : authorizables) { |
| String[] ids = new String[]{a.getID()}; |
| String[] result = syncMBean.syncUsers(ids, false); |
| assertResultMessages(result, a.getID(), "mis"); |
| assertNotNull(userManager.getAuthorizable(a.getID())); |
| |
| result = syncMBean.syncUsers(ids, true); |
| assertResultMessages(result, a.getID(), "del"); |
| assertNull(getUserManager().getAuthorizable(a.getID())); |
| } |
| } |
| |
| @Test |
| public void testSyncUsersNonExisting() { |
| String[] result = syncMBean.syncUsers(new String[] {"nonExisting"}, false); |
| assertResultMessages(result, "nonExisting", "nsa"); |
| } |
| |
| @Test |
| public void testSyncUsersLocal() { |
| String[] result = syncMBean.syncUsers(new String[] {UserConstants.DEFAULT_ANONYMOUS_ID}, false); |
| assertResultMessages(result, UserConstants.DEFAULT_ANONYMOUS_ID, "for"); |
| } |
| |
| @Test |
| public void testSyncUsersLocalPurge() throws Exception { |
| String[] result = syncMBean.syncUsers(new String[] {UserConstants.DEFAULT_ANONYMOUS_ID}, true); |
| assertResultMessages(result, UserConstants.DEFAULT_ANONYMOUS_ID, "for"); |
| |
| assertNotNull(getUserManager().getAuthorizable(UserConstants.DEFAULT_ANONYMOUS_ID)); |
| } |
| |
| @Test |
| public void testSyncUsersForeign() throws Exception { |
| // sync user from foreign IDP into the repository |
| SyncResult res = sync(foreignIDP, TestIdentityProvider.ID_TEST_USER, false); |
| assertNotNull(getUserManager().getAuthorizable(TestIdentityProvider.ID_TEST_USER)); |
| assertEquals(foreignIDP.getUser(TestIdentityProvider.ID_TEST_USER).getExternalId(), res.getIdentity().getExternalIdRef()); |
| |
| // syncUsers with testIDP must detect the foreign status |
| String[] result = syncMBean.syncUsers(new String[]{TestIdentityProvider.ID_TEST_USER}, false); |
| assertResultMessages(result, TestIdentityProvider.ID_TEST_USER, "for"); |
| assertNotNull(getUserManager().getAuthorizable(TestIdentityProvider.ID_TEST_USER)); |
| |
| // same expected with 'purge' set to true |
| result = syncMBean.syncUsers(new String[] {TestIdentityProvider.ID_TEST_USER}, true); |
| assertResultMessages(result, TestIdentityProvider.ID_TEST_USER, "for"); |
| assertNotNull(getUserManager().getAuthorizable(TestIdentityProvider.ID_TEST_USER)); |
| } |
| |
| @Test |
| public void testSyncGroupsForeign() throws Exception { |
| // sync user from foreign IDP into the repository |
| SyncResult res = sync(foreignIDP, "a", true); |
| assertNotNull(getUserManager().getAuthorizable("a")); |
| assertEquals(foreignIDP.getGroup("a").getExternalId(), res.getIdentity().getExternalIdRef()); |
| |
| // syncUsers with testIDP must detect the foreign status |
| String[] result = syncMBean.syncUsers(new String[]{"a"}, false); |
| assertResultMessages(result, "a", "for"); |
| assertNotNull(getUserManager().getAuthorizable("a")); |
| |
| // same expected with 'purge' set to true |
| result = syncMBean.syncUsers(new String[] {"a"}, true); |
| assertResultMessages(result, "a", "for"); |
| assertNotNull(getUserManager().getAuthorizable("a")); |
| } |
| |
| /** |
| * @see <a href="https://issues.apache.org/jira/browse/OAK-4360">OAK-4360</a> |
| */ |
| @Test |
| public void testSyncUserException() throws Exception { |
| User u = getUserManager().createUser(TestIdentityProvider.ID_EXCEPTION, null); |
| u.setProperty(DefaultSyncContext.REP_EXTERNAL_ID, getValueFactory().createValue(new ExternalIdentityRef(TestIdentityProvider.ID_EXCEPTION, idp.getName()).getString())); |
| root.commit(); |
| |
| String[] result = syncMBean.syncUsers(new String[]{TestIdentityProvider.ID_EXCEPTION}, false); |
| assertResultMessages(result, TestIdentityProvider.ID_EXCEPTION, "ERR"); |
| } |
| |
| @Test |
| public void testSyncUserThrowingHandler() throws Exception { |
| sync(idp, TestIdentityProvider.ID_TEST_USER, false); |
| |
| String[] result = createThrowingSyncMBean(false).syncUsers(new String[]{TestIdentityProvider.ID_TEST_USER}, false); |
| assertResultMessages(result, TestIdentityProvider.ID_TEST_USER, "ERR"); |
| } |
| |
| @Test |
| public void testInitialSyncExternalUsers() throws Exception { |
| ExternalUser externalUser = idp.getUser(TestIdentityProvider.ID_TEST_USER); |
| String[] externalId = new String[] {externalUser.getExternalId().getString()}; |
| |
| String[] result = syncMBean.syncExternalUsers(externalId); |
| assertResultMessages(result, TestIdentityProvider.ID_TEST_USER, "add"); |
| |
| UserManager userManager = getUserManager(); |
| User testUser = userManager.getAuthorizable(externalUser.getId(), User.class); |
| assertNotNull(testUser); |
| |
| for (ExternalIdentityRef groupRef : externalUser.getDeclaredGroups()) { |
| assertNotNull(userManager.getAuthorizable(groupRef.getId())); |
| } |
| } |
| |
| @Test |
| public void testInitialSyncExternalUsersNoNesting() throws Exception { |
| syncConfig.user().setMembershipNestingDepth(-1); |
| |
| ExternalUser externalUser = idp.getUser(TestIdentityProvider.ID_TEST_USER); |
| String[] externalId = new String[] {externalUser.getExternalId().getString()}; |
| |
| String[] result = syncMBean.syncExternalUsers(externalId); |
| assertResultMessages(result, TestIdentityProvider.ID_TEST_USER, "add"); |
| |
| UserManager userManager = getUserManager(); |
| User testUser = userManager.getAuthorizable(externalUser.getId(), User.class); |
| assertNotNull(testUser); |
| |
| for (ExternalIdentityRef groupRef : externalUser.getDeclaredGroups()) { |
| assertNull(userManager.getAuthorizable(groupRef.getId())); |
| } |
| } |
| |
| @Test |
| public void testSyncExternalUsersLastSyncedProperty() throws Exception { |
| ExternalUser externalUser = idp.getUser(TestIdentityProvider.ID_TEST_USER); |
| String[] externalId = new String[]{externalUser.getExternalId().getString()}; |
| |
| syncMBean.syncExternalUsers(externalId); |
| UserManager userManager = getUserManager(); |
| User testUser = userManager.getAuthorizable(externalUser.getId(), User.class); |
| |
| long lastSynced = testUser.getProperty(DefaultSyncContext.REP_LAST_SYNCED)[0].getLong(); |
| for (ExternalIdentityRef groupRef : externalUser.getDeclaredGroups()) { |
| Group gr = userManager.getAuthorizable(groupRef.getId(), Group.class); |
| long groupLastSynced = gr.getProperty(DefaultSyncContext.REP_LAST_SYNCED)[0].getLong(); |
| |
| assertTrue(lastSynced == groupLastSynced); |
| } |
| |
| while (System.currentTimeMillis() <= lastSynced) { |
| // wait for system time to move |
| } |
| |
| // default value for forceGroup sync is defined to be 'true' => verify result |
| syncMBean.syncExternalUsers(externalId); |
| userManager = getUserManager(); |
| testUser = userManager.getAuthorizable(externalUser.getId(), User.class); |
| long lastSynced2 = testUser.getProperty(DefaultSyncContext.REP_LAST_SYNCED)[0].getLong(); |
| |
| assertTrue("lastSynced: " + lastSynced + ", lastSynced2: " + lastSynced2, lastSynced < lastSynced2); |
| for (ExternalIdentityRef groupRef : externalUser.getDeclaredGroups()) { |
| Group gr = userManager.getAuthorizable(groupRef.getId(), Group.class); |
| long groupLastSynced = gr.getProperty(DefaultSyncContext.REP_LAST_SYNCED)[0].getLong(); |
| |
| assertTrue(lastSynced2 == groupLastSynced); |
| } |
| } |
| |
| @Test |
| public void testInitialSyncExternalGroup() throws Exception { |
| ExternalGroup externalGroup = idp.getGroup("a"); |
| String[] externalId = new String[] {externalGroup.getExternalId().getString()}; |
| |
| String[] result = syncMBean.syncExternalUsers(externalId); |
| assertResultMessages(result, "a", "add"); |
| |
| UserManager userManager = getUserManager(); |
| Group aGroup = userManager.getAuthorizable(externalGroup.getId(), Group.class); |
| assertNotNull(aGroup); |
| |
| // membership of groups are not synced (unless imposed by user-sync with membership depth) |
| for (ExternalIdentityRef groupRef : externalGroup.getDeclaredGroups()) { |
| assertNull(userManager.getAuthorizable(groupRef.getId())); |
| } |
| } |
| |
| @Test |
| public void testSyncExternalNonExisting() throws Exception { |
| ExternalIdentityRef ref = new ExternalIdentityRef("nonExisting", idp.getName()); |
| |
| String[] result = syncMBean.syncExternalUsers(new String[]{ref.getString()}); |
| assertResultMessages(result, "", "nsi"); |
| } |
| |
| /** |
| * @see <a href="https://issues.apache.org/jira/browse/OAK-4346">OAK-4346</a> |
| */ |
| @Test |
| public void testSyncExternalLocal() throws Exception { |
| ExternalIdentityRef ref = new ExternalIdentityRef(UserConstants.DEFAULT_ANONYMOUS_ID, null); |
| |
| String[] result = syncMBean.syncExternalUsers(new String[]{ref.getString()}); |
| assertResultMessages(result, UserConstants.DEFAULT_ANONYMOUS_ID, "for"); |
| } |
| |
| /** |
| * @see <a href="https://issues.apache.org/jira/browse/OAK-4346">OAK-4346</a> |
| */ |
| @Test |
| public void testSyncExternalForeign() throws Exception { |
| ExternalIdentityRef ref = new ExternalIdentityRef(TestIdentityProvider.ID_TEST_USER, "anotherIDP"); |
| |
| String[] result = syncMBean.syncExternalUsers(new String[]{ref.getString()}); |
| assertResultMessages(result, TestIdentityProvider.ID_TEST_USER, "for"); |
| |
| result = syncMBean.syncExternalUsers(new String[] {ref.getString()}); |
| assertResultMessages(result, TestIdentityProvider.ID_TEST_USER, "for"); |
| } |
| |
| @Test |
| public void testSyncExternalUserException() throws Exception { |
| ExternalIdentityRef ref = new ExternalIdentityRef(TestIdentityProvider.ID_EXCEPTION, idp.getName()); |
| String[] result = syncMBean.syncExternalUsers(new String[] {ref.getString()}); |
| assertResultMessages(result, TestIdentityProvider.ID_EXCEPTION, "ERR"); |
| } |
| |
| @Test |
| public void testSyncExternalUserThrowingHandler() throws Exception { |
| ExternalIdentityRef ref = new ExternalIdentityRef(TestIdentityProvider.ID_TEST_USER, idp.getName()); |
| String[] result = createThrowingSyncMBean(false).syncExternalUsers(new String[]{ref.getString()}); |
| assertResultMessages(result, TestIdentityProvider.ID_TEST_USER, "ERR"); |
| } |
| |
| /** |
| * test users have never been synced before => result must be empty |
| */ |
| @Test |
| public void testSyncAllUsersBefore() throws Exception { |
| String[] result = syncMBean.syncAllUsers(false); |
| assertEquals(0, result.length); |
| } |
| |
| @Test |
| public void testSyncAllUsers() throws Exception { |
| // first sync external users into the repo |
| syncMBean.syncAllExternalUsers(); |
| |
| // verify effect of syncAllUsers |
| String[] result = syncMBean.syncAllUsers(false); |
| |
| Map<String, String> expected = getExpectedUserResult("upd", true); |
| assertResultMessages(result, expected); |
| |
| UserManager userManager = getUserManager(); |
| for (String id : expected.keySet()) { |
| ExternalIdentity ei = idp.getUser(id); |
| if (ei == null) { |
| ei = idp.getGroup(id); |
| } |
| assertSync(ei, userManager); |
| } |
| } |
| |
| @Test |
| public void testSyncAllGroups() throws Exception { |
| // first sync external users into the repo |
| Map<String, String> expected = new HashMap(); |
| Iterator<ExternalGroup> grIt = idp.listGroups(); |
| while (grIt.hasNext()) { |
| ExternalGroup eg = grIt.next(); |
| sync(idp, eg.getId(), true); |
| expected.put(eg.getId(), "upd"); |
| } |
| |
| // verify effect of syncAllUsers (which in this case are groups) |
| String[] result = syncMBean.syncAllUsers(false); |
| assertResultMessages(result, expected); |
| |
| UserManager userManager = getUserManager(); |
| for (String id : expected.keySet()) { |
| ExternalIdentity ei = idp.getGroup(id); |
| assertSync(ei, userManager); |
| } |
| } |
| |
| @Test |
| public void testSyncAllUsersPurgeFalse() throws Exception { |
| // first sync external user|group into the repo that does't exist on the IDP (anymore) |
| sync(new TestIdentityProvider.TestUser("thirdUser", idp.getName()), idp); |
| sync(new TestIdentityProvider.TestGroup("g", idp.getName()), idp); |
| |
| // syncAll with purge = false |
| String[] result = syncMBean.syncAllUsers(false); |
| assertResultMessages(result, ImmutableMap.of("thirdUser", "mis", "g", "mis")); |
| |
| UserManager userManager = getUserManager(); |
| assertNotNull(userManager.getAuthorizable("thirdUser")); |
| assertNotNull(userManager.getAuthorizable("g")); |
| } |
| |
| @Test |
| public void testSyncAllUsersPurgeTrue() throws Exception { |
| // first sync external user|group into the repo that does't exist on the IDP (anymore) |
| sync(new TestIdentityProvider.TestUser("thirdUser", idp.getName()), idp); |
| sync(new TestIdentityProvider.TestGroup("g", idp.getName()), idp); |
| |
| // syncAll with purge = true |
| String[] result = syncMBean.syncAllUsers(true); |
| assertResultMessages(result, ImmutableMap.of("thirdUser", "del", "g", "del")); |
| |
| UserManager userManager = getUserManager(); |
| assertNull(userManager.getAuthorizable("thirdUser")); |
| assertNull(userManager.getAuthorizable("g")); |
| } |
| |
| @Test |
| public void testSyncAllUsersForeign() throws Exception { |
| // first sync external users + groups from 2 different IDPs into the repo |
| // but set membership-nesting to 0 |
| syncConfig.user().setMembershipNestingDepth(0); |
| sync(idp, TestIdentityProvider.ID_TEST_USER, false); |
| sync(idp, "a", true); |
| sync(foreignIDP, TestIdentityProvider.ID_SECOND_USER, false); |
| sync(foreignIDP, "aa", true); |
| |
| // verify effect of syncAllUsers : foreign user/group must be ignored by the sync. |
| String[] result = syncMBean.syncAllUsers(false); |
| Map<String, String> expectedResults = ImmutableMap.of(TestIdentityProvider.ID_TEST_USER, "upd", "a", "upd"); |
| assertResultMessages(result, expectedResults); |
| |
| ExternalIdentity[] expectedIds = new ExternalIdentity[] { |
| idp.getUser(TestIdentityProvider.ID_TEST_USER), |
| foreignIDP.getUser(TestIdentityProvider.ID_SECOND_USER), |
| idp.getGroup("a"), |
| foreignIDP.getGroup("aa") |
| }; |
| UserManager userManager = getUserManager(); |
| for (ExternalIdentity externalIdentity : expectedIds) { |
| assertSync(externalIdentity, userManager); |
| } |
| } |
| |
| @Test |
| public void testSyncAllUsersException() throws Exception { |
| User u = getUserManager().createUser(TestIdentityProvider.ID_EXCEPTION, null); |
| u.setProperty(DefaultSyncContext.REP_EXTERNAL_ID, getValueFactory().createValue(new ExternalIdentityRef(TestIdentityProvider.ID_EXCEPTION, idp.getName()).getString())); |
| root.commit(); |
| |
| String[] result = syncMBean.syncAllUsers(false); |
| assertResultMessages(result, TestIdentityProvider.ID_EXCEPTION, "ERR"); |
| |
| result = syncMBean.syncAllUsers(true); |
| assertResultMessages(result, TestIdentityProvider.ID_EXCEPTION, "ERR"); |
| } |
| |
| @Test(expected = IllegalStateException.class) |
| public void testSyncAllUsersThrowingHandler() throws Exception { |
| String[] result = createThrowingSyncMBean(false).syncAllUsers(false); |
| } |
| |
| @Test |
| public void testSyncAllUsersThrowingHandler2() throws Exception { |
| syncMBean.syncAllExternalUsers(); |
| |
| Map<String, String> expected = getExpectedUserResult("ERR", true); |
| String[] result = createThrowingSyncMBean(true).syncAllUsers(false); |
| |
| assertResultMessages(result, expected); |
| } |
| |
| @Test |
| public void testInitialSyncAllExternalUsers() throws Exception { |
| String[] result = syncMBean.syncAllExternalUsers(); |
| |
| Map<String, String> expected = getExpectedUserResult("add", false); |
| assertResultMessages(result, expected); |
| |
| UserManager userManager = getUserManager(); |
| for (String id : expected.keySet()) { |
| ExternalIdentity ei = idp.getUser(id); |
| if (ei == null) { |
| ei = idp.getGroup(id); |
| } |
| assertSync(ei, userManager); |
| } |
| } |
| |
| @Test |
| public void testSyncAllExternalUsersAgain() throws Exception { |
| syncMBean.syncAllExternalUsers(); |
| |
| // sync again |
| String[] result = syncMBean.syncAllExternalUsers(); |
| |
| // verify result |
| Map<String, String> expected = getExpectedUserResult("upd", false); |
| assertResultMessages(result, expected); |
| |
| UserManager userManager = getUserManager(); |
| for (String id : expected.keySet()) { |
| ExternalIdentity ei = idp.getUser(id); |
| if (ei == null) { |
| ei = idp.getGroup(id); |
| } |
| assertSync(ei, userManager); |
| } |
| } |
| |
| @Test |
| public void testSyncAllExternalUsersThrowingHandler() throws Exception { |
| String[] result = createThrowingSyncMBean(false).syncAllExternalUsers(); |
| |
| Map<String, String> expected = getExpectedUserResult("ERR", false); |
| assertResultMessages(result, expected); |
| } |
| |
| @Test |
| public void testListOrphanedUsers() throws Exception { |
| syncMBean.syncAllExternalUsers(); |
| |
| String[] result = syncMBean.listOrphanedUsers(); |
| assertEquals(0, result.length); |
| |
| sync(new TestIdentityProvider.TestUser("thirdUser", idp.getName()), idp); |
| sync(new TestIdentityProvider.TestGroup("g", idp.getName()), idp); |
| |
| result = syncMBean.listOrphanedUsers(); |
| assertEquals(2, result.length); |
| assertEquals(ImmutableSet.of("thirdUser", "g"), ImmutableSet.copyOf(result)); |
| } |
| |
| @Test |
| public void testListOrphanedUsersForeign() throws Exception { |
| sync(foreignIDP, "a", true); |
| sync(foreignIDP, TestIdentityProvider.ID_TEST_USER, false); |
| |
| String[] result = syncMBean.listOrphanedUsers(); |
| assertEquals(0, result.length); |
| } |
| |
| @Test |
| public void testListOrphanedUsersException () throws Exception { |
| User u = getUserManager().createUser(TestIdentityProvider.ID_EXCEPTION, null); |
| u.setProperty(DefaultSyncContext.REP_EXTERNAL_ID, getValueFactory().createValue(new ExternalIdentityRef(TestIdentityProvider.ID_EXCEPTION, idp.getName()).getString())); |
| root.commit(); |
| |
| String[] result = syncMBean.listOrphanedUsers(); |
| assertEquals(0, result.length); |
| } |
| |
| @Test |
| public void testListOrphanedUsersThrowingHandler() throws Exception { |
| sync(new TestIdentityProvider.TestUser("thirdUser", idp.getName()), idp); |
| sync(new TestIdentityProvider.TestGroup("g", idp.getName()), idp); |
| |
| String[] result = createThrowingSyncMBean(false).listOrphanedUsers(); |
| assertEquals(0, result.length); |
| |
| result = createThrowingSyncMBean(true).listOrphanedUsers(); |
| assertEquals(2, result.length); |
| assertEquals(ImmutableSet.of("thirdUser", "g"), ImmutableSet.copyOf(result)); |
| } |
| |
| @Test |
| public void testPurgeOrphanedUsersNoPurge() { |
| syncMBean.syncAllExternalUsers(); |
| |
| String[] result = syncMBean.purgeOrphanedUsers(); |
| assertEquals(0, result.length); |
| } |
| |
| @Test |
| public void testPurgeOrphanedUsers() throws Exception { |
| syncMBean.syncAllExternalUsers(); |
| |
| sync(new TestIdentityProvider.TestUser("thirdUser", idp.getName()), idp); |
| sync(new TestIdentityProvider.TestGroup("g", idp.getName()), idp); |
| |
| String[] result = syncMBean.purgeOrphanedUsers(); |
| assertResultMessages(result, ImmutableMap.of("thirdUser", "del", "g", "del")); |
| |
| UserManager userManager = getUserManager(); |
| assertNull(userManager.getAuthorizable("thirdUser")); |
| assertNull(userManager.getAuthorizable("g")); |
| } |
| |
| @Test |
| public void testPurgeOrphanedUsersForeign() throws Exception { |
| sync(foreignIDP, "a", true); |
| sync(foreignIDP, TestIdentityProvider.ID_TEST_USER, false); |
| |
| String[] result = syncMBean.purgeOrphanedUsers(); |
| assertEquals(0, result.length); |
| } |
| |
| @Test |
| public void testPurgeOrphanedUsersException() throws Exception { |
| User u = getUserManager().createUser(TestIdentityProvider.ID_EXCEPTION, null); |
| u.setProperty(DefaultSyncContext.REP_EXTERNAL_ID, getValueFactory().createValue(new ExternalIdentityRef(TestIdentityProvider.ID_EXCEPTION, idp.getName()).getString())); |
| root.commit(); |
| |
| String[] result = syncMBean.purgeOrphanedUsers(); |
| assertEquals(0, result.length); |
| } |
| |
| @Test |
| public void testPurgeOrphanedUsersThrowingHandler() throws Exception { |
| sync(new TestIdentityProvider.TestUser("thirdUser", idp.getName()), idp); |
| sync(new TestIdentityProvider.TestGroup("g", idp.getName()), idp); |
| |
| String[] result = createThrowingSyncMBean(false).purgeOrphanedUsers(); |
| assertEquals(0, result.length); |
| |
| UserManager userManager = getUserManager(); |
| assertNotNull(userManager.getAuthorizable("thirdUser")); |
| assertNotNull(userManager.getAuthorizable("g")); |
| } |
| |
| /** |
| * @see <a href="https://issues.apache.org/jira/browse/OAK-4362">OAK-4362</a> |
| */ |
| @Test |
| public void testPurgeOrphanedUsersThrowingHandler2() throws Exception { |
| sync(new TestIdentityProvider.TestUser("thirdUser", idp.getName()), idp); |
| sync(new TestIdentityProvider.TestGroup("g", idp.getName()), idp); |
| |
| String[] result = createThrowingSyncMBean(true).purgeOrphanedUsers(); |
| assertResultMessages(result, ImmutableMap.of("thirdUser", "ERR", "g", "ERR")); |
| |
| UserManager userManager = getUserManager(); |
| assertNotNull(userManager.getAuthorizable("thirdUser")); |
| assertNotNull(userManager.getAuthorizable("g")); |
| } |
| |
| /** |
| * SyncHandler implementation that throws Exceptions. |
| */ |
| private final class ThrowingSyncHandler extends DefaultSyncHandler { |
| |
| private static final String NAME = "throwing"; |
| private static final String NAME_ALLOWS_IDENTITY_LISTING = "throwingExceptListIdentities"; |
| |
| boolean allowsListIdentities = false; |
| |
| private ThrowingSyncHandler(boolean allowsListIdentities) { |
| super(syncConfig); |
| this.allowsListIdentities = allowsListIdentities; |
| }; |
| |
| @NotNull |
| @Override |
| public String getName() { |
| return allowsListIdentities ? NAME_ALLOWS_IDENTITY_LISTING : NAME; |
| } |
| |
| @NotNull |
| @Override |
| public SyncContext createContext(@NotNull ExternalIdentityProvider idp, @NotNull UserManager userManager, @NotNull ValueFactory valueFactory) throws SyncException { |
| return new DefaultSyncContext(syncConfig, idp, userManager, valueFactory) { |
| @NotNull |
| @Override |
| public SyncResult sync(@NotNull ExternalIdentity identity) throws SyncException { |
| throw new SyncException("sync " + identity); |
| } |
| |
| @NotNull |
| @Override |
| public SyncResult sync(@NotNull String id) throws SyncException { |
| throw new SyncException("sync " + id); |
| } |
| }; |
| } |
| |
| @Nullable |
| @Override |
| public SyncedIdentity findIdentity(@NotNull UserManager userManager, @NotNull String id) throws RepositoryException { |
| throw new RepositoryException("findIdentity"); |
| } |
| |
| @Override |
| public boolean requiresSync(@NotNull SyncedIdentity identity) { |
| return false; |
| } |
| |
| @NotNull |
| @Override |
| public Iterator<SyncedIdentity> listIdentities(@NotNull UserManager userManager) throws RepositoryException { |
| if (!allowsListIdentities) { |
| throw new RepositoryException("listIdentities"); |
| } else { |
| return super.listIdentities(userManager); |
| } |
| } |
| } |
| } |