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/05/17 16:18:30 UTC
svn commit: r1744292 [2/3] - in /jackrabbit/oak/trunk:
oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/basic/
oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/...
Copied: jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleDynamicMembershipTest.java (from r1742077, jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleDynamicMembershipTest.java?p2=jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleDynamicMembershipTest.java&p1=jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java&r1=1742077&r2=1744292&rev=1744292&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java (original)
+++ jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleDynamicMembershipTest.java Tue May 17 16:18:29 2016
@@ -16,123 +16,98 @@
*/
package org.apache.jackrabbit.oak.spi.security.authentication.external;
+import java.util.HashSet;
+import java.util.Set;
+import javax.annotation.Nonnull;
import javax.jcr.SimpleCredentials;
-import javax.security.auth.login.LoginException;
+import javax.jcr.Value;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.UserManager;
-import org.apache.jackrabbit.oak.api.ContentSession;
-import org.apache.jackrabbit.oak.namepath.NamePathMapper;
-import org.apache.jackrabbit.oak.plugins.value.ValueFactoryImpl;
-import org.junit.After;
-import org.junit.Before;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalIdentityConstants;
import org.junit.Test;
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.assertTrue;
-import static org.junit.Assert.fail;
-/**
- * ExternalLoginModuleTest...
- */
-public class ExternalLoginModuleTest extends ExternalLoginModuleTestBase {
+public class ExternalLoginModuleDynamicMembershipTest extends ExternalLoginModuleTest {
- @Before
+ @Override
public void before() throws Exception {
super.before();
+
+ syncConfig.user().setDynamicMembership(true);
}
- @After
- public void after() throws Exception {
- super.after();
+ private void assertExternalPrincipalNames(@Nonnull UserManager userMgr, @Nonnull String id) throws Exception {
+ Authorizable a = userMgr.getAuthorizable(id);
+ assertNotNull(a);
+
+ Set<String> expected = new HashSet();
+ calcExpectedPrincipalNames(idp.getUser(id), syncConfig.user().getMembershipNestingDepth(), expected);
+
+ Set<String> extPrincNames = new HashSet();
+ for (Value v : a.getProperty(ExternalIdentityConstants.REP_EXTERNAL_PRINCIPAL_NAMES)) {
+ extPrincNames.add(v.getString());
+ }
+
+ assertEquals(expected, extPrincNames);
}
- @Test
- public void testLoginFailed() throws Exception {
- UserManager userManager = getUserManager(root);
- try {
- ContentSession cs = login(new SimpleCredentials("unknown", new char[0]));
- cs.close();
- fail("login failure expected");
- } catch (LoginException e) {
- // success
- } finally {
- assertNull(userManager.getAuthorizable(USER_ID));
+ private void calcExpectedPrincipalNames(@Nonnull ExternalIdentity identity, long depth, @Nonnull Set<String> expected) throws Exception {
+ if (depth <= 0) {
+ return;
+ }
+ for (ExternalIdentityRef ref : identity.getDeclaredGroups()) {
+ ExternalIdentity groupIdentity = idp.getIdentity(ref);
+ expected.add(groupIdentity.getPrincipalName());
+ calcExpectedPrincipalNames(groupIdentity, depth-1, expected);
}
}
@Test
- public void testSyncCreateUser() throws Exception {
- UserManager userManager = getUserManager(root);
- ContentSession cs = null;
+ public void testSyncCreatesRepExternalPrincipals() throws Exception {
try {
- assertNull(userManager.getAuthorizable(USER_ID));
-
- cs = login(new SimpleCredentials(USER_ID, new char[0]));
+ login(new SimpleCredentials(USER_ID, new char[0])).close();
root.refresh();
-
- Authorizable a = userManager.getAuthorizable(USER_ID);
- assertNotNull(a);
- ExternalUser user = idp.getUser(USER_ID);
- for (String prop : user.getProperties().keySet()) {
- assertTrue(a.hasProperty(prop));
- }
- assertEquals(TEST_CONSTANT_PROPERTY_VALUE, a.getProperty(TEST_CONSTANT_PROPERTY_NAME)[0].getString());
+ assertExternalPrincipalNames(getUserManager(root), USER_ID);
} finally {
- if (cs != null) {
- cs.close();
- }
options.clear();
}
}
@Test
- public void testSyncCreateUserCaseInsensitive() throws Exception {
- UserManager userManager = getUserManager(root);
- ContentSession cs = null;
+ public void testSyncCreatesRepExternalPrincipalsDepthInfinite() throws Exception {
+ syncConfig.user().setMembershipNestingDepth(Long.MAX_VALUE);
try {
- assertNull(userManager.getAuthorizable(USER_ID));
-
- cs = login(new SimpleCredentials(USER_ID.toUpperCase(), new char[0]));
+ login(new SimpleCredentials(USER_ID, new char[0])).close();
root.refresh();
-
- Authorizable a = userManager.getAuthorizable(USER_ID);
- assertNotNull(a);
- ExternalUser user = idp.getUser(USER_ID);
- for (String prop : user.getProperties().keySet()) {
- assertTrue(a.hasProperty(prop));
- }
- assertEquals(TEST_CONSTANT_PROPERTY_VALUE, a.getProperty(TEST_CONSTANT_PROPERTY_NAME)[0].getString());
+ assertExternalPrincipalNames(getUserManager(root), USER_ID);
} finally {
- if (cs != null) {
- cs.close();
- }
options.clear();
}
}
@Test
public void testSyncCreateGroup() throws Exception {
- UserManager userManager = getUserManager(root);
- ContentSession cs = null;
try {
- cs = login(new SimpleCredentials(USER_ID, new char[0]));
+ login(new SimpleCredentials(USER_ID, new char[0])).close();
root.refresh();
+ UserManager userManager = getUserManager(root);
for (String id : new String[]{"a", "b", "c"}) {
- assertNotNull(userManager.getAuthorizable(id));
+ assertNull(userManager.getAuthorizable(id));
}
for (String id : new String[]{"aa", "aaa"}) {
assertNull(userManager.getAuthorizable(id));
}
} finally {
- if (cs != null) {
- cs.close();
- }
options.clear();
}
}
@@ -140,47 +115,72 @@ public class ExternalLoginModuleTest ext
@Test
public void testSyncCreateGroupNesting() throws Exception {
syncConfig.user().setMembershipNestingDepth(2);
- UserManager userManager = getUserManager(root);
- ContentSession cs = null;
try {
- cs = login(new SimpleCredentials(USER_ID, new char[0]));
+ login(new SimpleCredentials(USER_ID, new char[0])).close();
root.refresh();
for (String id : new String[]{"a", "b", "c", "aa", "aaa"}) {
- assertNotNull(userManager.getAuthorizable(id));
+ assertNull(getUserManager(root).getAuthorizable(id));
}
} finally {
- if (cs != null) {
- cs.close();
- }
options.clear();
}
}
@Test
- public void testSyncUpdate() throws Exception {
- // create user upfront in order to test update mode
- UserManager userManager = getUserManager(root);
- ExternalUser externalUser = idp.getUser(USER_ID);
- Authorizable user = userManager.createUser(externalUser.getId(), null);
- user.setProperty("rep:externalId", new ValueFactoryImpl(root, NamePathMapper.DEFAULT).createValue(externalUser.getExternalId().getString()));
- root.commit();
-
- ContentSession cs = null;
+ public void testSyncUpdateAfterXmlImport() throws Exception {
try {
- cs = login(new SimpleCredentials(USER_ID, new char[0]));
+ // force initial sync
+ login(new SimpleCredentials(USER_ID, new char[0])).close();
- root.refresh();
+ // remove properties according to the behavior in the XML-import
+ Root systemRoot = getSystemRoot();
+ UserManager userManager = getUserManager(systemRoot);
Authorizable a = userManager.getAuthorizable(USER_ID);
- assertNotNull(a);
- for (String prop : externalUser.getProperties().keySet()) {
- assertTrue(a.hasProperty(prop));
- }
+ a.removeProperty(ExternalIdentityConstants.REP_EXTERNAL_PRINCIPAL_NAMES);
+ a.removeProperty(ExternalIdentityConstants.REP_LAST_SYNCED);
+ systemRoot.commit();
+
+ // login again to force sync of the user (and it's group membership)
+ login(new SimpleCredentials(USER_ID, new char[0])).close();
+
+ systemRoot.refresh();
+ a = userManager.getAuthorizable(USER_ID);
+ assertTrue(a.hasProperty(ExternalIdentityConstants.REP_LAST_SYNCED));
+ assertExternalPrincipalNames(userManager, USER_ID);
} finally {
- if (cs != null) {
- cs.close();
+ options.clear();
+ }
+ }
+
+ @Test
+ public void testSyncUpdateWithRemovedPrincipalNames() throws Exception {
+ try {
+ // force initial sync
+ login(new SimpleCredentials(USER_ID, new char[0])).close();
+
+ // removing the rep:externalPrincipalNames property only will have the same
+ // effect as the compatibility behavior that respects previously
+ // synchronized users with full membership sync.
+ Root systemRoot = getSystemRoot();
+ UserManager userManager = getUserManager(systemRoot);
+ Authorizable a = userManager.getAuthorizable(USER_ID);
+ a.removeProperty(ExternalIdentityConstants.REP_EXTERNAL_PRINCIPAL_NAMES);
+ systemRoot.commit();
+
+ // login again
+ login(new SimpleCredentials(USER_ID, new char[0])).close();
+
+ systemRoot.refresh();
+ a = userManager.getAuthorizable(USER_ID);
+ assertTrue(a.hasProperty(ExternalIdentityConstants.REP_LAST_SYNCED));
+ assertFalse(a.hasProperty(ExternalIdentityConstants.REP_EXTERNAL_PRINCIPAL_NAMES));
+
+ for (ExternalIdentityRef ref : idp.getUser(USER_ID).getDeclaredGroups()) {
+ assertNotNull(userManager.getAuthorizable(ref.getId()));
}
+ } finally {
options.clear();
}
}
Modified: jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java?rev=1744292&r1=1744291&r2=1744292&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java (original)
+++ jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java Tue May 17 16:18:29 2016
@@ -22,8 +22,7 @@ import javax.security.auth.login.LoginEx
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.jackrabbit.oak.api.ContentSession;
-import org.apache.jackrabbit.oak.namepath.NamePathMapper;
-import org.apache.jackrabbit.oak.plugins.value.ValueFactoryImpl;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.basic.DefaultSyncContext;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -163,7 +162,7 @@ public class ExternalLoginModuleTest ext
UserManager userManager = getUserManager(root);
ExternalUser externalUser = idp.getUser(USER_ID);
Authorizable user = userManager.createUser(externalUser.getId(), null);
- user.setProperty("rep:externalId", new ValueFactoryImpl(root, NamePathMapper.DEFAULT).createValue(externalUser.getExternalId().getString()));
+ user.setProperty(DefaultSyncContext.REP_EXTERNAL_ID, getValueFactory().createValue(externalUser.getExternalId().getString()));
root.commit();
ContentSession cs = null;
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=1744292&r1=1744291&r2=1744292&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 May 17 16:18:29 2016
@@ -33,6 +33,7 @@ public class TestIdentityProvider implem
public static final String ID_TEST_USER = "testUser";
public static final String ID_SECOND_USER = "secondUser";
+ public static final String ID_WILDCARD_USER = "wildcardUser";
public static final String ID_EXCEPTION = "throw!";
@@ -46,6 +47,8 @@ public class TestIdentityProvider implem
addGroup(new TestGroup("b", getName()).withGroups("a"));
addGroup(new TestGroup("c", getName()));
addGroup(new TestGroup("secondGroup", getName()));
+ addGroup(new TestGroup("_gr_u_", getName()));
+ addGroup(new TestGroup("g%r%", getName()));
addUser(new TestUser(ID_TEST_USER, getName())
.withProperty("name", "Test User")
@@ -63,6 +66,9 @@ public class TestIdentityProvider implem
.withProperty("charArr", new char[]{'t', 'o', 'b'})
.withProperty("byteArr", new byte[0])
.withGroups("secondGroup"));
+
+ addUser(new TestUser(ID_WILDCARD_USER, getName())
+ .withGroups("_gr_u_", "g%r%"));
}
private void addUser(TestIdentity user) {
Added: jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestSecurityProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestSecurityProvider.java?rev=1744292&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestSecurityProvider.java (added)
+++ jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestSecurityProvider.java Tue May 17 16:18:29 2016
@@ -0,0 +1,42 @@
+/*
+ * 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;
+
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.oak.security.SecurityProviderImpl;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.principal.ExternalPrincipalConfiguration;
+import org.apache.jackrabbit.oak.spi.security.principal.CompositePrincipalConfiguration;
+import org.apache.jackrabbit.oak.spi.security.principal.PrincipalConfiguration;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public class TestSecurityProvider extends SecurityProviderImpl {
+ public TestSecurityProvider(@Nonnull ConfigurationParameters configuration) {
+ super(configuration);
+
+ PrincipalConfiguration principalConfiguration = getConfiguration(PrincipalConfiguration.class);
+ if (!(principalConfiguration instanceof CompositePrincipalConfiguration)) {
+ throw new IllegalStateException();
+ } else {
+ PrincipalConfiguration defConfig = checkNotNull(((CompositePrincipalConfiguration) principalConfiguration).getDefaultConfig());
+ bindPrincipalConfiguration((new ExternalPrincipalConfiguration(this)));
+ bindPrincipalConfiguration(defConfig);
+ }
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestSecurityProvider.java
------------------------------------------------------------------------------
svn:eol-style = native
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=1744292&r1=1744291&r2=1744292&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 May 17 16:18:29 2016
@@ -18,7 +18,6 @@ package org.apache.jackrabbit.oak.spi.se
import java.io.ByteArrayInputStream;
import java.math.BigDecimal;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
@@ -71,8 +70,6 @@ public class DefaultSyncContextTest exte
private ValueFactory valueFactory;
private DefaultSyncContext syncCtx;
- private List<String> authorizableIds = new ArrayList<String>();
-
@Before
public void before() throws Exception {
super.before();
@@ -86,13 +83,6 @@ public class DefaultSyncContextTest exte
try {
syncCtx.close();
root.refresh();
- for (String id : authorizableIds) {
- Authorizable a = userManager.getAuthorizable(id);
- if (a != null) {
- a.remove();
- }
- }
- root.commit();
} finally {
super.after();
}
@@ -104,9 +94,7 @@ public class DefaultSyncContextTest exte
}
private Group createTestGroup() throws Exception {
- Group gr = userManager.createGroup("group" + UUID.randomUUID());
- authorizableIds.add(gr.getID());
- return gr;
+ return userManager.createGroup("group" + UUID.randomUUID());
}
/**
@@ -380,8 +368,6 @@ public class DefaultSyncContextTest exte
// mark a regular repo user as external user from the test IDP
User u = userManager.createUser("test" + UUID.randomUUID(), null);
String userId = u.getID();
- authorizableIds.add(userId);
-
setExternalID(u, idp.getName());
// test sync with 'keepmissing' = true
@@ -484,7 +470,7 @@ public class DefaultSyncContextTest exte
@Test
public void testSyncByForeignId2() throws Exception {
- User u = getTestUser();
+ User u = userManager.getAuthorizable(getTestUser().getID(), User.class);
setExternalID(u, "differentIDP");
SyncResult result = syncCtx.sync(u.getID());
@@ -1138,7 +1124,7 @@ public class DefaultSyncContextTest exte
@Test
public void testIsSameIDPNull() throws Exception {
- assertFalse(syncCtx.isSameIDP(null));
+ assertFalse(syncCtx.isSameIDP((Authorizable) null));
}
@Test
@@ -1186,6 +1172,16 @@ public class DefaultSyncContextTest exte
assertFalse(syncCtx.isSameIDP(gr));
}
+ @Test
+ public void testIsSameIDPExternalIdentityRef() throws Exception {
+ assertFalse(syncCtx.isSameIDP(new TestIdentityProvider.ForeignExternalUser().getExternalId()));
+ assertFalse(syncCtx.isSameIDP(new TestIdentityProvider.ForeignExternalGroup().getExternalId()));
+
+ assertTrue(syncCtx.isSameIDP(new TestIdentityProvider.TestIdentity().getExternalId()));
+ assertTrue(syncCtx.isSameIDP(idp.listGroups().next().getExternalId()));
+ assertTrue(syncCtx.isSameIDP(idp.listUsers().next().getExternalId()));
+ }
+
private final class ExternalUserWithDeclaredGroup extends TestIdentityProvider.TestIdentity implements ExternalUser {
private final ExternalIdentityRef declaredGroupRef;
Added: jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DynamicSyncContextTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DynamicSyncContextTest.java?rev=1744292&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DynamicSyncContextTest.java (added)
+++ jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DynamicSyncContextTest.java Tue May 17 16:18:29 2016
@@ -0,0 +1,440 @@
+/*
+ * 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;
+
+import java.util.HashSet;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.AbstractExternalAuthTest;
+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.SyncContext;
+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.DefaultSyncConfig;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.basic.DefaultSyncContext;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+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;
+import static org.junit.Assert.fail;
+
+public class DynamicSyncContextTest extends AbstractExternalAuthTest {
+
+ private Root r;
+ private UserManager userManager;
+ private ValueFactory valueFactory;
+
+ private DynamicSyncContext syncContext;
+
+ @Before
+ public void before() throws Exception {
+ super.before();
+ r = getSystemRoot();
+ userManager = getUserManager(r);
+ valueFactory = getValueFactory(r);
+ syncContext = new DynamicSyncContext(syncConfig, idp, userManager, valueFactory);
+ }
+
+ @After
+ public void after() throws Exception {
+ try {
+ syncContext.close();
+ r.refresh();
+ } finally {
+ super.after();
+ }
+ }
+
+ @Override
+ protected DefaultSyncConfig createSyncConfig() {
+ DefaultSyncConfig sc = super.createSyncConfig();
+ sc.user().setDynamicMembership(true);
+ return sc;
+ }
+
+ private void sync(@Nonnull ExternalIdentity externalIdentity, @Nonnull SyncResult.Status expectedStatus) throws Exception {
+ SyncResult result = syncContext.sync(externalIdentity);
+ assertSame(expectedStatus, result.getStatus());
+ r.commit();
+ }
+
+ private void assertDynamicMembership(@Nonnull Authorizable a, @Nonnull ExternalIdentity externalIdentity, long depth) throws Exception {
+ Value[] vs = a.getProperty(ExternalIdentityConstants.REP_EXTERNAL_PRINCIPAL_NAMES);
+ Iterable<String> pNames = Iterables.transform(ImmutableList.copyOf(vs), new Function<Value, String>() {
+ @Nullable
+ @Override
+ public String apply(Value input) {
+ try {
+ return input.getString();
+ } catch (RepositoryException e) {
+ fail(e.getMessage());
+ return null;
+ }
+ };
+ });
+
+ Set<String> expected = new HashSet<>();
+ collectGroupPrincipals(expected, externalIdentity.getDeclaredGroups(), depth);
+
+ assertEquals(expected, ImmutableSet.copyOf(pNames));
+ }
+
+ private void collectGroupPrincipals(Set<String> pNames, @Nonnull Iterable<ExternalIdentityRef> declaredGroups, long depth) throws ExternalIdentityException {
+ if (depth <= 0) {
+ return;
+ }
+ for (ExternalIdentityRef ref : declaredGroups) {
+ ExternalIdentity ei = idp.getIdentity(ref);
+ pNames.add(ei.getPrincipalName());
+ collectGroupPrincipals(pNames, ei.getDeclaredGroups(), depth - 1);
+ }
+ }
+
+ private static void assertSyncedMembership(@Nonnull UserManager userManager,
+ @Nonnull Authorizable a,
+ @Nonnull ExternalIdentity externalIdentity) throws Exception {
+ for (ExternalIdentityRef ref : externalIdentity.getDeclaredGroups()) {
+ Group gr = userManager.getAuthorizable(ref.getId(), Group.class);
+ assertNotNull(gr);
+ assertTrue(gr.isMember(a));
+ }
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSyncExternalIdentity() throws Exception {
+ syncContext.sync(new TestIdentityProvider.TestIdentity());
+ }
+
+ @Test
+ public void testSyncExternalUser() throws Exception {
+ ExternalUser externalUser = idp.getUser(USER_ID);
+ sync(externalUser, SyncResult.Status.ADD);
+
+ assertNotNull(userManager.getAuthorizable(USER_ID));
+ }
+
+ @Test
+ public void testSyncExternalUserDepth0() throws Exception {
+ syncConfig.user().setMembershipNestingDepth(0);
+
+ ExternalUser externalUser = idp.getUser(USER_ID);
+ sync(externalUser, SyncResult.Status.ADD);
+
+ Tree tree = r.getTree(userManager.getAuthorizable(USER_ID).getPath());
+ PropertyState extPrincipalNames = tree.getProperty(ExternalIdentityConstants.REP_EXTERNAL_PRINCIPAL_NAMES);
+ assertNotNull(extPrincipalNames);
+ assertEquals(0, extPrincipalNames.count());
+ }
+
+ @Test
+ public void testSyncExternalUserDepth1() throws Exception {
+ syncConfig.user().setMembershipNestingDepth(1);
+
+ ExternalUser externalUser = idp.getUser(USER_ID);
+ sync(externalUser, SyncResult.Status.ADD);
+
+ Tree tree = r.getTree(userManager.getAuthorizable(USER_ID).getPath());
+ PropertyState extPrincipalNames = tree.getProperty(ExternalIdentityConstants.REP_EXTERNAL_PRINCIPAL_NAMES);
+ assertNotNull(extPrincipalNames);
+
+ Set<String> pNames = Sets.newHashSet(extPrincipalNames.getValue(Type.STRINGS));
+ for (ExternalIdentityRef ref : externalUser.getDeclaredGroups()) {
+ assertTrue(pNames.remove(idp.getIdentity(ref).getPrincipalName()));
+ }
+ assertTrue(pNames.isEmpty());
+ }
+
+ @Test
+ public void testSyncExternalUserDepthInfinite() throws Exception {
+ syncConfig.user().setMembershipNestingDepth(Long.MAX_VALUE);
+
+ ExternalUser externalUser = idp.getUser(USER_ID);
+ sync(externalUser, SyncResult.Status.ADD);
+
+ Tree tree = r.getTree(userManager.getAuthorizable(USER_ID).getPath());
+ PropertyState extPrincipalNames = tree.getProperty(ExternalIdentityConstants.REP_EXTERNAL_PRINCIPAL_NAMES);
+ assertNotNull(extPrincipalNames);
+
+ Set<String> pNames = Sets.newHashSet(extPrincipalNames.getValue(Type.STRINGS));
+ Set<String> expected = Sets.newHashSet();
+ collectGroupPrincipals(expected, externalUser.getDeclaredGroups(), Long.MAX_VALUE);
+
+ assertEquals(expected, pNames);
+ }
+
+ @Test
+ public void testSyncExternalUserExistingGroups() throws Exception {
+ syncConfig.user().setMembershipNestingDepth(1);
+
+ ExternalUser externalUser = idp.getUser(USER_ID);
+
+ DefaultSyncContext ctx = new DefaultSyncContext(syncConfig, idp, userManager, valueFactory);
+ ctx.sync(externalUser);
+ ctx.close();
+
+ Authorizable a = userManager.getAuthorizable(USER_ID);
+ assertSyncedMembership(userManager, a, externalUser);
+
+ syncContext.setForceUserSync(true);
+ syncConfig.user().setMembershipExpirationTime(-1);
+ syncContext.sync(externalUser);
+
+ Tree t = r.getTree(a.getPath());
+ assertFalse(t.hasProperty(ExternalIdentityConstants.REP_EXTERNAL_PRINCIPAL_NAMES));
+
+ assertSyncedMembership(userManager, a, externalUser);
+ }
+
+ @Test
+ public void testSyncExternalGroup() throws Exception {
+ ExternalGroup gr = idp.listGroups().next();
+
+ syncContext.sync(gr);
+ assertNull(userManager.getAuthorizable(gr.getId()));
+ assertFalse(r.hasPendingChanges());
+ }
+
+ @Test
+ public void testSyncExternalGroupVerifyStatus() throws Exception {
+ ExternalGroup gr = idp.listGroups().next();
+
+ SyncResult result = syncContext.sync(gr);
+ assertEquals(SyncResult.Status.NOP, result.getStatus());
+
+ result = syncContext.sync(gr);
+ assertEquals(SyncResult.Status.NOP, result.getStatus());
+
+ syncContext.setForceGroupSync(true);
+ result = syncContext.sync(gr);
+ assertEquals(SyncResult.Status.NOP, result.getStatus());
+ }
+
+ @Test
+ public void testSyncExternalGroupExisting() throws Exception {
+ // create an external external group that already has been synced into the repo
+ ExternalGroup externalGroup = idp.listGroups().next();
+ SyncContext ctx = new DefaultSyncContext(syncConfig, idp, userManager, valueFactory);
+ ctx.sync(externalGroup);
+ ctx.close();
+
+ // synchronizing using DynamicSyncContext must update the existing group
+ syncContext.setForceGroupSync(true);
+ SyncResult result = syncContext.sync(externalGroup);
+ assertSame(SyncResult.Status.UPDATE, result.getStatus());
+ }
+
+ @Test
+ public void testSyncForeignExternalGroup() throws Exception {
+ ExternalGroup foreign = new TestIdentityProvider.ForeignExternalGroup();
+
+ SyncResult res = syncContext.sync(foreign);
+ assertNotNull(res);
+ assertSame(SyncResult.Status.FOREIGN, res.getStatus());
+
+ // expect {@code SyncedIdentity} in accordance with {@code sync(String userId)},
+ // where the authorizable is found to be linked to a different IDP.
+ SyncedIdentity si = res.getIdentity();
+ assertNotNull(si);
+ assertEquals(foreign.getId(), si.getId());
+ ExternalIdentityRef ref = si.getExternalIdRef();
+ assertNotNull(ref);
+ assertEquals(foreign.getExternalId(), ref);
+ assertTrue(si.isGroup());
+ assertEquals(-1, si.lastSynced());
+
+ assertFalse(r.hasPendingChanges());
+ }
+
+ @Test
+ public void testSyncUserByIdUpdate() throws Exception {
+ ExternalIdentity externalId = idp.listUsers().next();
+
+ Authorizable a = userManager.createUser(externalId.getId(), null);
+ a.setProperty(DefaultSyncContext.REP_EXTERNAL_ID, valueFactory.createValue(externalId.getExternalId().getString()));
+
+ syncContext.setForceUserSync(true);
+ SyncResult result = syncContext.sync(externalId.getId());
+ assertEquals(SyncResult.Status.UPDATE, result.getStatus());
+
+ Tree t = r.getTree(a.getPath());
+ assertTrue(t.hasProperty(ExternalIdentityConstants.REP_EXTERNAL_PRINCIPAL_NAMES));
+ }
+
+ @Test
+ public void testSyncUserIdExistingGroups() throws Exception {
+ ExternalUser externalUser = idp.getUser(USER_ID);
+
+ DefaultSyncContext ctx = new DefaultSyncContext(syncConfig, idp, userManager, valueFactory);
+ ctx.sync(externalUser);
+ ctx.close();
+
+ Authorizable user = userManager.getAuthorizable(externalUser.getId());
+ for (ExternalIdentityRef ref : externalUser.getDeclaredGroups()) {
+ Group gr = userManager.getAuthorizable(ref.getId(), Group.class);
+ assertTrue(gr.isMember(user));
+ }
+
+ syncContext.setForceUserSync(true);
+ syncContext.sync(externalUser.getId());
+
+ Authorizable a = userManager.getAuthorizable(USER_ID);
+ Tree t = r.getTree(a.getPath());
+ assertFalse(t.hasProperty(ExternalIdentityConstants.REP_EXTERNAL_PRINCIPAL_NAMES));
+ assertSyncedMembership(userManager, a, externalUser);
+ }
+
+ @Test
+ public void testSyncMembershipWithNesting() throws Exception {
+ long nesting = 1;
+ syncConfig.user().setMembershipNestingDepth(nesting);
+
+ ExternalUser externalUser = idp.getUser(USER_ID);
+ sync(externalUser, SyncResult.Status.ADD);
+
+ Authorizable a = userManager.getAuthorizable(externalUser.getId());
+ assertDynamicMembership(a, externalUser, nesting);
+
+ // verify that the membership is always reflected in the rep:externalPrincipalNames property
+ // 1. membership nesting = -1
+ nesting = -1;
+ syncContext.syncMembership(externalUser, a, nesting);
+ assertDynamicMembership(a, externalUser, nesting);
+
+ // 2. membership nesting is > 0
+ nesting = Long.MAX_VALUE;
+ syncContext.syncMembership(externalUser, a, nesting);
+ assertDynamicMembership(a, externalUser, nesting);
+ }
+
+ @Test
+ public void testSyncMembershipWithChangedGroups() throws Exception {
+ long nesting = 1;
+ syncConfig.user().setMembershipNestingDepth(nesting);
+
+ ExternalUser externalUser = idp.getUser(USER_ID);
+ sync(externalUser, SyncResult.Status.ADD);
+
+ Authorizable a = userManager.getAuthorizable(externalUser.getId());
+ assertDynamicMembership(a, externalUser, nesting);
+
+ // sync user with modified membership => must be reflected
+ // 1. empty set of declared groups
+ ExternalUser mod = new TestUserWithGroupRefs(externalUser, ImmutableSet.<ExternalIdentityRef>of());
+ syncContext.syncMembership(mod, a, nesting);
+ assertDynamicMembership(a, mod, nesting);
+
+ // 2. set with different groups that defined on IDP
+ mod = new TestUserWithGroupRefs(externalUser, ImmutableSet.<ExternalIdentityRef>of(
+ idp.getGroup("a").getExternalId(),
+ idp.getGroup("aa").getExternalId(),
+ idp.getGroup("secondGroup").getExternalId()));
+ syncContext.syncMembership(mod, a, nesting);
+ assertDynamicMembership(a, mod, nesting);
+ }
+
+ @Test
+ public void testSyncMembershipWithChangedExistingGroups() throws Exception {
+ long nesting = 1;
+ syncConfig.user().setMembershipNestingDepth(nesting);
+
+ ExternalUser externalUser = idp.getUser(USER_ID);
+
+ DefaultSyncContext ctx = new DefaultSyncContext(syncConfig, idp, userManager, valueFactory);
+ ctx.sync(externalUser);
+ ctx.close();
+
+ Authorizable a = userManager.getAuthorizable(externalUser.getId());
+ assertSyncedMembership(userManager, a, externalUser);
+
+ // sync user with modified membership => must be reflected
+ // 1. empty set of declared groups
+ ExternalUser mod = new TestUserWithGroupRefs(externalUser, ImmutableSet.<ExternalIdentityRef>of());
+ syncContext.syncMembership(mod, a, nesting);
+ assertSyncedMembership(userManager, a, mod);
+
+ // 2. set with different groups that defined on IDP
+ mod = new TestUserWithGroupRefs(externalUser, ImmutableSet.<ExternalIdentityRef>of(
+ idp.getGroup("a").getExternalId(),
+ idp.getGroup("aa").getExternalId(),
+ idp.getGroup("secondGroup").getExternalId()));
+ syncContext.syncMembership(mod, a, nesting);
+ assertSyncedMembership(userManager, a, mod);
+ }
+
+ @Test
+ public void testSyncMembershipForExternalGroup() throws Exception {
+ ExternalGroup externalGroup = idp.getGroup("a"); // a group that has declaredGroups
+ SyncContext ctx = new DefaultSyncContext(syncConfig, idp, userManager, valueFactory);
+ ctx.sync(externalGroup);
+ ctx.close();
+ r.commit();
+
+ Authorizable gr = userManager.getAuthorizable(externalGroup.getId());
+ syncContext.syncMembership(externalGroup, gr, 1);
+
+ assertFalse(gr.hasProperty(ExternalIdentityConstants.REP_EXTERNAL_PRINCIPAL_NAMES));
+ assertFalse(r.hasPendingChanges());
+ }
+
+ private static final class TestUserWithGroupRefs extends TestIdentityProvider.TestIdentity implements ExternalUser {
+
+ private Iterable<ExternalIdentityRef> declaredGroupRefs;
+
+ private TestUserWithGroupRefs(@Nonnull ExternalUser base, @Nonnull Iterable<ExternalIdentityRef> declaredGroupRefs) {
+ super(base);
+ this.declaredGroupRefs = declaredGroupRefs;
+ }
+
+ public String getPassword() {
+ return "";
+ }
+
+ @Nonnull
+ @Override
+ public Iterable<ExternalIdentityRef> getDeclaredGroups() {
+ return declaredGroupRefs;
+ }
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DynamicSyncContextTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/AbstractPrincipalTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/AbstractPrincipalTest.java?rev=1744292&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/AbstractPrincipalTest.java (added)
+++ jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/AbstractPrincipalTest.java Tue May 17 16:18:29 2016
@@ -0,0 +1,97 @@
+/*
+ * 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.principal;
+
+import java.security.Principal;
+import java.util.UUID;
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.AbstractExternalAuthTest;
+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.TestIdentityProvider;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.basic.DefaultSyncConfig;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.basic.DefaultSyncContext;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DynamicSyncContext;
+import org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider;
+import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public abstract class AbstractPrincipalTest extends AbstractExternalAuthTest {
+
+ PrincipalProvider principalProvider;
+
+ @Override
+ public void before() throws Exception {
+ super.before();
+
+ // sync external users into the system using the 2 different sync-context implementations
+ Root systemRoot = getSystemRoot();
+ SyncContext syncContext = new DynamicSyncContext(syncConfig, idp, getUserManager(systemRoot), getValueFactory(systemRoot));
+ syncContext.sync(idp.getUser(USER_ID));
+ syncContext.close();
+
+ syncContext = new DefaultSyncContext(syncConfig, idp, getUserManager(systemRoot), getValueFactory(systemRoot));
+ syncContext.sync(idp.getUser(TestIdentityProvider.ID_SECOND_USER));
+ syncContext.close();
+
+ systemRoot.commit();
+
+ root.refresh();
+ principalProvider = createPrincipalProvider();
+ }
+
+ @Nonnull
+ PrincipalProvider createPrincipalProvider() {
+ return new ExternalGroupPrincipalProvider(root, getSecurityProvider().getConfiguration(UserConfiguration.class), NamePathMapper.DEFAULT);
+ }
+
+ @Override
+ protected DefaultSyncConfig createSyncConfig() {
+ DefaultSyncConfig config = super.createSyncConfig();
+ DefaultSyncConfig.User u = config.user();
+ u.setDynamicMembership(true);
+ return config;
+ }
+
+ java.security.acl.Group getGroupPrincipal() throws Exception {
+ ExternalUser externalUser = idp.getUser(USER_ID);
+ return getGroupPrincipal(externalUser.getDeclaredGroups().iterator().next());
+ }
+
+ java.security.acl.Group getGroupPrincipal(@Nonnull ExternalIdentityRef ref) throws Exception {
+ String principalName = idp.getIdentity(ref).getPrincipalName();
+ Principal p = principalProvider.getPrincipal(principalName);
+
+ assertNotNull(p);
+ assertTrue(p instanceof java.security.acl.Group);
+
+ return (java.security.acl.Group) p;
+ }
+
+ Group createTestGroup() throws Exception {
+ Group gr = getUserManager(root).createGroup("group" + UUID.randomUUID());
+ root.commit();
+ return gr;
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/AbstractPrincipalTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/EmptyPrincipalProviderTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/EmptyPrincipalProviderTest.java?rev=1744292&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/EmptyPrincipalProviderTest.java (added)
+++ jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/EmptyPrincipalProviderTest.java Tue May 17 16:18:29 2016
@@ -0,0 +1,83 @@
+/*
+ * 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.principal;
+
+import java.security.Principal;
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalIdentityConstants;
+import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
+import org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider;
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+public class EmptyPrincipalProviderTest extends AbstractPrincipalTest {
+
+ private String externalPrincipalName;
+ private Principal testPrincipal;
+
+ @Override
+ public void before() throws Exception {
+ super.before();
+
+ assertFalse(principalProvider instanceof ExternalGroupPrincipalProvider);
+
+ externalPrincipalName = getUserManager(root).getAuthorizable(USER_ID).getProperty(ExternalIdentityConstants.REP_EXTERNAL_PRINCIPAL_NAMES)[0].getString();
+ testPrincipal = getTestUser().getPrincipal();
+ }
+
+ @Nonnull
+ @Override
+ PrincipalProvider createPrincipalProvider() {
+ return new ExternalPrincipalConfiguration().getPrincipalProvider(root, NamePathMapper.DEFAULT);
+ }
+
+ @Test
+ public void testGetPrincipal() {
+ assertNull(principalProvider.getPrincipal(externalPrincipalName));
+ assertNull(principalProvider.getPrincipal(testPrincipal.getName()));
+ }
+
+ @Test
+ public void testGetGroupMembership() {
+ assertTrue(principalProvider.getGroupMembership(new PrincipalImpl(externalPrincipalName)).isEmpty());
+ assertTrue(principalProvider.getGroupMembership(testPrincipal).isEmpty());
+ }
+
+ @Test
+ public void testGetPrincipals() throws Exception {
+ assertTrue(principalProvider.getPrincipals(USER_ID).isEmpty());
+ assertTrue(principalProvider.getPrincipals(getTestUser().getID()).isEmpty());
+ }
+
+ @Test
+ public void testFindPrincipalsByHint() {
+ assertFalse(principalProvider.findPrincipals("a", PrincipalManager.SEARCH_TYPE_ALL).hasNext());
+ }
+
+ @Test
+ public void testFindPrincipalsByType() {
+ assertFalse(principalProvider.findPrincipals(PrincipalManager.SEARCH_TYPE_ALL).hasNext());
+ assertFalse(principalProvider.findPrincipals(PrincipalManager.SEARCH_TYPE_NOT_GROUP).hasNext());
+ assertFalse(principalProvider.findPrincipals(PrincipalManager.SEARCH_TYPE_GROUP).hasNext());
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/EmptyPrincipalProviderTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalProviderTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalProviderTest.java?rev=1744292&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalProviderTest.java (added)
+++ jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalProviderTest.java Tue May 17 16:18:29 2016
@@ -0,0 +1,440 @@
+/*
+ * 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.principal;
+
+import java.security.Principal;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Iterators;
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+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.api.Root;
+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.TestIdentityProvider;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.basic.DefaultSyncConfig;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DynamicSyncContext;
+import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
+import org.junit.Test;
+
+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;
+import static org.junit.Assert.fail;
+
+public class ExternalGroupPrincipalProviderTest extends AbstractPrincipalTest {
+
+ private void syncWithMembership(@Nonnull ExternalUser externalUser, long depth) throws Exception {
+ DefaultSyncConfig sc = new DefaultSyncConfig();
+ sc.user().setMembershipNestingDepth(depth);
+
+ Root systemRoot = getSystemRoot();
+ DynamicSyncContext syncContext = new DynamicSyncContext(sc, idp, getUserManager(systemRoot), getValueFactory(systemRoot));
+ syncContext.setForceUserSync(true);
+ syncContext.setForceGroupSync(true);
+ syncContext.sync(externalUser);
+ syncContext.close();
+ systemRoot.commit();
+
+ root.refresh();
+ }
+
+ private Set<Principal> getDeclaredGroupPrincipals(@Nonnull String userId) throws ExternalIdentityException {
+ Set<Principal> principals = ImmutableSet.copyOf(Iterables.transform(idp.getUser(userId).getDeclaredGroups(), new Function<ExternalIdentityRef, Principal>() {
+ @Nullable
+ @Override
+ public Principal apply(ExternalIdentityRef input) {
+ try {
+ return new PrincipalImpl(idp.getIdentity(input).getPrincipalName());
+ } catch (ExternalIdentityException e) {
+ fail(e.getMessage());
+ return null;
+ }
+ }
+
+ ;
+ }));
+ return principals;
+ }
+
+ @Test
+ public void testGetPrincipalLocalUser() throws Exception {
+ assertNull(principalProvider.getPrincipal(getTestUser().getPrincipal().getName()));
+ }
+
+ @Test
+ public void testGetPrincipalLocalGroup() throws Exception {
+ Group gr = createTestGroup();
+ assertNull(principalProvider.getPrincipal(gr.getPrincipal().getName()));
+ }
+
+ @Test
+ public void testGetPrincipalExternalUser() throws Exception {
+ UserManager userManager = getUserManager(root);
+
+ // synced by principal-sync-ctx
+ User syncedUser = userManager.getAuthorizable(USER_ID, User.class);
+ assertNull(principalProvider.getPrincipal(syncedUser.getPrincipal().getName()));
+
+ // synced by default-sync-ctx
+ syncedUser = userManager.getAuthorizable(TestIdentityProvider.ID_SECOND_USER, User.class);
+ assertNull(principalProvider.getPrincipal(syncedUser.getPrincipal().getName()));
+ }
+
+
+ @Test
+ public void testGetPrincipalExternalGroup() throws Exception {
+ Group gr = getUserManager(root).getAuthorizable("secondGroup", Group.class);
+ assertNotNull(gr);
+
+ assertNull(principalProvider.getPrincipal(gr.getPrincipal().getName()));
+ }
+
+ @Test
+ public void testGetPrincipalDynamicGroupDepth1() throws Exception {
+ for (ExternalIdentityRef ref : idp.getUser(USER_ID).getDeclaredGroups()) {
+
+ String princName = idp.getIdentity(ref).getPrincipalName();
+ Principal principal = principalProvider.getPrincipal(princName);
+
+ assertNotNull(principal);
+ assertTrue(principal instanceof java.security.acl.Group);
+ }
+ }
+
+ @Test
+ public void testGetPrincipalInheritedGroupsDepth1() throws Exception {
+ ImmutableSet<ExternalIdentityRef> declared = ImmutableSet.<ExternalIdentityRef>copyOf(idp.getUser(USER_ID).getDeclaredGroups());
+
+ for (ExternalIdentityRef ref : declared) {
+ for (ExternalIdentityRef inheritedGroupRef : idp.getIdentity(ref).getDeclaredGroups()) {
+ if (declared.contains(inheritedGroupRef)) {
+ continue;
+ }
+ String inheritedPrincName = idp.getIdentity(inheritedGroupRef).getPrincipalName();
+ assertNull(principalProvider.getPrincipal(inheritedPrincName));
+ }
+ }
+ }
+
+ @Test
+ public void testGetPrincipalInheritedGroupsDepthInfinite() throws Exception {
+ ExternalUser externalUser = idp.getUser(USER_ID);
+ syncWithMembership(externalUser, Long.MAX_VALUE);
+
+ for (ExternalIdentityRef ref : externalUser.getDeclaredGroups()) {
+ ExternalIdentity externalGroup = idp.getIdentity(ref);
+ Principal grPrincipal = principalProvider.getPrincipal(externalGroup.getPrincipalName());
+
+ for (ExternalIdentityRef inheritedGroupRef : externalGroup.getDeclaredGroups()) {
+ String inheritedPrincName = idp.getIdentity(inheritedGroupRef).getPrincipalName();
+
+ Principal principal = principalProvider.getPrincipal(inheritedPrincName);
+
+ assertNotNull(principal);
+ assertTrue(principal instanceof java.security.acl.Group);
+
+ java.security.acl.Group inheritedGrPrincipal = (java.security.acl.Group) principal;
+ assertTrue(inheritedGrPrincipal.isMember(new PrincipalImpl(externalUser.getPrincipalName())));
+ assertFalse(inheritedGrPrincipal.isMember(grPrincipal));
+ }
+ }
+ }
+
+ @Test
+ public void testGetPrincipalUnderscoreSign() throws Exception {
+ ExternalUser externalUser = idp.getUser(USER_ID);
+ syncWithMembership(externalUser, 1);
+
+ for (ExternalIdentityRef ref : externalUser.getDeclaredGroups()) {
+ String pName = idp.getIdentity(ref).getPrincipalName();
+
+ for (String n : new String[]{"_", "_" + pName.substring(1), pName.substring(0, pName.length() - 1) + "_"}) {
+ assertNull(principalProvider.getPrincipal(n));
+ }
+ }
+ }
+
+ @Test
+ public void testGetPrincipalPercentSign() throws Exception {
+ ExternalUser externalUser = idp.getUser(USER_ID);
+ syncWithMembership(externalUser, 1);
+
+ for (ExternalIdentityRef ref : externalUser.getDeclaredGroups()) {
+ String pName = idp.getIdentity(ref).getPrincipalName();
+
+ for (String n : new String[] {"%", "%" + pName, pName + "%", pName.charAt(0) + "%"}) {
+ assertNull(principalProvider.getPrincipal(n));
+ }
+ }
+ }
+
+ @Test
+ public void testGetPrincipalGroupsWithQueryWildCard() throws Exception {
+ ExternalUser externalUser = idp.getUser(TestIdentityProvider.ID_WILDCARD_USER);
+ syncWithMembership(externalUser, 1);
+
+ for (ExternalIdentityRef ref : externalUser.getDeclaredGroups()) {
+ String pName = idp.getIdentity(ref).getPrincipalName();
+ Principal p = principalProvider.getPrincipal(pName);
+ assertNotNull(p);
+ assertEquals(pName, p.getName());
+ }
+ }
+
+ @Test
+ public void testGetGroupMembershipLocalPrincipal() throws Exception {
+ Set<? extends Principal> principals = principalProvider.getGroupMembership(getTestUser().getPrincipal());
+ assertTrue(principals.isEmpty());
+ }
+
+ @Test
+ public void testGetGroupMembershipLocalGroupPrincipal() throws Exception {
+ Group gr = createTestGroup();
+ Set<? extends Principal> principals = principalProvider.getGroupMembership(gr.getPrincipal());
+ assertTrue(principals.isEmpty());
+
+ // same if the principal is not marked as 'java.security.acl.Group' and not tree-based-principal
+ principals = principalProvider.getGroupMembership(new PrincipalImpl(gr.getPrincipal().getName()));
+ assertTrue(principals.isEmpty());
+ }
+
+ @Test
+ public void testGetGroupMembershipExternalUser() throws Exception {
+ Authorizable user = getUserManager(root).getAuthorizable(USER_ID);
+ assertNotNull(user);
+
+ Set<Principal> expected = getDeclaredGroupPrincipals(USER_ID);
+
+ Set<? extends Principal> principals = principalProvider.getGroupMembership(user.getPrincipal());
+ assertEquals(expected, principals);
+
+ // same if the principal is not a tree-based-principal
+ principals = principalProvider.getGroupMembership(new PrincipalImpl(user.getPrincipal().getName()));
+ assertEquals(expected, principals);
+ }
+
+ @Test
+ public void testGetGroupMembershipExternalUser2() throws Exception {
+ // synchronized by default sync-context => no 'dynamic' group principals
+ Authorizable user = getUserManager(root).getAuthorizable(TestIdentityProvider.ID_SECOND_USER);
+ assertNotNull(user);
+
+ Set<? extends Principal> principals = principalProvider.getGroupMembership(user.getPrincipal());
+ assertTrue(principals.isEmpty());
+
+ // same if the principal is not a tree-based-principal
+ principals = principalProvider.getGroupMembership(new PrincipalImpl(user.getPrincipal().getName()));
+ assertTrue(principals.isEmpty());
+ }
+
+ @Test
+ public void testGetGroupMembershipExternalUserInfiniteDepth() throws Exception {
+ ExternalUser externalUser = idp.getUser(USER_ID);
+ syncWithMembership(externalUser, Long.MAX_VALUE);
+
+ Set<Principal> expectedGrPrincipals = new HashSet();
+ collectExpectedPrincipals(expectedGrPrincipals, externalUser.getDeclaredGroups(), Long.MAX_VALUE);
+
+ Authorizable user = getUserManager(root).getAuthorizable(USER_ID);
+ Set<? extends Principal> principals = principalProvider.getGroupMembership(user.getPrincipal());
+ assertEquals(expectedGrPrincipals, principals);
+
+ // same if the principal is not a tree-based-principal
+ principals = principalProvider.getGroupMembership(new PrincipalImpl(user.getPrincipal().getName()));
+ assertEquals(expectedGrPrincipals, principals);
+ }
+
+ private void collectExpectedPrincipals(Set<Principal> grPrincipals, @Nonnull Iterable<ExternalIdentityRef> declaredGroups, long depth) throws ExternalIdentityException {
+ if (depth <= 0) {
+ return;
+ }
+ for (ExternalIdentityRef ref : declaredGroups) {
+ ExternalIdentity ei = idp.getIdentity(ref);
+ grPrincipals.add(new PrincipalImpl(ei.getPrincipalName()));
+ collectExpectedPrincipals(grPrincipals, ei.getDeclaredGroups(), depth - 1);
+ }
+ }
+
+ @Test
+ public void testGetGroupMembershipExternalGroup() throws Exception {
+ Authorizable group = getUserManager(root).getAuthorizable("secondGroup");
+ assertNotNull(group);
+
+ Set<? extends Principal> principals = principalProvider.getGroupMembership(group.getPrincipal());
+ assertTrue(principals.isEmpty());
+
+ // same if the principal is not marked as 'java.security.acl.Group' and not tree-based-principal
+ principals = principalProvider.getGroupMembership(new PrincipalImpl(group.getPrincipal().getName()));
+ assertTrue(principals.isEmpty());
+ }
+
+ @Test
+ public void testGetPrincipalsLocalUser() throws Exception {
+ Set<? extends Principal> principals = principalProvider.getPrincipals(getTestUser().getID());
+ assertTrue(principals.isEmpty());
+ }
+
+ @Test
+ public void testGetPrincipalsLocalGroup() throws Exception {
+ Set<? extends Principal> principals = principalProvider.getPrincipals(createTestGroup().getID());
+ assertTrue(principals.isEmpty());
+ }
+
+ @Test
+ public void testGetPrincipalsExternalUser() throws Exception {
+ Set<? extends Principal> principals = principalProvider.getPrincipals(USER_ID);
+ assertEquals(getDeclaredGroupPrincipals(USER_ID), principals);
+ }
+
+ @Test
+ public void testGetPrincipalsExternalUser2() {
+ // synchronized by default sync-context => no 'dynamic' group principals
+ Set<? extends Principal> principals = principalProvider.getPrincipals(TestIdentityProvider.ID_SECOND_USER);
+ assertTrue(principals.isEmpty());
+ }
+
+ @Test
+ public void testGetPrincipalsExternalGroup() throws Exception {
+ Authorizable authorizable = getUserManager(root).getAuthorizable("secondGroup");
+ assertNotNull(authorizable);
+
+ Set<? extends Principal> principals = principalProvider.getPrincipals(authorizable.getID());
+ assertTrue(principals.isEmpty());
+ }
+
+ @Test
+ public void testGetPrincipalsNonExistingUser() throws Exception {
+ assertNull(getUserManager(root).getAuthorizable("nonExistingUser"));
+ Set<? extends Principal> principals = principalProvider.getPrincipals("nonExistingUser");
+ assertTrue(principals.isEmpty());
+ }
+
+ @Test
+ public void testFindPrincipalsByHintTypeNotGroup() {
+ Iterator<? extends Principal> iter = principalProvider.findPrincipals("a", PrincipalManager.SEARCH_TYPE_NOT_GROUP);
+ assertSame(Iterators.emptyIterator(), iter);
+ }
+
+ @Test
+ public void testFindPrincipalsByHintTypeGroup() throws Exception {
+ ExternalUser externalUser = idp.getUser(USER_ID);
+ syncWithMembership(externalUser, Long.MAX_VALUE);
+
+ Set<? extends Principal> expected = ImmutableSet.of(new PrincipalImpl("a"), new PrincipalImpl("aa"), new PrincipalImpl("aaa"));
+ Set<? extends Principal> res = ImmutableSet.copyOf(principalProvider.findPrincipals("a", PrincipalManager.SEARCH_TYPE_GROUP));
+
+ assertEquals(expected, res);
+ }
+
+ @Test
+ public void testFindPrincipalsByHintTypeAll() throws Exception {
+ ExternalUser externalUser = idp.getUser(USER_ID);
+ syncWithMembership(externalUser, Long.MAX_VALUE);
+
+ Set<? extends Principal> expected = ImmutableSet.of(
+ new PrincipalImpl("a"),
+ new PrincipalImpl("aa"),
+ new PrincipalImpl("aaa"));
+ Set<? extends Principal> res = ImmutableSet.copyOf(principalProvider.findPrincipals("a", PrincipalManager.SEARCH_TYPE_ALL));
+
+ assertEquals(expected, res);
+ }
+
+ @Test
+ public void testFindPrincipalsContainingUnderscore() throws Exception {
+ ExternalUser externalUser = idp.getUser(TestIdentityProvider.ID_WILDCARD_USER);
+ syncWithMembership(externalUser, 1);
+
+ Set<? extends Principal> expected = ImmutableSet.of(
+ new PrincipalImpl("_gr_u_"));
+ Set<? extends Principal> res = ImmutableSet.copyOf(principalProvider.findPrincipals("_", PrincipalManager.SEARCH_TYPE_ALL));
+
+ assertEquals(expected, res);
+ }
+
+ @Test
+ public void testFindPrincipalsContainingPercentSign() throws Exception {
+ ExternalUser externalUser = idp.getUser(TestIdentityProvider.ID_WILDCARD_USER);
+ syncWithMembership(externalUser, 1);
+
+ Set<? extends Principal> expected = ImmutableSet.of(
+ new PrincipalImpl("g%r%"));
+ Set<? extends Principal> res = ImmutableSet.copyOf(principalProvider.findPrincipals("%", PrincipalManager.SEARCH_TYPE_ALL));
+
+ assertEquals(expected, res);
+ }
+
+ @Test
+ public void testFindPrincipalsByTypeNotGroup() {
+ Iterator<? extends Principal> iter = principalProvider.findPrincipals(PrincipalManager.SEARCH_TYPE_NOT_GROUP);
+ assertSame(Iterators.emptyIterator(), iter);
+ }
+
+ @Test
+ public void testFindPrincipalsByTypeGroup() throws Exception {
+ Set<? extends Principal> res = ImmutableSet.copyOf(principalProvider.findPrincipals(PrincipalManager.SEARCH_TYPE_GROUP));
+ assertEquals(getDeclaredGroupPrincipals(USER_ID), res);
+ }
+
+ @Test
+ public void testFindPrincipalsByTypeAll() throws Exception {
+ Set<? extends Principal> res = ImmutableSet.copyOf(principalProvider.findPrincipals(PrincipalManager.SEARCH_TYPE_ALL));
+ assertEquals(getDeclaredGroupPrincipals(USER_ID), res);
+ }
+
+ @Test
+ public void testFindPrincipalsFiltersDuplicates() throws Exception {
+ ExternalUser otherUser = new TestUser("anotherUser", ImmutableSet.of(idp.getGroup("a").getExternalId()));
+ syncWithMembership(otherUser, 1);
+
+ Iterator<? extends Principal> res = principalProvider.findPrincipals("a", PrincipalManager.SEARCH_TYPE_ALL);
+ assertTrue(res.hasNext());
+ assertEquals(new PrincipalImpl("a"), res.next());
+ assertFalse(res.hasNext());
+ }
+
+ private static final class TestUser extends TestIdentityProvider.TestIdentity implements ExternalUser {
+
+ private final Iterable<ExternalIdentityRef> declaredGroups;
+
+ private TestUser(@Nonnull String id, @Nonnull Iterable<ExternalIdentityRef> declaredGroups) {
+ super(id);
+ this.declaredGroups = declaredGroups;
+ }
+ @Nonnull
+ @Override
+ public Iterable<ExternalIdentityRef> getDeclaredGroups() {
+ return declaredGroups;
+ }
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalProviderTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalTest.java?rev=1744292&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalTest.java (added)
+++ jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalTest.java Tue May 17 16:18:29 2016
@@ -0,0 +1,121 @@
+/*
+ * 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.principal;
+
+import java.security.Principal;
+import java.util.Enumeration;
+import javax.annotation.Nullable;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalGroup;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalUser;
+import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class ExternalGroupPrincipalTest extends AbstractPrincipalTest {
+
+ @Test
+ public void testIsMember() throws Exception {
+ ExternalUser externalUser = idp.getUser(USER_ID);
+ java.security.acl.Group principal = getGroupPrincipal(externalUser.getDeclaredGroups().iterator().next());
+
+ assertTrue(principal.isMember(new PrincipalImpl(externalUser.getPrincipalName())));
+ assertTrue(principal.isMember(getUserManager(root).getAuthorizable(USER_ID).getPrincipal()));
+ }
+
+ @Test
+ public void testIsMemberExternalGroup() throws Exception {
+ java.security.acl.Group principal = getGroupPrincipal();
+
+ Iterable<String> exGroupPrincNames = Iterables.transform(ImmutableList.copyOf(idp.listGroups()), new Function<ExternalGroup, String>() {
+ @Nullable
+ @Override
+ public String apply(ExternalGroup input) {
+ return input.getPrincipalName();
+ }
+ });
+
+ for (String principalName : exGroupPrincNames) {
+ assertFalse(principal.isMember(new PrincipalImpl(principalName)));
+ }
+ }
+
+ @Test
+ public void testIsMemberLocalUser() throws Exception {
+ java.security.acl.Group principal = getGroupPrincipal();
+
+ assertFalse(principal.isMember(getTestUser().getPrincipal()));
+ assertFalse(principal.isMember(new PrincipalImpl(getTestUser().getPrincipal().getName())));
+ }
+
+ @Test
+ public void testIsMemberLocalGroup() throws Exception {
+ Group gr = createTestGroup();
+ java.security.acl.Group principal = getGroupPrincipal();
+
+ assertFalse(principal.isMember(gr.getPrincipal()));
+ assertFalse(principal.isMember(new PrincipalImpl(gr.getPrincipal().getName())));
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testAddMember() throws Exception {
+ java.security.acl.Group principal = getGroupPrincipal();
+ principal.addMember(getTestUser().getPrincipal());
+ }
+
+ @Test
+ public void testAddMemberExistingMember() throws Exception {
+ java.security.acl.Group principal = getGroupPrincipal();
+ assertFalse(principal.addMember(getUserManager(root).getAuthorizable(USER_ID).getPrincipal()));
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testRemoveMember() throws Exception {
+ java.security.acl.Group principal = getGroupPrincipal();
+ principal.removeMember(getUserManager(root).getAuthorizable(USER_ID).getPrincipal());
+ }
+
+ @Test
+ public void testRemoveMemberNotMember() throws Exception {
+ java.security.acl.Group principal = getGroupPrincipal();
+ assertFalse(principal.removeMember(getTestUser().getPrincipal()));
+ }
+
+ @Test
+ public void testMembers() throws Exception {
+ java.security.acl.Group principal = getGroupPrincipal();
+
+ Principal[] expectedMembers = new Principal[] {
+ getUserManager(root).getAuthorizable(USER_ID).getPrincipal(),
+ new PrincipalImpl(idp.getUser(USER_ID).getPrincipalName())
+ };
+
+ for (Principal expected : expectedMembers) {
+ Enumeration<? extends Principal> members = principal.members();
+ assertTrue(members.hasMoreElements());
+ assertEquals(expected, members.nextElement());
+ assertFalse(members.hasMoreElements());
+ }
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalIdentityImporterTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalIdentityImporterTest.java?rev=1744292&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalIdentityImporterTest.java (added)
+++ jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalIdentityImporterTest.java Tue May 17 16:18:29 2016
@@ -0,0 +1,147 @@
+/*
+ * 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.principal;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.security.PrivilegedExceptionAction;
+import javax.annotation.Nonnull;
+import javax.jcr.ImportUUIDBehavior;
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import javax.security.auth.Subject;
+
+import org.apache.jackrabbit.api.JackrabbitRepository;
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.oak.jcr.Jcr;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
+import org.apache.jackrabbit.oak.spi.security.authentication.SystemSubject;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.TestSecurityProvider;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalIdentityConstants;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test XML import of external users/groups with protection of external identity
+ * properties turned on.
+ */
+public class ExternalIdentityImporterTest {
+
+ public static final String XML_EXTERNAL_USER_WITH_PRINCIPAL_NAMES = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<sv:node sv:name=\"t\" xmlns:mix=\"http://www.jcp.org/jcr/mix/1.0\" xmlns:nt=\"http://www.jcp.org/jcr/nt/1.0\" xmlns:fn_old=\"http://www.w3.org/2004/10/xpath-functions\" xmlns:fn=\"http://www.w3.org/2005/xpath-functions\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:sv=\"http://www.jcp.org/jcr/sv/1.0\" xmlns:rep=\"internal\" xmlns:jcr=\"http://www.jcp.org/jcr/1.0\">" +
+ " <sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\"><sv:value>rep:User</sv:value></sv:property>" +
+ " <sv:property sv:name=\"jcr:uuid\" sv:type=\"String\"><sv:value>e358efa4-89f5-3062-b10d-d7316b65649e</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:authorizableId\" sv:type=\"String\"><sv:value>t</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:principalName\" sv:type=\"String\"><sv:value>tPrinc</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:externalId\" sv:type=\"String\"><sv:value>idp;ext-t</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:externalPrincipalNames\" sv:type=\"String\"><sv:value>grPrinc</sv:value><sv:value>gr2Princ</sv:value></sv:property>" +
+ " <sv:property sv:name=\"rep:lastSynced\" sv:type=\"Date\"><sv:value>2016-05-03T10:03:08.061+02:00</sv:value></sv:property>" +
+ "</sv:node>";
+
+ private Repository repo;
+ private SecurityProvider securityProvider;
+ private JackrabbitSession session;
+
+ @Before
+ public void before() throws Exception {
+ securityProvider = new TestSecurityProvider(getConfigurationParameters());
+ Jcr jcr = new Jcr();
+ jcr.with(securityProvider);
+ repo = jcr.createRepository();
+ }
+
+ @After
+ public void after() throws Exception {
+ try {
+ if (session != null) {
+ session.logout();
+ }
+ } finally {
+ if (repo instanceof JackrabbitRepository) {
+ ((JackrabbitRepository) repo).shutdown();
+ }
+ }
+ }
+
+ @Nonnull
+ ConfigurationParameters getConfigurationParameters() {
+ return ConfigurationParameters.EMPTY;
+ }
+
+ JackrabbitSession createSession(boolean isSystem) throws Exception {
+ if (isSystem) {
+ session = (JackrabbitSession) Subject.doAs(SystemSubject.INSTANCE, new PrivilegedExceptionAction<Session>() {
+ @Override
+ public Session run() throws RepositoryException {
+ return repo.login(null, null);
+ }
+ });
+ } else {
+ session = (JackrabbitSession) repo.login(new SimpleCredentials(UserConstants.DEFAULT_ADMIN_ID, UserConstants.DEFAULT_ADMIN_ID.toCharArray()));
+ }
+ return session;
+ }
+
+ Node doImport(Session importSession, String parentPath, String xml) throws Exception {
+ InputStream in;
+ if (xml.charAt(0) == '<') {
+ in = new ByteArrayInputStream(xml.getBytes());
+ } else {
+ in = getClass().getResourceAsStream(xml);
+ }
+ try {
+ importSession.importXML(parentPath, in, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW);
+ return importSession.getNode(parentPath);
+ } finally {
+ in.close();
+ }
+ }
+
+ static void assertHasProperties(@Nonnull Node node, @Nonnull String... propertyNames) throws Exception {
+ for (String pN : propertyNames) {
+ assertTrue(node.hasProperty(pN));
+ }
+ }
+
+ static void assertNotHasProperties(@Nonnull Node node, @Nonnull String... propertyNames) throws Exception {
+ for (String pN : propertyNames) {
+ assertFalse(node.hasProperty(pN));
+ }
+ }
+
+ @Test
+ public void importExternalUserWithPrincipalNames() throws Exception {
+ Node parent = doImport(createSession(false), UserConstants.DEFAULT_USER_PATH, XML_EXTERNAL_USER_WITH_PRINCIPAL_NAMES);
+ assertHasProperties(parent.getNode("t"), ExternalIdentityConstants.REP_EXTERNAL_ID);
+ assertNotHasProperties(parent.getNode("t"), ExternalIdentityConstants.REP_LAST_SYNCED, ExternalIdentityConstants.REP_EXTERNAL_PRINCIPAL_NAMES);
+ }
+
+ @Test
+ public void importExternalUserWithPrincipalNamesAsSystem() throws Exception {
+ Node parent = doImport(createSession(true), UserConstants.DEFAULT_USER_PATH, XML_EXTERNAL_USER_WITH_PRINCIPAL_NAMES);
+ assertHasProperties(parent.getNode("t"), ExternalIdentityConstants.REP_EXTERNAL_ID, ExternalIdentityConstants.REP_LAST_SYNCED, ExternalIdentityConstants.REP_EXTERNAL_PRINCIPAL_NAMES);
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalIdentityImporterTest.java
------------------------------------------------------------------------------
svn:eol-style = native