Author: angela Date: Fri Nov 2 09:54:25 2012 New Revision: 1404905 URL: http://svn.apache.org/viewvc?rev=1404905&view=rev Log: OAK-91 - Implement Authentication Support (WIP)
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestLoginModule.java Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/ConfigurationParameters.java jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/DefaultSyncHandler.java jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModule.java jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalUser.java jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncMode.java jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/AbstractSecurityTest.java jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/ConfigurationParametersTest.java Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/ConfigurationParameters.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/ConfigurationParameters.java?rev=1404905&r1=1404904&r2=1404905&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/ConfigurationParameters.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/ConfigurationParameters.java Fri Nov 2 09:54:25 2012 @@ -55,6 +55,10 @@ public class ConfigurationParameters { //--------------------------------------------------------< private >--- @SuppressWarnings("unchecked") private static <T> T convert(Object configProperty, T defaultValue) { + if (configProperty == null) { + return defaultValue; + } + T value; String str = configProperty.toString(); Class targetClass = (defaultValue == null) ? configProperty.getClass() : defaultValue.getClass(); Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/DefaultSyncHandler.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/DefaultSyncHandler.java?rev=1404905&r1=1404904&r2=1404905&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/DefaultSyncHandler.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/DefaultSyncHandler.java Fri Nov 2 09:54:25 2012 @@ -21,9 +21,11 @@ import java.util.Collection; import java.util.List; import java.util.Map; import javax.annotation.CheckForNull; +import javax.jcr.PropertyType; import javax.jcr.RepositoryException; import javax.jcr.Value; import javax.jcr.ValueFactory; +import javax.jcr.ValueFormatException; import org.apache.jackrabbit.api.security.user.Authorizable; import org.apache.jackrabbit.api.security.user.Group; @@ -109,7 +111,7 @@ public class DefaultSyncHandler implemen @CheckForNull private User createUser(ExternalUser externalUser) throws RepositoryException, SyncException { if (mode.contains(SyncMode.MODE_CREATE_USER)) { - User user = userManager.createUser(externalUser.getId(), null, externalUser.getPrincipal(), externalUser.getPath()); + User user = userManager.createUser(externalUser.getId(), externalUser.getPassword(), externalUser.getPrincipal(), externalUser.getPath()); syncAuthorizable(externalUser, user); return user; } else { @@ -157,24 +159,46 @@ public class DefaultSyncHandler implemen Object prop = properties.get(key); if (prop instanceof Collection) { Value[] values = createValues((Collection) prop); - authorizable.setProperty(key, values); + if (values != null) { + authorizable.setProperty(key, values); + } } else { Value value = createValue(prop); - authorizable.setProperty(key, value); + if (value != null) { + authorizable.setProperty(key, value); + } } } } - private Value createValue(Object propValue) { - // TODO - return null; + @CheckForNull + private Value createValue(Object propValue) throws ValueFormatException { + int type = getType(propValue); + if (type == PropertyType.UNDEFINED) { + return null; + } else { + return valueFactory.createValue(propValue.toString(), type); + } } - private Value[] createValues(Collection<?> propValues) { + @CheckForNull + private Value[] createValues(Collection<?> propValues) throws ValueFormatException { List<Value> values = new ArrayList<Value>(); for (Object obj : propValues) { - values.add(createValue(obj)); + Value v = createValue(obj); + if (v != null) { + values.add(v); + } } return values.toArray(new Value[values.size()]); } + + private static int getType(Object propValue) { + // TODO: add proper type detection + if (propValue == null) { + return PropertyType.UNDEFINED; + } else { + return PropertyType.STRING; + } + } } \ No newline at end of file Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModule.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModule.java?rev=1404905&r1=1404904&r2=1404905&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModule.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModule.java Fri Nov 2 09:54:25 2012 @@ -24,7 +24,6 @@ import javax.security.auth.login.LoginEx import org.apache.jackrabbit.oak.api.CommitFailedException; import org.apache.jackrabbit.oak.api.Root; import org.apache.jackrabbit.oak.spi.security.authentication.AbstractLoginModule; -import org.apache.jackrabbit.util.Text; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -66,19 +65,22 @@ public abstract class ExternalLoginModul * @throws SyncException */ protected SyncHandler getSyncHandler() throws SyncException { - String shClass = options.getConfigValue(PARAM_SYNC_HANDLER, DEFAULT_SYNC_HANDLER); - Object syncHandler; - try { - // FIXME this will create problems within OSGi environment - syncHandler = Class.forName(shClass).newInstance(); - } catch (Exception e) { - throw new SyncException("Error while getting SyncHandler:", e); - } - - if (syncHandler instanceof SyncHandler) { + Object syncHandler = options.getConfigValue(PARAM_SYNC_HANDLER, null); + if (syncHandler == null) { + return new DefaultSyncHandler(); + } else if (syncHandler instanceof SyncHandler) { return (SyncHandler) syncHandler; } else { - throw new SyncException("Invalid SyncHandler class configured: " + syncHandler.getClass().getName()); + try { + Object sh = Class.forName(syncHandler.toString()).newInstance(); + if (sh instanceof SyncHandler) { + return (SyncHandler) sh; + } else { + throw new SyncException("Invalid SyncHandler configuration: " + sh); + } + } catch (Exception e) { + throw new SyncException("Error while getting SyncHandler:", e); + } } } @@ -115,12 +117,12 @@ public abstract class ExternalLoginModul try { SyncHandler handler = getSyncHandler(); Root root = getRoot(); - String smValue = options.getConfigValue(PARAM_SYNC_MODE, null); + Object smValue = options.getConfigValue(PARAM_SYNC_MODE, null); SyncMode syncMode; if (smValue == null) { syncMode = DEFAULT_SYNC_MODE; } else { - syncMode = SyncMode.fromStrings(Text.explode(smValue, ',', false)); + syncMode = SyncMode.fromObject(smValue); } if (handler.initialize(getUserManager(), root, syncMode, options)) { handler.sync(getExternalUser()); Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalUser.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalUser.java?rev=1404905&r1=1404904&r2=1404905&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalUser.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalUser.java Fri Nov 2 09:54:25 2012 @@ -27,6 +27,8 @@ public interface ExternalUser { String getId(); + String getPassword(); + Principal getPrincipal(); String getPath(); Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncMode.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncMode.java?rev=1404905&r1=1404904&r2=1404905&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncMode.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncMode.java Fri Nov 2 09:54:25 2012 @@ -16,6 +16,8 @@ */ package org.apache.jackrabbit.oak.spi.security.authentication.external; +import org.apache.jackrabbit.util.Text; + /** * SyncMode... TODO: define sync-modes */ @@ -26,8 +28,9 @@ public class SyncMode { public static final int MODE_CREATE_GROUPS = 2; public static final int MODE_UPDATE = 4; - public static final String CREATE_USER_NAME = "createUser"; - public static final String CREATE_GROUP_NAME = "createGroup"; + public static final String NO_SYNC = ""; + public static final String CREATE_USER = "createUser"; + public static final String CREATE_GROUP = "createGroup"; public static final String UPDATE = "update"; public static final SyncMode DEFAULT_SYNC = new SyncMode(MODE_CREATE_USER|MODE_CREATE_GROUPS|MODE_UPDATE); @@ -42,15 +45,27 @@ public class SyncMode { return (this.mode & mode) == mode; } + public static SyncMode fromObject(Object smValue) { + if (smValue instanceof SyncMode) { + return (SyncMode) smValue; + } else if (smValue instanceof String[]) { + return fromStrings((String[]) smValue); + } else { + return fromStrings(Text.explode(smValue.toString(), ',', false)); + } + } + public static SyncMode fromString(String name) { int mode; - if (CREATE_USER_NAME.equals(name)) { + if (CREATE_USER.equals(name)) { mode = MODE_CREATE_USER; - } else if (CREATE_GROUP_NAME.equals(name)) { + } else if (CREATE_GROUP.equals(name)) { mode = MODE_CREATE_GROUPS; } else if (UPDATE.equals(name)) { mode = MODE_UPDATE; - } else { + } else if (name.isEmpty()) { + mode = MODE_NO_SYNC; + }else { throw new IllegalArgumentException("invalid sync mode name " + name); } return fromInt(mode); Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/AbstractSecurityTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/AbstractSecurityTest.java?rev=1404905&r1=1404904&r2=1404905&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/AbstractSecurityTest.java (original) +++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/AbstractSecurityTest.java Fri Nov 2 09:54:25 2012 @@ -66,6 +66,7 @@ public abstract class AbstractSecurityTe } return securityProvider; } + protected Configuration getConfiguration() { return new OakConfiguration(); } Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/ConfigurationParametersTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/ConfigurationParametersTest.java?rev=1404905&r1=1404904&r2=1404905&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/ConfigurationParametersTest.java (original) +++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/ConfigurationParametersTest.java Fri Nov 2 09:54:25 2012 @@ -103,6 +103,16 @@ public class ConfigurationParametersTest assertEquals("1000", options.getConfigValue("Int3", "1000")); } + @Test + public void testNullValue() { + ConfigurationParameters options = new ConfigurationParameters(Collections.singletonMap("test", null)); + + assertNull(options.getConfigValue("test", null)); + assertEquals("value", options.getConfigValue("test", "value")); + TestObject testObject = new TestObject("t"); + assertEquals(testObject, options.getConfigValue("test", testObject)); + } + private class TestObject { Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java?rev=1404905&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java (added) +++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java Fri Nov 2 09:54:25 2012 @@ -0,0 +1,306 @@ +/* + * 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 java.util.HashMap; +import java.util.HashSet; +import java.util.Set; +import javax.jcr.SimpleCredentials; +import javax.security.auth.login.AppConfigurationEntry; +import javax.security.auth.login.Configuration; +import javax.security.auth.login.LoginException; + +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.api.Root; +import org.apache.jackrabbit.oak.namepath.NamePathMapper; +import org.apache.jackrabbit.oak.security.AbstractSecurityTest; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +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 AbstractSecurityTest { + + private final HashMap<String, Object> options = new HashMap<String, Object>(); + + private String userId; + private Set<String> ids = new HashSet<String>(); + + private UserManager userManager; + + private Root root; + + @Before + public void before() throws Exception { + super.before(); + + userId = TestLoginModule.externalUser.getId(); + ids.add(userId); + for (ExternalGroup group : TestLoginModule.externalGroups) { + ids.add(group.getId()); + } + + root = admin.getLatestRoot(); + userManager = securityProvider.getUserConfiguration().getUserManager(root, NamePathMapper.DEFAULT); + } + + @After + public void after() throws Exception { + try { + for (String id : ids) { + Authorizable a = userManager.getAuthorizable(id); + if (a != null) { + a.remove(); + } + } + root.commit(); + } finally { + root.refresh(); + super.after(); + } + } + + + + @Test + public void testLoginFailed() throws Exception { + try { + ContentSession cs = login(new SimpleCredentials("unknown", new char[0])); + cs.close(); + fail("login failure expected"); + } catch (LoginException e) { + // success + } finally { + assertNull(userManager.getAuthorizable(userId)); + } + } + + @Test + public void testSyncCreateUser() throws Exception { + options.put(ExternalLoginModule.PARAM_SYNC_MODE, SyncMode.CREATE_USER); + + ContentSession cs = null; + try { + cs = login(new SimpleCredentials(userId, new char[0])); + + root.refresh(); + for (String id : ids) { + if (id.equals(userId)) { + Authorizable a = userManager.getAuthorizable(id); + assertNotNull(a); + for (String prop : TestLoginModule.externalUser.getProperties().keySet()) { + assertTrue(a.hasProperty(prop)); + } + } else { + assertNull(userManager.getAuthorizable(id)); + } + } + } finally { + if (cs != null) { + cs.close(); + } + options.clear(); + } + } + + @Test + public void testSyncCreateGroup() throws Exception { + options.put(ExternalLoginModule.PARAM_SYNC_MODE, SyncMode.CREATE_GROUP); + + ContentSession cs = null; + try { + cs = login(new SimpleCredentials(userId, new char[0])); + + root.refresh(); + for (String id : ids) { + assertNull(userManager.getAuthorizable(id)); + } + } finally { + if (cs != null) { + cs.close(); + } + options.clear(); + } + } + + @Test + public void testSyncCreateUserAndGroups() throws Exception { + options.put(ExternalLoginModule.PARAM_SYNC_MODE, new String[] {SyncMode.CREATE_USER,SyncMode.CREATE_GROUP}); + + ContentSession cs = null; + try { + cs = login(new SimpleCredentials(userId, new char[0])); + + root.refresh(); + for (String id : ids) { + if (id.equals(userId)) { + Authorizable a = userManager.getAuthorizable(id); + assertNotNull(a); + for (String prop : TestLoginModule.externalUser.getProperties().keySet()) { + assertTrue(a.hasProperty(prop)); + } + } else { + assertNotNull(userManager.getAuthorizable(id)); + } + } + } finally { + if (cs != null) { + cs.close(); + } + options.clear(); + } + } + + @Test + public void testSyncUpdate() throws Exception { + options.put(ExternalLoginModule.PARAM_SYNC_MODE, SyncMode.UPDATE); + + // create user upfront in order to test update mode + ExternalUser externalUser = TestLoginModule.externalUser; + Authorizable user = userManager.createUser(externalUser.getId(), externalUser.getPassword()); + root.commit(); + + ContentSession cs = null; + try { + cs = login(new SimpleCredentials(userId, new char[0])); + + root.refresh(); + for (String id : ids) { + if (id.equals(userId)) { + Authorizable a = userManager.getAuthorizable(id); + assertNotNull(a); + for (String prop : TestLoginModule.externalUser.getProperties().keySet()) { + assertTrue(a.hasProperty(prop)); + } + } else { + assertNull(userManager.getAuthorizable(id)); + } + } + } finally { + if (cs != null) { + cs.close(); + } + options.clear(); + } + } + + @Test + public void testSyncUpdateAndGroups() throws Exception { + options.put(ExternalLoginModule.PARAM_SYNC_MODE, new String[] {SyncMode.UPDATE, SyncMode.CREATE_GROUP}); + + // create user upfront in order to test update mode + ExternalUser externalUser = TestLoginModule.externalUser; + Authorizable user = userManager.createUser(externalUser.getId(), externalUser.getPassword()); + root.commit(); + + ContentSession cs = null; + try { + cs = login(new SimpleCredentials(userId, new char[0])); + + root.refresh(); + for (String id : ids) { + if (id.equals(userId)) { + Authorizable a = userManager.getAuthorizable(id); + assertNotNull(a); + for (String prop : TestLoginModule.externalUser.getProperties().keySet()) { + assertTrue(a.hasProperty(prop)); + } + } else { + assertNotNull(userManager.getAuthorizable(id)); + } + } + } finally { + if (cs != null) { + cs.close(); + } + options.clear(); + } + } + + @Test + public void testDefaultSync() throws Exception { + options.put(ExternalLoginModule.PARAM_SYNC_MODE, null); + + ContentSession cs = null; + try { + cs = login(new SimpleCredentials(userId, new char[0])); + + root.refresh(); + for (String id : ids) { + if (id.equals(userId)) { + Authorizable a = userManager.getAuthorizable(id); + assertNotNull(a); + for (String prop : TestLoginModule.externalUser.getProperties().keySet()) { + assertTrue(a.hasProperty(prop)); + } + } else { + assertNotNull(userManager.getAuthorizable(id)); + } + } + } finally { + if (cs != null) { + cs.close(); + } + options.clear(); + } + } + + @Test + public void testNoSync() throws Exception { + options.put(ExternalLoginModule.PARAM_SYNC_MODE, ""); + + ContentSession cs = null; + try { + cs = login(new SimpleCredentials(userId, new char[0])); + + root.refresh(); + for (String id : ids) { + assertNull(userManager.getAuthorizable(id)); + } + } finally { + if (cs != null) { + cs.close(); + } + options.clear(); + } + } + + protected Configuration getConfiguration() { + return new Configuration() { + @Override + public AppConfigurationEntry[] getAppConfigurationEntry(String s) { + AppConfigurationEntry entry = new AppConfigurationEntry( + TestLoginModule.class.getName(), + AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, + options); + return new AppConfigurationEntry[] {entry}; + } + }; + } + + + +} \ No newline at end of file Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestLoginModule.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestLoginModule.java?rev=1404905&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestLoginModule.java (added) +++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestLoginModule.java Fri Nov 2 09:54:25 2012 @@ -0,0 +1,145 @@ +/* + * 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 java.security.Principal; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.jcr.Credentials; +import javax.jcr.SimpleCredentials; +import javax.security.auth.login.LoginException; + +/** + * ExternalLoginModuleImpl... TODO + */ +public class TestLoginModule extends ExternalLoginModule { + + static Set<ExternalGroup> externalGroups = new HashSet<ExternalGroup>(); + static { + externalGroups.add(new TestGroup("a", new String[] {"aa", "aaa"})); + externalGroups.add(new TestGroup("b", new String[] {"a"})); + externalGroups.add(new TestGroup("c", new String[0])); + } + + static Map<String,Object> props = new HashMap<String, Object>(); + static { + props.put("name", "Test User"); + props.put("profile/name", "Public Name"); + props.put("profile/age", 72); + props.put("./email", "t...@testuser.com"); + } + static ExternalUser externalUser = new TestUser("testUser", externalGroups, props); + + boolean success; + + @Override + protected boolean loginSucceeded() { + return success; + } + + @Override + protected ExternalUser getExternalUser() { + return externalUser; + } + + @Override + public boolean login() throws LoginException { + Credentials creds = getCredentials(); + if (creds instanceof SimpleCredentials) { + if (externalUser.getId().equals(((SimpleCredentials) creds).getUserID())) { + success = true; + return success; + } else { + throw new LoginException("Invalid user"); + } + } else { + return false; + } + } + + //-------------------------------------------------------------------------- + + private static class TestUser implements ExternalUser { + + private final String userId; + private final Set<ExternalGroup> groups; + private final Map props; + + private TestUser(String userId, Set<ExternalGroup> groups, Map<String, Object> props) { + this.userId = userId; + this.groups = groups; + this.props = props; + } + + @Override + public String getId() { + return userId; + } + + @Override + public String getPassword() { + return null; + } + + @Override + public Principal getPrincipal() { + return new Principal() { + @Override + public String getName() { + return userId; + } + }; + } + + @Override + public String getPath() { + return null; + } + + @Override + public Set<ExternalGroup> getGroups() { + return groups; + } + + @Override + public Map<String, ?> getProperties() { + return props; + } + } + + private static class TestGroup extends TestUser implements ExternalGroup { + + private final String[] groupNames; + + private TestGroup(String id, String[] groupNames) { + super(id, Collections.<ExternalGroup>emptySet(), Collections.<String, Object>emptyMap()); + this.groupNames = groupNames; + } + + @Override + public Set<ExternalGroup> getGroups() { + Set<ExternalGroup> groups = new HashSet<ExternalGroup>(); + for (String gn : groupNames) { + groups.add(new TestGroup(gn, new String[0])); + } + return groups; + } + } +} \ No newline at end of file