You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by an...@apache.org on 2016/04/19 18:52:36 UTC
svn commit: r1739959 - in
/jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external:
TestIdentityProvider.java basic/DefaultSyncContextTest.java
Author: angela
Date: Tue Apr 19 16:52:36 2016
New Revision: 1739959
URL: http://svn.apache.org/viewvc?rev=1739959&view=rev
Log:
OAK-4226 : Improve testing of DefaultSyncContext
Modified:
jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestIdentityProvider.java
jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncContextTest.java
Modified: jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestIdentityProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestIdentityProvider.java?rev=1739959&r1=1739958&r2=1739959&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestIdentityProvider.java (original)
+++ jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestIdentityProvider.java Tue Apr 19 16:52:36 2016
@@ -27,9 +27,14 @@ import javax.jcr.Credentials;
import javax.jcr.SimpleCredentials;
import javax.security.auth.login.LoginException;
+import com.google.common.collect.ImmutableList;
+
public class TestIdentityProvider implements ExternalIdentityProvider {
public static final String ID_TEST_USER = "testUser";
+ public static final String ID_SECOND_USER = "secondUser";
+
+ public static final String ID_EXCEPTION = "throw!";
private final Map<String, ExternalGroup> externalGroups = new HashMap<String, ExternalGroup>();
private final Map<String, ExternalUser> externalUsers = new HashMap<String, ExternalUser>();
@@ -40,6 +45,7 @@ public class TestIdentityProvider implem
addGroup(new TestGroup("a").withGroups("aa", "aaa"));
addGroup(new TestGroup("b").withGroups("a"));
addGroup(new TestGroup("c"));
+ addGroup(new TestGroup("secondGroup"));
addUser(new TestUser(ID_TEST_USER)
.withProperty("name", "Test User")
@@ -48,6 +54,15 @@ public class TestIdentityProvider implem
.withProperty("email", "test@testuser.com")
.withGroups("a", "b", "c")
);
+
+ addUser(new TestUser(ID_SECOND_USER)
+ .withProperty("profile/name", "Second User")
+ .withProperty("age", 24)
+ .withProperty("col", ImmutableList.of("v1", "v2", "v3"))
+ .withProperty("boolArr", new Boolean[]{true, false})
+ .withProperty("charArr", new char[]{'t', 'o', 'b'})
+ .withProperty("byteArr", new byte[0])
+ .withGroups("secondGroup"));
}
private void addUser(TestIdentity user) {
@@ -75,6 +90,9 @@ public class TestIdentityProvider implem
@Override
public ExternalUser getUser(@Nonnull String userId) throws ExternalIdentityException {
+ if (ID_EXCEPTION.equals(userId)) {
+ throw new ExternalIdentityException(ID_EXCEPTION);
+ }
return externalUsers.get(userId.toLowerCase());
}
@@ -95,6 +113,9 @@ public class TestIdentityProvider implem
@Override
public ExternalGroup getGroup(@Nonnull String name) throws ExternalIdentityException {
+ if (ID_EXCEPTION.equals(name)) {
+ throw new ExternalIdentityException(ID_EXCEPTION);
+ }
return externalGroups.get(name.toLowerCase());
}
Modified: jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncContextTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncContextTest.java?rev=1739959&r1=1739958&r2=1739959&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncContextTest.java (original)
+++ jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/DefaultSyncContextTest.java Tue Apr 19 16:52:36 2016
@@ -17,7 +17,13 @@
package org.apache.jackrabbit.oak.spi.security.authentication.external.basic;
import java.io.ByteArrayInputStream;
+import java.math.BigDecimal;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -30,9 +36,12 @@ import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
+import com.google.common.collect.Lists;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.User;
@@ -40,18 +49,24 @@ import org.apache.jackrabbit.api.securit
import org.apache.jackrabbit.oak.AbstractSecurityTest;
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.ExternalIdentityRef;
import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalUser;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncException;
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.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
public class DefaultSyncContextTest extends AbstractSecurityTest {
@@ -100,10 +115,173 @@ public class DefaultSyncContextTest exte
return gr;
}
+ /**
+ * Test utility method to synchronize the given identity into the repository.
+ * This is intended to simplify those tests that require a given user/group
+ * to be synchronized before executing the test.
+ *
+ * @param externalIdentity The external identity to be synchronized.
+ * @throws Exception
+ */
+ private void sync(@Nonnull ExternalIdentity externalIdentity) throws Exception {
+ SyncResult result = syncCtx.sync(externalIdentity);
+ assertSame(SyncResult.Status.ADD, result.getStatus());
+ root.commit();
+ }
+
private void setExternalID(@Nonnull Authorizable authorizable, @Nullable String idpName) throws RepositoryException {
authorizable.setProperty(DefaultSyncContext.REP_EXTERNAL_ID, getValueFactory().createValue(authorizable.getID() + ';' + idpName));
}
+ @Test
+ public void testCreateSyncedIdentityNull() throws Exception {
+ assertNull(DefaultSyncContext.createSyncedIdentity(null));
+ }
+
+ @Test
+ public void testCreateSyncedIdentityLocalGroup() throws Exception {
+ Group gr = createTestGroup();
+ SyncedIdentity si = DefaultSyncContext.createSyncedIdentity(gr);
+
+ assertNotNull(si);
+ assertEquals(gr.getID(), si.getId());
+ assertNull(si.getExternalIdRef());
+ assertTrue(si.isGroup());
+ assertEquals(-1, si.lastSynced());
+ }
+
+ @Test
+ public void testCreateSyncedIdentityLocalUser() throws Exception {
+ User u = getTestUser();
+ SyncedIdentity si = DefaultSyncContext.createSyncedIdentity(u);
+
+ assertNotNull(si);
+ assertEquals(u.getID(), si.getId());
+ assertNull(si.getExternalIdRef());
+ assertFalse(si.isGroup());
+ assertEquals(-1, si.lastSynced());
+ }
+
+ @Test
+ public void testCreateSyncedIdentitySyncedGroup() throws Exception {
+ ExternalIdentity externalGroup = idp.listGroups().next();
+ sync(externalGroup);
+
+ Authorizable a = getUserManager(root).getAuthorizable(externalGroup.getId());
+ SyncedIdentity si = DefaultSyncContext.createSyncedIdentity(a);
+
+ assertNotNull(si);
+ assertEquals(a.getID(), si.getId());
+ assertNotNull(si.getExternalIdRef());
+ assertTrue(si.isGroup());
+ assertEquals(syncCtx.now, si.lastSynced());
+ }
+
+ @Test
+ public void testCreateSyncedIdentitySyncedUser() throws Exception {
+ ExternalIdentity externalUser = idp.listUsers().next();
+ sync(externalUser);
+
+ Authorizable a = getUserManager(root).getAuthorizable(externalUser.getId());
+ SyncedIdentity si = DefaultSyncContext.createSyncedIdentity(a);
+
+ assertNotNull(si);
+ assertEquals(a.getID(), si.getId());
+ assertNotNull(si.getExternalIdRef());
+ assertFalse(si.isGroup());
+ assertEquals(syncCtx.now, si.lastSynced());
+ }
+
+ @Test
+ public void testCreateSyncedIdentityEmptyLastSyncedProperty() throws Exception {
+ Group gr = createTestGroup();
+ gr.setProperty(DefaultSyncContext.REP_LAST_SYNCED, new Value[0]);
+
+ SyncedIdentity si = DefaultSyncContext.createSyncedIdentity(gr);
+ assertNotNull(si);
+ assertEquals(-1, si.lastSynced());
+ }
+
+ @Test
+ public void testGetIdentityRefNull() throws Exception {
+ assertNull(DefaultSyncContext.getIdentityRef(null));
+ }
+
+ @Test
+ public void testGetIdentityRefLocalGroup() throws Exception {
+ assertNull(DefaultSyncContext.getIdentityRef(createTestGroup()));
+ }
+
+ @Test
+ public void testGetIdentityRefLocalUser() throws Exception {
+ assertNull(DefaultSyncContext.getIdentityRef(getTestUser()));
+ }
+
+ @Test
+ public void testGetIdentityRefSyncGroup() throws Exception {
+ ExternalIdentity externalGroup = idp.listGroups().next();
+ sync(externalGroup);
+
+ ExternalIdentityRef ref = DefaultSyncContext.getIdentityRef(getUserManager(root).getAuthorizable(externalGroup.getId()));
+ assertNotNull(ref);
+ assertEquals(externalGroup.getExternalId(), ref);
+ }
+
+ @Test
+ public void testGetIdentityRefSyncUser() throws Exception {
+ ExternalIdentity externalGroupUser = idp.listGroups().next();
+ sync(externalGroupUser);
+
+ ExternalIdentityRef ref = DefaultSyncContext.getIdentityRef(getUserManager(root).getAuthorizable(externalGroupUser.getId()));
+ assertNotNull(ref);
+ assertEquals(externalGroupUser.getExternalId(), ref);
+ }
+
+ @Test
+ public void testGetIdentityRefEmptyMvProperty() throws Exception {
+ Group gr = createTestGroup();
+ // NOTE: making rep:externalId a multivalue property without any value
+ // not committing the changes as this prop is expected to become
+ // protected to prevent unintentional or malicious modification.
+ gr.setProperty(DefaultSyncContext.REP_EXTERNAL_ID, new Value[0]);
+
+ ExternalIdentityRef ref = DefaultSyncContext.getIdentityRef(gr);
+ assertNull(ref);
+ }
+
+ @Test
+ public void testIsKeepMissing() {
+ assertFalse(syncCtx.isKeepMissing());
+
+ assertSame(syncCtx, syncCtx.setKeepMissing(true));
+ assertTrue(syncCtx.isKeepMissing());
+
+ assertSame(syncCtx, syncCtx.setKeepMissing(false));
+ assertFalse(syncCtx.isKeepMissing());
+ }
+
+ @Test
+ public void testIsForceUserSync() {
+ assertFalse(syncCtx.isForceUserSync());
+
+ assertSame(syncCtx, syncCtx.setForceUserSync(true));
+ assertTrue(syncCtx.isForceUserSync());
+
+ assertSame(syncCtx, syncCtx.setForceUserSync(false));
+ assertFalse(syncCtx.isForceUserSync());
+ }
+
+ @Test
+ public void testIsForceGroupSync() {
+ assertFalse(syncCtx.isForceGroupSync());
+
+ assertSame(syncCtx, syncCtx.setForceGroupSync(true));
+ assertTrue(syncCtx.isForceGroupSync());
+
+ assertSame(syncCtx, syncCtx.setForceGroupSync(false));
+ assertFalse(syncCtx.isForceGroupSync());
+ }
+
@Test(expected = IllegalArgumentException.class)
public void testSyncInvalidExternalIdentity() throws Exception {
syncCtx.sync(new TestExternalIdentity());
@@ -142,6 +320,16 @@ public class DefaultSyncContextTest exte
assertEquals(SyncResult.Status.UPDATE, result.getStatus());
}
+ @Ignore("OAK-4224")
+ @Test(expected = SyncException.class)
+ public void testSyncForeignExternalIdentity() throws Exception {
+ ExternalIdentity foreign = new ForeignExternalUser();
+
+ syncCtx.sync(foreign);
+ // don't commit changes as the after-call would not properly remove any
+ // authorizable created this way.
+ }
+
@Test
public void testSyncUserById() throws Exception {
ExternalIdentity externalId = idp.listUsers().next();
@@ -259,6 +447,14 @@ public class DefaultSyncContextTest exte
assertEquals(SyncResult.Status.FOREIGN, result.getStatus());
}
+ @Test(expected = SyncException.class)
+ public void testSyncByIdUsingExceptionId() throws Exception {
+ Group gr = getUserManager(root).createGroup(TestIdentityProvider.ID_EXCEPTION);
+ setExternalID(gr, idp.getName());
+
+ syncCtx.sync(TestIdentityProvider.ID_EXCEPTION);
+ }
+
@Test
public void testSyncAutoMembership() throws Exception {
Group gr = createTestGroup();
@@ -344,6 +540,510 @@ public class DefaultSyncContextTest exte
assertTrue(gr.isDeclaredMember(user));
}
+ @Test
+ public void testGetAuthorizableUser() throws Exception {
+ ExternalIdentity extUser = idp.listUsers().next();
+ User user = syncCtx.getAuthorizable(extUser, User.class);
+ assertNull(user);
+
+ sync(extUser);
+
+ user = syncCtx.getAuthorizable(extUser, User.class);
+ assertNotNull(user);
+ }
+
+ @Test(expected = SyncException.class)
+ public void testGetAuthorizableUserWrongType() throws Exception {
+ ExternalIdentity extUser = idp.listUsers().next();
+ sync(extUser);
+ syncCtx.getAuthorizable(extUser, Group.class);
+ }
+
+ @Test
+ public void testGetAuthorizableGroup() throws Exception {
+ ExternalIdentity extGroup = idp.listGroups().next();
+ Group gr = syncCtx.getAuthorizable(extGroup, Group.class);
+ assertNull(gr);
+
+ sync(extGroup);
+
+ gr = syncCtx.getAuthorizable(extGroup, Group.class);
+ assertNotNull(gr);
+ }
+
+ @Test(expected = SyncException.class)
+ public void testGetAuthorizableGroupWrongType() throws Exception {
+ ExternalIdentity extGroup = idp.listGroups().next();
+ sync(extGroup);
+ syncCtx.getAuthorizable(extGroup, User.class);
+ }
+
+ @Test
+ public void testSyncMembershipDepthNoSync() throws Exception {
+ ExternalUser externalUser = idp.listUsers().next();
+ Authorizable a = syncCtx.createUser(externalUser);
+ root.commit();
+
+ assertTrue(externalUser.getDeclaredGroups().iterator().hasNext());
+
+ syncCtx.syncMembership(externalUser, a, 0);
+ assertFalse(root.hasPendingChanges());
+
+ syncCtx.syncMembership(externalUser, a, -1);
+ assertFalse(root.hasPendingChanges());
+ }
+
+ @Test
+ public void testSyncMembershipDepth1() throws Exception {
+ ExternalUser externalUser = idp.listUsers().next();
+ Authorizable a = syncCtx.createUser(externalUser);
+
+ syncCtx.syncMembership(externalUser, a, 1);
+ assertTrue(root.hasPendingChanges());
+
+ UserManager uMgr = getUserManager(root);
+ for (ExternalIdentityRef ref : externalUser.getDeclaredGroups()) {
+ Group g = uMgr.getAuthorizable(ref.getId(), Group.class);
+ assertNotNull(g);
+ assertTrue(g.isDeclaredMember(a));
+ }
+ }
+
+ @Test
+ public void testSyncMembershipDepthInfinite() throws Exception {
+ ExternalUser externalUser = idp.listUsers().next();
+ Authorizable a = syncCtx.createUser(externalUser);
+
+ syncCtx.syncMembership(externalUser, a, Long.MAX_VALUE);
+ assertTrue(root.hasPendingChanges());
+ root.commit();
+
+ UserManager uMgr = getUserManager(root);
+ for (ExternalIdentityRef ref : externalUser.getDeclaredGroups()) {
+ ExternalIdentity extGr = idp.getIdentity(ref);
+ assertNotNull(extGr);
+
+ for (ExternalIdentityRef inheritedGrRef : extGr.getDeclaredGroups()) {
+ Group g = uMgr.getAuthorizable(inheritedGrRef.getId(), Group.class);
+ assertNotNull(g);
+ if (Iterables.contains(externalUser.getDeclaredGroups(), inheritedGrRef)) {
+ assertTrue(g.isDeclaredMember(a));
+ } else {
+ assertFalse(g.isDeclaredMember(a));
+ }
+ assertTrue(g.isMember(a));
+ }
+ }
+ }
+
+ @Test
+ public void testSyncMembershipGroupIsExternalUser() throws Exception {
+ // sync the 'wrong' external group into the repository
+ ExternalIdentity externalIdentity = idp.listUsers().next();
+ sync(externalIdentity);
+
+ // create external user with an synced-ext-user as declared group
+ ExternalUser withWrongDeclaredGroup = new ExternalUserWithDeclaredGroup(externalIdentity.getExternalId());
+
+ try {
+ Authorizable a = syncCtx.createUser(withWrongDeclaredGroup);
+ root.commit();
+
+ syncCtx.syncMembership(withWrongDeclaredGroup, a, 1);
+ assertFalse(root.hasPendingChanges());
+ } finally {
+ Authorizable a = getUserManager(root).getAuthorizable(withWrongDeclaredGroup.getId());
+ if (a != null) {
+ a.remove();
+ root.commit();
+ }
+ }
+ }
+
+ @Test
+ public void testSyncMembershipGroupIsSyncedAsUser() throws Exception {
+ ExternalUser fromIDP = idp.listUsers().next();
+ ExternalIdentityRef groupRef = fromIDP.getDeclaredGroups().iterator().next();
+
+ // sync the the ext-user from the idp (but make it just declare a single group)
+ ExternalUser extuser = new ExternalUserWithDeclaredGroup(groupRef, fromIDP);
+ Authorizable a = syncCtx.createUser(extuser);
+
+ // create an external-user based on info that the IDP knows as group and sync it
+ ExternalUser externalIdentity = new ExternalUserFromGroup(idp.getIdentity(groupRef));
+ Authorizable a2 = syncCtx.createUser(externalIdentity);
+ assertFalse(a2.isGroup());
+ root.commit();
+
+ // now sync-ing the membership should not have any effect as the external
+ // group referenced from 'extuser' has already been created in the system
+ // as user.
+ syncCtx.syncMembership(extuser, a, 1);
+ assertFalse(root.hasPendingChanges());
+ }
+
+ @Test
+ public void testApplyMembershipNonExistingGroup() throws Exception {
+ User u = getTestUser();
+
+ assertNull(getUserManager(root).getAuthorizable("anyGroup", Group.class));
+ syncCtx.applyMembership(u, ImmutableSet.of("anyGroup"));
+ assertFalse(root.hasPendingChanges());
+ }
+
+ @Test
+ public void testApplyMembershipNonGroup() throws Exception {
+ ExternalUser externalUser = idp.listUsers().next();
+ sync(externalUser);
+ User u = getTestUser();
+
+ syncCtx.applyMembership(getUserManager(root).getAuthorizable(externalUser.getId()), ImmutableSet.of(u.getID()));
+ assertFalse(root.hasPendingChanges());
+ }
+
+ @Test
+ public void testApplyMembership() throws Exception {
+ User u = getTestUser();
+ Group gr = createTestGroup();
+
+ syncCtx.applyMembership(u, ImmutableSet.of(gr.getID()));
+ assertTrue(gr.isDeclaredMember(u));
+ assertTrue(root.hasPendingChanges());
+ }
+
+ @Test
+ public void testSyncPropertiesEmptyMap() throws Exception {
+ ExternalUser externalUser = idp.getUser(TestIdentityProvider.ID_SECOND_USER);
+ Authorizable a = syncCtx.createUser(externalUser);
+
+ syncCtx.syncProperties(externalUser, a, ImmutableMap.<String, String>of());
+
+ for (String propName : externalUser.getProperties().keySet()) {
+ assertFalse(a.hasProperty(propName));
+ }
+ }
+
+ @Test
+ public void testSyncPropertiesEmptyMapExistingProps() throws Exception {
+ ExternalUser externalUser = idp.getUser(TestIdentityProvider.ID_SECOND_USER);
+ Authorizable a = syncCtx.createUser(externalUser);
+
+ Value anyValue = getValueFactory().createValue("any");
+
+ Map<String, ?> extProps = externalUser.getProperties();
+ for (String propName : extProps.keySet()) {
+ a.setProperty(propName, anyValue);
+ }
+
+ syncCtx.syncProperties(externalUser, a, ImmutableMap.<String, String>of());
+ for (String propName : extProps.keySet()) {
+ assertTrue(a.hasProperty(propName));
+ assertEquals(anyValue, a.getProperty(propName)[0]);
+ }
+ }
+
+ @Test
+ public void testSyncPropertiesMappingRemovesExisting() throws Exception {
+ ExternalUser externalUser = idp.getUser(TestIdentityProvider.ID_SECOND_USER);
+ sync(externalUser);
+
+ Authorizable a = getUserManager(root).getAuthorizable(externalUser.getId());
+
+ // create mapping that doesn't match to names in the external-properties
+ // -> previously synced properties must be removed
+ Map<String, String> mapping = new HashMap();
+ Map<String, ?> extProps = externalUser.getProperties();
+ for (String propName : extProps.keySet()) {
+ mapping.put(propName, "any");
+ }
+
+ syncCtx.syncProperties(externalUser, a, mapping);
+ for (String propName : extProps.keySet()) {
+ assertFalse(a.hasProperty(propName));
+ }
+ }
+
+ @Test
+ public void testSyncPropertiesMappingConstants() throws Exception {
+ ExternalUser externalUser = idp.getUser(TestIdentityProvider.ID_SECOND_USER);
+ sync(externalUser);
+
+ Authorizable a = getUserManager(root).getAuthorizable(externalUser.getId());
+
+ // create mapping that doesn't match to names in the external-properties
+ // -> previously synced properties must be removed
+ Map<String, String> mapping = new HashMap();
+ Map<String, ?> extProps = externalUser.getProperties();
+ for (String propName : extProps.keySet()) {
+ mapping.put(propName, "\"any\"");
+ }
+
+ syncCtx.syncProperties(externalUser, a, mapping);
+ Value anyValue = getValueFactory().createValue("any");
+ for (String propName : extProps.keySet()) {
+ assertTrue(a.hasProperty(propName));
+ assertEquals(anyValue, a.getProperty(propName)[0]);
+ }
+ }
+
+ @Test
+ public void testSyncPropertiesMappingDQuoteName() throws Exception {
+ ExternalUser externalUser = idp.getUser(TestIdentityProvider.ID_SECOND_USER);
+ sync(externalUser);
+
+ Authorizable a = getUserManager(root).getAuthorizable(externalUser.getId());
+
+ // mapping to '"' (i.e. name size = 1) which doesn't qualify as constant
+ // -> same behavior expected as with 'testSyncPropertiesMappingRemovesExisting'
+ Map<String, String> mapping = new HashMap();
+ Map<String, ?> extProps = externalUser.getProperties();
+ for (String propName : extProps.keySet()) {
+ mapping.put(propName, "\"");
+ }
+
+ syncCtx.syncProperties(externalUser, a, mapping);
+ for (String propName : extProps.keySet()) {
+ assertFalse(a.hasProperty(propName));
+ }
+ }
+
+ @Test
+ public void testSyncPropertiesMappingNameStartsWithDQuote() throws Exception {
+ ExternalUser externalUser = idp.getUser(TestIdentityProvider.ID_SECOND_USER);
+ sync(externalUser);
+
+ Authorizable a = getUserManager(root).getAuthorizable(externalUser.getId());
+
+ // mapping to '"any', which doesn't qualify as constant
+ // -> same behavior expected as with 'testSyncPropertiesMappingRemovesExisting'
+ Map<String, String> mapping = new HashMap();
+ Map<String, ?> extProps = externalUser.getProperties();
+ for (String propName : extProps.keySet()) {
+ mapping.put(propName, "\"any");
+ }
+
+ syncCtx.syncProperties(externalUser, a, mapping);
+ for (String propName : extProps.keySet()) {
+ assertFalse(a.hasProperty(propName));
+ }
+ }
+
+ @Test
+ public void testSyncProperties() throws Exception {
+ ExternalUser externalUser = idp.getUser(TestIdentityProvider.ID_SECOND_USER);
+ Authorizable a = syncCtx.createUser(externalUser);
+
+ // create exact mapping
+ Map<String, String> mapping = new HashMap();
+ Map<String, ?> extProps = externalUser.getProperties();
+ for (String propName : extProps.keySet()) {
+ mapping.put(propName, propName);
+ }
+ syncCtx.syncProperties(externalUser, a, mapping);
+
+ for (String propName : extProps.keySet()) {
+ assertTrue(a.hasProperty(propName));
+
+ Object obj = extProps.get(propName);
+ Value[] vs = a.getProperty(propName);
+ if (vs.length == 1) {
+ assertEquals(syncCtx.createValue(obj), a.getProperty(propName)[0]);
+ } else {
+ Value[] expected = (obj instanceof Collection) ?
+ syncCtx.createValues((Collection) obj) :
+ syncCtx.createValues(Arrays.asList((Object[]) obj));
+ assertArrayEquals(expected, a.getProperty(propName));
+ }
+ }
+ }
+
+ @Test
+ public void testSyncPropertiesRemapped() throws Exception {
+ ExternalUser externalUser = idp.getUser(TestIdentityProvider.ID_SECOND_USER);
+ Authorizable a = syncCtx.createUser(externalUser);
+
+ // create exact mapping
+ Map<String, String> mapping = new HashMap();
+ Map<String, ?> extProps = externalUser.getProperties();
+ for (String propName : extProps.keySet()) {
+ mapping.put("a/"+propName, propName);
+ }
+ syncCtx.syncProperties(externalUser, a, mapping);
+
+ for (String propName : extProps.keySet()) {
+ String relPath = "a/" + propName;
+
+ assertTrue(a.hasProperty(relPath));
+
+ Object obj = extProps.get(propName);
+ Value[] vs = a.getProperty(relPath);
+ if (vs.length == 1) {
+ assertEquals(syncCtx.createValue(obj), a.getProperty(relPath)[0]);
+ } else {
+ Value[] expected = (obj instanceof Collection) ?
+ syncCtx.createValues((Collection) obj) :
+ syncCtx.createValues(Arrays.asList((Object[]) obj));
+ assertArrayEquals(expected, a.getProperty(relPath));
+ }
+ }
+ }
+
+ @Test
+ public void testIsExpiredLocalGroup() throws Exception {
+ Group gr = createTestGroup();
+ assertTrue(syncCtx.isExpired(gr, config.group().getExpirationTime(), "any"));
+ }
+
+ @Test
+ public void testIsExpiredEmptyLastSyncedProperty() throws Exception {
+ Group gr = createTestGroup();
+ gr.setProperty(DefaultSyncContext.REP_LAST_SYNCED, new Value[0]);
+
+ assertTrue(syncCtx.isExpired(gr, config.group().getExpirationTime(), "any"));
+ }
+
+ @Test
+ public void testIsExpiredSyncedUser() throws Exception {
+ ExternalIdentity externalUser = idp.listUsers().next();
+ sync(externalUser);
+
+ Authorizable a = getUserManager(root).getAuthorizable(externalUser.getId());
+ assertFalse(syncCtx.isExpired(a, config.user().getExpirationTime(), "any"));
+ assertTrue(syncCtx.isExpired(a, -1, "any"));
+
+ // create a ctx with a newer 'now'
+ DefaultSyncContext ctx = new DefaultSyncContext(config, idp, getUserManager(root), getValueFactory());
+ assertTrue(ctx.isExpired(a, 1, "any"));
+
+ // remove last-sync property
+ a.removeProperty(DefaultSyncContext.REP_LAST_SYNCED);
+ assertTrue(syncCtx.isExpired(a, config.user().getExpirationTime(), "any"));
+ }
+
+ @Test
+ public void testIsExpiredSyncedGroup() throws Exception {
+ ExternalIdentity externalGroup = idp.listGroups().next();
+ sync(externalGroup);
+
+ Authorizable a = getUserManager(root).getAuthorizable(externalGroup.getId());
+ assertFalse(syncCtx.isExpired(a, config.group().getExpirationTime(), "any"));
+ assertTrue(syncCtx.isExpired(a, -1, "any"));
+
+ // create a ctx with a newer 'now'
+ DefaultSyncContext ctx = new DefaultSyncContext(config, idp, getUserManager(root), getValueFactory());
+ assertTrue(ctx.isExpired(a, 1, "any"));
+
+ // remove last-sync property
+ a.removeProperty(DefaultSyncContext.REP_LAST_SYNCED);
+ assertTrue(syncCtx.isExpired(a, config.group().getExpirationTime(), "any"));
+ }
+
+ @Test
+ public void testCreateValueNull() throws Exception {
+ assertNull(syncCtx.createValue(null));
+ }
+
+ @Test
+ public void testCreateValueString() throws Exception {
+ Value v = syncCtx.createValue("s");
+ assertNotNull(v);
+ assertEquals(PropertyType.STRING, v.getType());
+ assertEquals("s", v.getString());
+
+ v = syncCtx.createValue(new char[] {'s'});
+ assertNotNull(v);
+ assertEquals(PropertyType.STRING, v.getType());
+ assertEquals("s", v.getString());
+
+ Object o = new ForeignExternalUser();
+ v = syncCtx.createValue(o);
+ assertNotNull(v);
+ assertEquals(PropertyType.STRING, v.getType());
+ assertEquals(o.toString(), v.getString());
+ }
+
+ @Test
+ public void testCreateValueBoolean() throws Exception {
+ Value v = syncCtx.createValue(true);
+ assertNotNull(v);
+ assertEquals(PropertyType.BOOLEAN, v.getType());
+ assertEquals(true, v.getBoolean());
+ }
+
+ @Test
+ public void testCreateValueLong() throws Exception {
+ Value v = syncCtx.createValue(Long.MAX_VALUE);
+ assertNotNull(v);
+ assertEquals(PropertyType.LONG, v.getType());
+ assertEquals(Long.MAX_VALUE, v.getLong());
+
+ v = syncCtx.createValue(Integer.valueOf(23));
+ assertNotNull(v);
+ assertEquals(PropertyType.LONG, v.getType());
+ assertEquals(23, v.getLong());
+
+ v = syncCtx.createValue(Short.MIN_VALUE);
+ assertNotNull(v);
+ assertEquals(PropertyType.LONG, v.getType());
+ assertEquals(Short.MIN_VALUE, v.getLong());
+
+ v = syncCtx.createValue(Byte.MAX_VALUE);
+ assertNotNull(v);
+ assertEquals(PropertyType.LONG, v.getType());
+ assertEquals(Byte.MAX_VALUE, v.getLong());
+ }
+
+ @Test
+ public void testCreateValueDouble() throws Exception {
+ Value v = syncCtx.createValue(Double.valueOf(1.1));
+ assertNotNull(v);
+ assertEquals(PropertyType.DOUBLE, v.getType());
+ assertEquals(1.1, v.getDouble(), 0);
+
+ v = syncCtx.createValue(Float.NaN);
+ assertNotNull(v);
+ assertEquals(PropertyType.DOUBLE, v.getType());
+ assertEquals(Float.NaN, v.getDouble(), 0);
+ }
+
+ @Test
+ public void testCreateValueDate() throws Exception {
+ Date d = new Date();
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(d);
+
+ Value v = syncCtx.createValue(cal);
+ assertNotNull(v);
+ assertEquals(PropertyType.DATE, v.getType());
+
+ Value v2 = syncCtx.createValue(d);
+ assertNotNull(v2);
+ assertEquals(PropertyType.DATE, v2.getType());
+
+ assertEquals(v, v2);
+ }
+
+ @Test
+ public void testCreateValueDecimal() throws Exception {
+ BigDecimal dec = new BigDecimal(123);
+ Value v = syncCtx.createValue(dec);
+ assertNotNull(v);
+ assertEquals(PropertyType.DECIMAL, v.getType());
+ assertEquals(dec, v.getDecimal());
+ }
+
+ @Test
+ public void testCreateValueFromBytesArray() throws Exception {
+ byte[] bytes = new byte[]{'a', 'b'};
+ ByteArrayInputStream is = new ByteArrayInputStream(bytes);
+ Binary binary = getValueFactory().createBinary(is);
+
+ Value v = syncCtx.createValue(bytes);
+ assertNotNull(v);
+ assertEquals(PropertyType.BINARY, v.getType());
+ assertEquals(binary, v.getBinary());
+ }
+
/**
* @see <a href="https://issues.apache.org/jira/browse/OAK-4231">OAK-4231</a>
*/
@@ -374,10 +1074,88 @@ public class DefaultSyncContextTest exte
assertEquals(binary, v.getBinary());
}
+ @Test
+ public void testCreateValuesEmptyCollection() throws Exception {
+ Value[] vs = syncCtx.createValues(ImmutableList.of());
+ assertNotNull(vs);
+ assertEquals(0, vs.length);
+ }
+
+ @Test
+ public void testCreateValuesSkipsNull() throws Exception {
+ List<String> strings = Lists.newArrayList("s", null, null, "t");
+ Value[] vs = syncCtx.createValues(strings);
+ assertNotNull(vs);
+ assertEquals(2, vs.length);
+ }
+
+ @Test
+ public void testIsSameIDPNull() throws Exception {
+ assertFalse(syncCtx.isSameIDP(null));
+ }
+
+ @Test
+ public void testIsSameIDPLocalGroup() throws Exception {
+ assertFalse(syncCtx.isSameIDP(createTestGroup()));
+ }
+
+ @Test
+ public void testIsSameIDPLocalUser() throws Exception {
+ assertFalse(syncCtx.isSameIDP(getTestUser()));
+ }
+
+ @Test
+ public void testIsSameIDPSyncedGroup() throws Exception {
+ ExternalIdentity externalGroup = idp.listGroups().next();
+ sync(externalGroup);
+
+ assertTrue(syncCtx.isSameIDP(getUserManager(root).getAuthorizable(externalGroup.getId())));
+ }
+
+ @Test
+ public void testIsSameIDPSyncedUser() throws Exception {
+ ExternalIdentity externalUser = idp.listUsers().next();
+ sync(externalUser);
+
+ assertTrue(syncCtx.isSameIDP(getUserManager(root).getAuthorizable(externalUser.getId())));
+ }
+
+ @Test
+ public void testIsSameIDPMissingExternalId() throws Exception {
+ ExternalIdentity externalUser = idp.listUsers().next();
+ sync(externalUser);
+
+ Authorizable a = getUserManager(root).getAuthorizable(externalUser.getId());
+ a.removeProperty(DefaultSyncContext.REP_EXTERNAL_ID);
+
+ assertFalse(syncCtx.isSameIDP(a));
+ }
+
+ @Test
+ public void testIsSameIDPForeign() throws Exception {
+ Group gr = createTestGroup();
+ setExternalID(gr, "some_other_idp");
+
+ assertFalse(syncCtx.isSameIDP(gr));
+ }
+
/**
* ExternalIdentity implementation that is neither user nor group.
*/
- private final class TestExternalIdentity implements ExternalIdentity {
+ private class TestExternalIdentity implements ExternalIdentity {
+
+ private final String id;
+ private final String principalName;
+
+ private TestExternalIdentity() {
+ this.id = "externalId";
+ this.principalName = "principalName";
+ }
+
+ private TestExternalIdentity(ExternalIdentity base) {
+ this.id = base.getId();
+ this.principalName = base.getPrincipalName();
+ }
@Nonnull
@Override
@@ -388,13 +1166,13 @@ public class DefaultSyncContextTest exte
@Nonnull
@Override
public String getId() {
- return "externalId";
+ return id;
}
@Nonnull
@Override
public String getPrincipalName() {
- return "principalName";
+ return principalName;
}
@CheckForNull
@@ -405,7 +1183,7 @@ public class DefaultSyncContextTest exte
@Nonnull
@Override
- public Iterable<ExternalIdentityRef> getDeclaredGroups() {
+ public Iterable<ExternalIdentityRef> getDeclaredGroups() throws ExternalIdentityException {
return ImmutableSet.of();
}
@@ -415,4 +1193,40 @@ public class DefaultSyncContextTest exte
return ImmutableMap.of();
}
}
+
+ private final class ForeignExternalUser extends TestExternalIdentity implements ExternalUser {
+
+ @Nonnull
+ @Override
+ public ExternalIdentityRef getExternalId() {
+ return new ExternalIdentityRef(getId(), "AnotherExternalIDP");
+ }
+ }
+
+ private final class ExternalUserWithDeclaredGroup extends TestExternalIdentity implements ExternalUser {
+
+ private final ExternalIdentityRef declaredGroupRef;
+
+ private ExternalUserWithDeclaredGroup(@Nonnull ExternalIdentityRef declaredGroupRef) {
+ this.declaredGroupRef = declaredGroupRef;
+ }
+
+ private ExternalUserWithDeclaredGroup(@Nonnull ExternalIdentityRef declaredGroupRef, @Nonnull ExternalIdentity base) {
+ super(base);
+ this.declaredGroupRef = declaredGroupRef;
+ }
+
+ @Nonnull
+ @Override
+ public Iterable<ExternalIdentityRef> getDeclaredGroups() {
+ return ImmutableSet.of(declaredGroupRef);
+ }
+ }
+
+ private final class ExternalUserFromGroup extends TestExternalIdentity implements ExternalUser {
+
+ private ExternalUserFromGroup(@Nonnull ExternalIdentity base) {
+ super(base);
+ }
+ }
}
\ No newline at end of file