diff --git a/projects/cadcAccessControl-Server/build.xml b/projects/cadcAccessControl-Server/build.xml index 13d624b3a918da1962e4f02a8224d1e3bfc798ff..de905078c28b11f0999473109426e05221718c2c 100644 --- a/projects/cadcAccessControl-Server/build.xml +++ b/projects/cadcAccessControl-Server/build.xml @@ -136,4 +136,19 @@ <echo>******************</echo> </target> + <target name="test" depends="compile,compile-test"> + <echo message="Running test suite..." /> + <junit printsummary="yes" haltonfailure="yes" fork="yes"> + <classpath> + <pathelement path="${build}/class"/> + <pathelement path="${build}/test/class"/> + <pathelement path="${jars}:${testingJars}"/> + </classpath> + <sysproperty key="ca.nrc.cadc.util.PropertiesReader.dir" value="test"/> + <test name="ca.nrc.cadc.ac.server.ldap.LdapUserDAOTest" /> + <!--<test name="ca.nrc.cadc.ac.server.ldap.LdapGroupDAOTest" />--> + <formatter type="plain" usefile="false" /> + </junit> + </target> + </project> diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapDAO.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapDAO.java index 1b85d39d0a180638f3d53bb03b21449960f35d7f..528a44dedad746a1e02cda2e564016361fcf4aa2 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapDAO.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapDAO.java @@ -68,7 +68,6 @@ */ package ca.nrc.cadc.ac.server.ldap; -import ca.nrc.cadc.ac.UserAlreadyExistsException; import ca.nrc.cadc.auth.HttpPrincipal; import ca.nrc.cadc.auth.NumericPrincipal; import ca.nrc.cadc.auth.OpenIdPrincipal; @@ -79,18 +78,17 @@ import com.unboundid.ldap.sdk.LDAPException; import com.unboundid.ldap.sdk.ResultCode; import com.unboundid.ldap.sdk.SearchResult; import com.unboundid.ldap.sdk.SearchScope; +import org.apache.log4j.Logger; -import java.nio.file.FileAlreadyExistsException; +import javax.net.SocketFactory; +import javax.net.ssl.SSLSocketFactory; +import javax.security.auth.Subject; +import javax.security.auth.x500.X500Principal; import java.security.AccessControlException; import java.security.AccessController; import java.security.GeneralSecurityException; import java.security.Principal; import java.util.Set; -import javax.net.SocketFactory; -import javax.net.ssl.SSLSocketFactory; -import javax.security.auth.Subject; -import javax.security.auth.x500.X500Principal; -import org.apache.log4j.Logger; public abstract class LdapDAO @@ -236,6 +234,7 @@ public abstract class LdapDAO throws TransientException { logger.debug("Ldap result: " + code); + System.out.println("Ldap result: " + code); if (code == ResultCode.INSUFFICIENT_ACCESS_RIGHTS) { diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAO.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAO.java index 23ad3b9a6cbc0728423df19a7028ffb58b24baa3..726b5f94cfda210c83e26d7f46327d29268f1baa 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAO.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAO.java @@ -68,18 +68,6 @@ */ package ca.nrc.cadc.ac.server.ldap; -import java.security.AccessControlException; -import java.security.Principal; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import javax.security.auth.x500.X500Principal; - -import org.apache.log4j.Logger; - import ca.nrc.cadc.ac.ActivatedGroup; import ca.nrc.cadc.ac.Group; import ca.nrc.cadc.ac.GroupAlreadyExistsException; @@ -89,7 +77,6 @@ import ca.nrc.cadc.ac.User; import ca.nrc.cadc.ac.UserNotFoundException; import ca.nrc.cadc.net.TransientException; import ca.nrc.cadc.util.StringUtil; - import com.unboundid.ldap.sdk.AddRequest; import com.unboundid.ldap.sdk.Attribute; import com.unboundid.ldap.sdk.DN; @@ -106,6 +93,16 @@ import com.unboundid.ldap.sdk.SearchResult; import com.unboundid.ldap.sdk.SearchResultEntry; import com.unboundid.ldap.sdk.SearchScope; import com.unboundid.ldap.sdk.controls.ProxiedAuthorizationV2RequestControl; +import org.apache.log4j.Logger; + +import javax.security.auth.x500.X500Principal; +import java.security.AccessControlException; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; public class LdapGroupDAO<T extends Principal> extends LdapDAO { diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java index 835fa9a9924abb5cc2d919979761336bed1d8da6..c7d4d056e7ec946f85e9745f67c03d2e13843991 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java @@ -68,23 +68,41 @@ */ package ca.nrc.cadc.ac.server.ldap; -import ca.nrc.cadc.ac.*; +import ca.nrc.cadc.ac.PersonalDetails; +import ca.nrc.cadc.ac.PosixDetails; +import ca.nrc.cadc.ac.User; +import ca.nrc.cadc.ac.UserAlreadyExistsException; +import ca.nrc.cadc.ac.UserDetails; +import ca.nrc.cadc.ac.UserNotFoundException; +import ca.nrc.cadc.ac.UserRequest; import ca.nrc.cadc.auth.AuthenticationUtil; import ca.nrc.cadc.auth.HttpPrincipal; import ca.nrc.cadc.net.TransientException; import com.unboundid.ldap.sdk.AddRequest; import com.unboundid.ldap.sdk.Attribute; +import com.unboundid.ldap.sdk.BindRequest; +import com.unboundid.ldap.sdk.BindResult; +import com.unboundid.ldap.sdk.Control; import com.unboundid.ldap.sdk.DN; import com.unboundid.ldap.sdk.Filter; import com.unboundid.ldap.sdk.LDAPException; import com.unboundid.ldap.sdk.LDAPResult; import com.unboundid.ldap.sdk.LDAPSearchException; +import com.unboundid.ldap.sdk.Modification; +import com.unboundid.ldap.sdk.ModificationType; +import com.unboundid.ldap.sdk.ModifyRequest; import com.unboundid.ldap.sdk.ResultCode; import com.unboundid.ldap.sdk.SearchRequest; import com.unboundid.ldap.sdk.SearchResult; import com.unboundid.ldap.sdk.SearchResultEntry; import com.unboundid.ldap.sdk.SearchScope; +import com.unboundid.ldap.sdk.SimpleBindRequest; import com.unboundid.ldap.sdk.controls.ProxiedAuthorizationV2RequestControl; +import com.unboundid.ldap.sdk.extensions.PasswordModifyExtendedRequest; +import com.unboundid.ldap.sdk.extensions.PasswordModifyExtendedResult; +import org.apache.log4j.Logger; + +import javax.security.auth.x500.X500Principal; import java.security.AccessControlException; import java.security.Principal; import java.util.ArrayList; @@ -93,8 +111,6 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; -import javax.security.auth.x500.X500Principal; -import org.apache.log4j.Logger; public class LdapUserDAO<T extends Principal> extends LdapDAO @@ -163,6 +179,40 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO memberAttribs = tmp; } + /** + * Verifies the username and password for an existing User. + * + * @param username username to verify. + * @param password password to verify. + * @return User + * @throws TransientException + * @throws UserNotFoundException + */ + public User<T> loginUser(final String username, final String password) + throws TransientException, UserNotFoundException + { + try + { + BindRequest bindRequest = new SimpleBindRequest(getUserDN(username), password); + BindResult bindResult = getConnection().bind(bindRequest); + + if (bindResult != null && bindResult.getResultCode() == ResultCode.SUCCESS) + { + return getUser((T) new HttpPrincipal(username)); + } + else + { + throw new AccessControlException("Invalid username or password"); + } + } + catch (LDAPException e) + { + logger.debug("addUser Exception: " + e, e); + + throw new RuntimeException("Unexpected LDAP exception", e); + } + } + /** * @return * @throws TransientException @@ -208,10 +258,8 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO throw new IllegalStateException("Unexpected exception: " + e1.getMatchedDN(), e1); } - } - /** * Add the specified user.. * @@ -298,8 +346,6 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO } catch (LDAPException e) { - System.out.println("LDAPe: " + e); - System.out.println("LDAPrc: " + e.getResultCode()); logger.debug("addUser Exception: " + e, e); LdapUserDAO.checkUserLDAPResult(e.getResultCode()); throw new RuntimeException("Unexpected LDAP exception", e); @@ -376,9 +422,8 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO throw new UserNotFoundException(msg); } User<T> user = new User<T>(userID); - user.getIdentities().add(new HttpPrincipal(searchResult - .getAttributeValue(userLdapAttrib - .get(HttpPrincipal.class)))); + user.getIdentities().add(new HttpPrincipal(searchResult.getAttributeValue( + userLdapAttrib.get(HttpPrincipal.class)))); String fname = searchResult.getAttributeValue(LDAP_FIRST_NAME); String lname = searchResult.getAttributeValue(LDAP_LAST_NAME); @@ -480,11 +525,99 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO * @throws TransientException If an temporary, unexpected problem occurred. * @throws AccessControlException If the operation is not permitted. */ - public User<T> modifyUser(User<T> user) - throws UserNotFoundException, TransientException, - AccessControlException + public User<T> modifyUser(final User<T> user) + throws UserNotFoundException, TransientException, AccessControlException + { + User existingUser = getUser(user.getUserID()); + + List<Modification> mods = new ArrayList<Modification>(); + for (UserDetails details : user.details) + { + if (details.getClass() == PersonalDetails.class) + { + PersonalDetails pd = (PersonalDetails) details; + mods.add(new Modification(ModificationType.REPLACE, LDAP_FIRST_NAME, pd.getFirstName())); + mods.add(new Modification(ModificationType.REPLACE, LDAP_LAST_NAME, pd.getLastName())); + mods.add(new Modification(ModificationType.REPLACE, LDAP_ADDRESS, pd.address)); + mods.add(new Modification(ModificationType.REPLACE, LDAP_CITY, pd.city)); + mods.add(new Modification(ModificationType.REPLACE, LDAP_COUNTRY, pd.country)); + mods.add(new Modification(ModificationType.REPLACE, LDAP_EMAIL, pd.email)); + mods.add(new Modification(ModificationType.REPLACE, LDAP_INSTITUTE, pd.institute)); + } + else if (details.getClass() == PosixDetails.class) + { + PosixDetails pd = (PosixDetails) details; + mods.add(new Modification(ModificationType.REPLACE, LDAP_OBJECT_CLASS, LDAP_POSIX_ACCOUNT)); + mods.add(new Modification(ModificationType.REPLACE, LDAP_UID, Long.toString(pd.getUid()))); + mods.add(new Modification(ModificationType.REPLACE, LDAP_UID_NUMBER, Long.toString(pd.getUid()))); + mods.add(new Modification(ModificationType.REPLACE, LDAP_GID_NUMBER, Long.toString(pd.getGid()))); + mods.add(new Modification(ModificationType.REPLACE, LDAP_HOME_DIRECTORY, pd.getHomeDirectory())); + mods.add(new Modification(ModificationType.REPLACE, LDAP_LOGIN_SHELL, pd.loginShell)); + } + } + + try + { + ModifyRequest modifyRequest = new ModifyRequest(getUserDN(user), mods); + modifyRequest.addControl( + new ProxiedAuthorizationV2RequestControl( + "dn:" + getSubjectDN().toNormalizedString())); + LdapDAO.checkLdapResult(getConnection().modify(modifyRequest).getResultCode()); + } + catch (LDAPException e1) + { + logger.debug("Modify Exception: " + e1, e1); + LdapDAO.checkLdapResult(e1.getResultCode()); + } + try + { + return getUser(user.getUserID()); + } + catch (UserNotFoundException e) + { + throw new RuntimeException( + "BUG: modified user not found (" + user.getUserID() + ")"); + } + } + + /** + * Update a user's password. The given user and authenticating user must match. + * + * @param user + * @param oldPassword current password. + * @param newPassword new password. + * @throws UserNotFoundException If the given user does not exist. + * @throws TransientException If an temporary, unexpected problem occurred. + * @throws AccessControlException If the operation is not permitted. + */ + public void setPassword(User<T> user, final String oldPassword, final String newPassword) + throws UserNotFoundException, TransientException, AccessControlException { - return null; + try + { + DN userDN = getUserDN(user); + DN subjectDN = getSubjectDN(); + if (!userDN.equals(subjectDN)) + { + throw new AccessControlException("Given user and authenticating user do not match"); + } + + ProxiedAuthorizationV2RequestControl control = + new ProxiedAuthorizationV2RequestControl("dn:" + getSubjectDN().toNormalizedString()); + Control[] controls = new Control[] {control}; + + PasswordModifyExtendedRequest passwordModifyRequest = + new PasswordModifyExtendedRequest(userDN.toNormalizedString(), oldPassword, newPassword, controls); + + PasswordModifyExtendedResult passwordModifyResult = (PasswordModifyExtendedResult) + getConnection().processExtendedOperation(passwordModifyRequest); + LdapDAO.checkLdapResult(passwordModifyResult.getResultCode()); + } + catch (LDAPException e) + { + logger.debug("setPassword Exception: " + e); + LdapDAO.checkLdapResult(e.getResultCode()); + } } /** @@ -588,7 +721,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO * @throws TransientException If an temporary, unexpected problem occurred. * @throws AccessControlException If the operation is not permitted. */ - public boolean isMember(T userID, String groupID) + public boolean isMember(final T userID, final String groupID) throws UserNotFoundException, TransientException, AccessControlException { diff --git a/projects/cadcAccessControl-Server/test/LdapConfig.test.properties b/projects/cadcAccessControl-Server/test/LdapConfig.test.properties index 2354a157763992f801c862d5d1945663edd9b055..bb88d99c07772fa45762f109b6c5c32be22651f0 100644 --- a/projects/cadcAccessControl-Server/test/LdapConfig.test.properties +++ b/projects/cadcAccessControl-Server/test/LdapConfig.test.properties @@ -1,9 +1,8 @@ # This are the configuration fields required by the Ldap ldap-dao unit tests server = proc5-03.cadc.dao.nrc.ca -port = 636 -proxyUser = webproxy -usersDn = ou=Users,ou=ds,dc=canfar,dc=net +port = 389 +proxyUser = testproxy +usersDn = ou=Users,ou=ds,dc=testcanfar userRequestsDN = ou=UserRequests,ou=ds,dc=testcanfar -newUsersDn = ou=NewUsers,ou=ds,dc=canfar,dc=net -groupsDn = ou=Groups,ou=ds,dc=canfar,dc=net -adminGroupsDn = ou=adminGroups,ou=ds,dc=canfar,dc=net \ No newline at end of file +groupsDn = ou=Groups,ou=ds,dc=testcanfar +adminGroupsDn = ou=adminGroups,ou=ds,dc=testcanfar \ No newline at end of file diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAOTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAOTest.java index bad3d32ac6ec804357f8bae67f88707fdca8d619..2f9bcdf27a8fb962fd5d1645f997975200956706 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAOTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAOTest.java @@ -67,23 +67,6 @@ package ca.nrc.cadc.ac.server.ldap; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.security.AccessControlException; -import java.security.PrivilegedExceptionAction; -import java.util.Collection; - -import javax.security.auth.Subject; -import javax.security.auth.x500.X500Principal; - -import org.apache.log4j.Level; -import org.apache.log4j.Logger; -import org.junit.BeforeClass; -import org.junit.Test; - import ca.nrc.cadc.ac.ActivatedGroup; import ca.nrc.cadc.ac.Group; import ca.nrc.cadc.ac.GroupAlreadyExistsException; @@ -91,8 +74,23 @@ import ca.nrc.cadc.ac.GroupNotFoundException; import ca.nrc.cadc.ac.GroupProperty; import ca.nrc.cadc.ac.Role; import ca.nrc.cadc.ac.User; -import ca.nrc.cadc.util.Log4jInit; import ca.nrc.cadc.auth.HttpPrincipal; +import ca.nrc.cadc.util.Log4jInit; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.junit.BeforeClass; +import org.junit.Test; + +import javax.security.auth.Subject; +import javax.security.auth.x500.X500Principal; +import java.security.AccessControlException; +import java.security.PrivilegedExceptionAction; +import java.util.Collection; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; public class LdapGroupDAOTest extends AbstractLdapDAOTest { diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAOTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAOTest.java index aa47a3091287bdbdb006f9876b389df026ce05d6..94b9e28bd28e006ecffe3d38da8ab78e45bf7848 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAOTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAOTest.java @@ -69,6 +69,7 @@ package ca.nrc.cadc.ac.server.ldap; import ca.nrc.cadc.ac.PersonalDetails; +import ca.nrc.cadc.ac.PosixDetails; import ca.nrc.cadc.ac.User; import ca.nrc.cadc.ac.UserDetails; import ca.nrc.cadc.ac.UserRequest; @@ -86,7 +87,11 @@ import java.security.Principal; import java.security.PrivilegedExceptionAction; import java.util.Collection; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; public class LdapUserDAOTest extends AbstractLdapDAOTest { @@ -127,7 +132,7 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest /** * Test of addUser method, of class LdapUserDAO. */ - @Test +// @Test public void testAddUser() throws Exception { final User<HttpPrincipal> expected = new User<HttpPrincipal>(new HttpPrincipal(getUserID())); @@ -147,7 +152,7 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest /** * Test of getUser method, of class LdapUserDAO. */ - @Test +// @Test public void testGetUser() throws Exception { Subject subject = new Subject(); @@ -156,13 +161,14 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest // do everything as owner Subject.doAs(subject, new PrivilegedExceptionAction<Object>() { - public Object run() throws Exception + public Object run() + throws Exception { try { User<X500Principal> actual = getUserDAO().getUser(testUser.getUserID()); check(testUser, actual); - + return null; } catch (Exception e) @@ -177,7 +183,7 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest /** * Test of getUserGroups method, of class LdapUserDAO. */ - @Test +// @Test public void testGetUserGroups() throws Exception { Subject subject = new Subject(); @@ -215,7 +221,7 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest /** * Test of getUserGroups method, of class LdapUserDAO. */ - @Test +// @Test public void testIsMember() throws Exception { Subject subject = new Subject(); @@ -248,7 +254,7 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest /** * Test of getMember. */ - @Test +// @Test public void testGetMember() throws Exception { Subject subject = new Subject(); @@ -279,10 +285,11 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest // do everything as owner Subject.doAs(subject, new PrivilegedExceptionAction<Object>() { - public Object run() throws Exception + public Object run() + throws Exception { try - { + { User<X500Principal> actual = getUserDAO().getMember(new DN(testUserDN)); check(testUser, actual); return null; @@ -290,7 +297,7 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest catch (Exception e) { throw new Exception("Problems", e); - } + } } }); } @@ -298,7 +305,7 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest /** * Test of testGetCadcUserIDs. */ - @Test +// @Test public void testGetCadcUserIDs() throws Exception { Subject subject = new Subject(); @@ -343,7 +350,167 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest } }); assertEquals("User listing should be independent of the access type", - users1, users2); + users1, users2); + } + + @Test + public void testSetPassword() throws Exception + { + // Create a test user with a known password + final User<HttpPrincipal> teststUser2; + final String username = getUserID(); + final String password = "foo"; + final String newPassword = "bar"; + + User<HttpPrincipal> user = new User<HttpPrincipal>(new HttpPrincipal(username)); + user.details.add(new PersonalDetails("firstName", "lastName")); + UserRequest userRequest = new UserRequest(user, password); + teststUser2 = getUserDAO().addUser(userRequest); + + Subject subject = new Subject(); + + // authenticate new useranme and password + Subject.doAs(subject, new PrivilegedExceptionAction<Object>() + { + public Object run() + throws Exception + { + try + { + getUserDAO().loginUser(username, password); + } + catch (Exception e) + { + fail("exception during login: " + e.getMessage()); + } + return null; + } + }); + + // anonymous access should throw exception + Subject.doAs(subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + getUserDAO().setPassword(teststUser2, password, newPassword); + fail("should throw exception if subject and user are not the same"); + } + catch (Exception ignore){} + return null; + } + }); + + // change the password + subject.getPrincipals().add(teststUser2.getUserID()); + Subject.doAs(subject, new PrivilegedExceptionAction<Object>() + { + public Object run() + throws Exception + { + try + { + getUserDAO().setPassword(teststUser2, password, newPassword); + } + catch (Exception e) + { + fail("exception setting password: " + e.getMessage()); + } + return null; + } + }); + + // verify new password + Subject.doAs(subject, new PrivilegedExceptionAction<Object>() + { + public Object run() + throws Exception + { + try + { + getUserDAO().loginUser(username, password); + } + catch (Exception e) + { + fail("exception during login: " + e.getMessage()); + } + return null; + } + }); + + } + + @Test + public void testUpdateUser() throws Exception + { + // Create a test user with a known password + final User<HttpPrincipal> testUser2; + final String username = getUserID(); + final String password = "foo"; + final String newPassword = "bar"; + + User<HttpPrincipal> user = new User<HttpPrincipal>(new HttpPrincipal(username)); + user.details.add(new PersonalDetails("firstName", "lastName")); + UserRequest userRequest = new UserRequest(user, password); + testUser2 = getUserDAO().addUser(userRequest); + + // update the user + for (UserDetails details : user.details) + { + if (details instanceof PersonalDetails) + { + PersonalDetails pd = (PersonalDetails) details; + pd.email = "email2"; + pd.address = "address2"; + pd.institute = "institute2"; + pd.city = "city2"; + pd.country = "country2"; + } + } + user.details.add(new PosixDetails(123L, 456L, "/dev/null")); + + Subject subject = new Subject(); + + // anonymous access should throw exception + Subject.doAs(subject, new PrivilegedExceptionAction<Object>() + { + public Object run() + throws Exception + { + try + { + getUserDAO().modifyUser(testUser2); + fail("should throw exception if subject and user are not the same"); + } + catch (Exception ignore) + { + } + return null; + } + }); + + // update the user + subject.getPrincipals().add(testUser2.getUserID()); + User<? extends Principal> updatedUser = + (User<? extends Principal>) Subject.doAs(subject, new PrivilegedExceptionAction<Object>() + { + public Object run() + throws Exception + { + try + { + return getUserDAO().modifyUser(testUser2); + } + catch (Exception e) + { + fail("exception updating user: " + e.getMessage()); + } + return null; + } + }); + assertNotNull(updatedUser); + check(testUser2, updatedUser); } private static void check(final User<? extends Principal> user1, final User<? extends Principal> user2) @@ -375,6 +542,24 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest assertTrue(found); } } + if (d1 instanceof PosixDetails) + { + PosixDetails pd1 = (PosixDetails) d1; + boolean found = false; + for(UserDetails d2 : user2.details) + { + if(d2 instanceof PosixDetails) + { + PosixDetails pd2 = (PosixDetails) d2; + assertEquals(pd1, pd2); + assertEquals(pd1.getUid(), pd2.getUid()); + assertEquals(pd1.getGid(), pd2.getGid()); + assertEquals(pd1.getHomeDirectory(), pd2.getHomeDirectory()); + found = true; + } + assertTrue(found); + } + } } }