diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/UserPersistence.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/UserPersistence.java index dd80c02e02130e7b717e2d2293773c2e0037f0bc..8a3d81a0de607a4d3350b3ba73030cbb2b33c636 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/UserPersistence.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/UserPersistence.java @@ -91,9 +91,9 @@ public interface UserPersistence<T extends Principal> throws TransientException, AccessControlException; /** - * Add the new user. + * Add the user to the active user tree. * - * @param user The user request to put into the request tree. + * @param user The user request to put into the active user tree. * * @return User instance. * @@ -104,6 +104,20 @@ public interface UserPersistence<T extends Principal> throws TransientException, AccessControlException, UserAlreadyExistsException; + /** + * Add the user to the pending user tree. + * + * @param user The user request to put into the pending user tree. + * + * @return User instance. + * + * @throws TransientException If an temporary, unexpected problem occurred. + * @throws AccessControlException If the operation is not permitted. + */ + void addPendingUser(UserRequest<T> user) + throws TransientException, AccessControlException, + UserAlreadyExistsException; + /** * Get the user specified by userID. * 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 1cee54aed419269958d481b45a0614ffb1180692..130591405dcc6af03a01c2453139387c217e209f 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 @@ -978,6 +978,8 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO { try { + // TODO Subject has the X500Principal, no need to go to ldap. + // TODO X500Principal is optional??? User<X500Principal> subjectUser = userPersist.getX500User(getSubjectDN()); if (subjectUser.equals(owner)) 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 d903007e730fde557dae560653e3b29375ede075..2d1731f7404be9bbae2b1da2c4f9889a101128f2 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 @@ -199,7 +199,8 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO { try { - BindRequest bindRequest = new SimpleBindRequest(getUserDN(username), password); + BindRequest bindRequest = new SimpleBindRequest( + getUserDN(username, config.getUsersDN()), password); BindResult bindResult = getConnection().bind(bindRequest); if (bindResult != null && bindResult.getResultCode() == ResultCode.SUCCESS) @@ -276,75 +277,34 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO } /** - * Add the specified user.. + * Add the specified user to the active user tree. * - * @param userRequest The user to add. + * @param userRequest The user to add. * @return User instance. * @throws TransientException If an temporary, unexpected problem occurred. - * @throws AccessControlException If the operation is not permitted. * @throws UserAlreadyExistsException If the user already exists. */ public void addUser(final UserRequest<T> userRequest) throws TransientException, UserAlreadyExistsException { - DN userDN; - try - { - T userID = userRequest.getUser().getUserID(); - try - { - getUser(userID, config.getUsersDN(), false); - throw new UserAlreadyExistsException(userID.getName() + " found in " + - config.getUsersDN()); - } - catch (UserNotFoundException ignore) {} - - userDN = getUserRequestsDN(userID.getName()); - addUser(userRequest, userDN); - } - catch (LDAPException e) - { - logger.error("addUser Exception: " + e, e); - LdapUserDAO.checkUserLDAPResult(e.getResultCode()); - throw new RuntimeException("Unexpected LDAP exception", e); - } + addUser(userRequest, config.getUsersDN()); } /** - * Package level method for unit testing to add a User directly to the - * Users tree. + *Add the specified user to the pending user tree. + * + * @param userRequest The user to add. + * @return User instance. + * @throws TransientException If an temporary, unexpected problem occurred. + * @throws UserAlreadyExistsException If the user already exists. */ - User<T> newUser(final UserRequest<T> userRequest) - throws TransientException, UserAlreadyExistsException + public void addPendingUser(final UserRequest<T> userRequest) + throws TransientException, UserAlreadyExistsException { - DN userDN; - try - { - userDN = getUserDN(userRequest.getUser().getUserID().getName()); - addUser(userRequest, userDN); - - // AD: Search results sometimes come incomplete if - // connection is not reset - not sure why. - getConnection().reconnect(); - try - { - return getUser(userRequest.getUser().getUserID(), config.getUsersDN()); - } - catch (UserNotFoundException e) - { - throw new RuntimeException("BUG: new user " + userDN.toNormalizedString() + - " not found because " + e.getMessage()); - } - } - catch (LDAPException e) - { - logger.error("newUser Exception: " + e, e); - LdapUserDAO.checkUserLDAPResult(e.getResultCode()); - throw new RuntimeException("Unexpected LDAP exception", e); - } + addUser(userRequest, config.getUserRequestsDN()); } - private void addUser(final UserRequest<T> userRequest, final DN userDN) + private void addUser(final UserRequest<T> userRequest, final String usersDN) throws TransientException, UserAlreadyExistsException { final User<T> user = userRequest.getUser(); @@ -358,25 +318,18 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO try { - // add new user - - DN userX500DN = getUserRequestsDN(user.getUserID().getName()); List<Attribute> attributes = new ArrayList<Attribute>(); addAttribute(attributes, LDAP_OBJECT_CLASS, LDAP_INET_ORG_PERSON); addAttribute(attributes, LDAP_OBJECT_CLASS, LDAP_INET_USER); addAttribute(attributes, LDAP_OBJECT_CLASS, LDAP_CADC_ACCOUNT); - addAttribute(attributes, LDAP_COMMON_NAME, user.getUserID() - .getName()); - addAttribute(attributes, LADP_USER_PASSWORD, new String(userRequest - .getPassword())); - addAttribute(attributes, LDAP_NUMERICID, - String.valueOf(genNextNumericId())); + addAttribute(attributes, LDAP_COMMON_NAME, user.getUserID().getName()); + addAttribute(attributes, LADP_USER_PASSWORD, new String(userRequest.getPassword())); + addAttribute(attributes, LDAP_NUMERICID, String.valueOf(genNextNumericId())); for (Principal princ : user.getIdentities()) { if (princ instanceof X500Principal) { - addAttribute(attributes, LDAP_DISTINGUISHED_NAME, - princ.getName()); + addAttribute(attributes, LDAP_DISTINGUISHED_NAME, princ.getName()); } } for (UserDetails details : user.details) @@ -399,6 +352,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO } } + DN userDN = getUserDN(user.getUserID().getName(), usersDN); AddRequest addRequest = new AddRequest(userDN, attributes); LDAPResult result = getConnection().add(addRequest); LdapDAO.checkLdapResult(result.getResultCode()); @@ -457,24 +411,6 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO private User<T> getUser(final T userID, final String usersDN) throws UserNotFoundException, TransientException, AccessControlException - { - return getUser(userID, usersDN, true); - } - - /** - * Get the user specified by userID. - * - * @param userID The userID. - * @param usersDN The LDAP tree to search. - * @param proxy If true proxy the request as the calling user. - * @return User instance. - * @throws UserNotFoundException when the user is not found. - * @throws TransientException If an temporary, unexpected problem occurred. - * @throws AccessControlException If the operation is not permitted. - */ - private User<T> getUser(final T userID, final String usersDN, boolean proxy) - throws UserNotFoundException, TransientException, - AccessControlException { String searchField = userLdapAttrib.get(userID.getClass()); if (searchField == null) @@ -483,25 +419,20 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO "Unsupported principal type " + userID.getClass()); } - searchField = "(" + searchField + "=" + userID.getName() + ")"; - logger.debug(searchField); - SearchResultEntry searchResult = null; try { + Filter filter = Filter.createNOTFilter(Filter.createPresenceFilter("nsaccountlock")); + filter = Filter.createANDFilter(filter, + Filter.createEqualityFilter(searchField, userID.getName())); + logger.debug("search filter: " + filter); + SearchRequest searchRequest = - new SearchRequest(usersDN, SearchScope.SUB, - searchField, userAttribs); - if (proxy && isSecure(usersDN)) - { - String proxyDN = "dn:" + getSubjectDN().toNormalizedString(); - logger.debug("Proxying auth as: " + proxyDN); - searchRequest.addControl(new ProxiedAuthorizationV2RequestControl(proxyDN)); - } - else - { - logger.debug("Not proxying authorization"); - } + new SearchRequest(usersDN, SearchScope.SUB, filter, userAttribs); + + String proxyDN = "dn:" + getSubjectDN().toNormalizedString(); + logger.debug("Proxying auth as: " + proxyDN); + searchRequest.addControl(new ProxiedAuthorizationV2RequestControl(proxyDN)); searchResult = getConnection().searchForEntry(searchRequest); } @@ -562,16 +493,13 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO try { + Filter filter = Filter.createNOTFilter(Filter.createPresenceFilter("nsaccountlock")); + filter = Filter.createANDFilter(filter, + Filter.createEqualityFilter(searchField, userID.getName())); + logger.debug("search filter: " + filter); - searchField = "(" + searchField + "=" + userID.getName() + ")"; - - logger.debug("search field: " + searchField); - - // TODO: Search must take into account deleted users (nsaccountlock attr) - - SearchRequest searchRequest = - new SearchRequest(config.getUsersDN(), SearchScope.ONE, - searchField, identityAttribs); + SearchRequest searchRequest = new SearchRequest( + config.getUsersDN(), SearchScope.ONE, filter, identityAttribs); SearchResultEntry searchResult = getConnection().searchForEntry(searchRequest); @@ -602,59 +530,62 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO } /** - * Obtain whether the given DN tree requires authentication. + * Get all users from the active tree. * - * @param usersDN The usersDN to check. - * @return True if requires authentication, False otherwise. + * @return A Collection of User's. + * @throws TransientException If an temporary, unexpected problem occurred. */ - private boolean isSecure(final String usersDN) + public Collection<User<Principal>> getUsers() + throws TransientException { - return !usersDN.equals(config.getUserRequestsDN()); + return getUsers(config.getUsersDN()); } /** - * Get all users. This will query the main tree only, and will return the - * user name as the map's key, with the user's full name as the value. + * Get all users from the pending tree. * - * @return A map of string keys to string values. + * @return A Collection of User's. * @throws TransientException If an temporary, unexpected problem occurred. */ - public Collection<User<Principal>> getUsers() - throws TransientException + public Collection<User<Principal>> getPendingUsers() + throws TransientException + { + return getUsers(config.getUserRequestsDN()); + } + + private Collection<User<Principal>> getUsers(final String usersDN) + throws TransientException { final Collection<User<Principal>> users = new ArrayList<User<Principal>>(); try { - final Filter filter = Filter.createPresenceFilter(LDAP_UID); - final String[] attributes = new String[]{LDAP_UID, - LDAP_FIRST_NAME, - LDAP_LAST_NAME, - LDAP_NSACCOUNTLOCK}; + Filter filter = Filter.createNOTFilter(Filter.createPresenceFilter("nsaccountlock")); + filter = Filter.createANDFilter(filter, Filter.createPresenceFilter(LDAP_UID)); + logger.debug("search filter: " + filter); + + final String[] attributes = new String[] + { LDAP_UID, LDAP_FIRST_NAME, LDAP_LAST_NAME, LDAP_NSACCOUNTLOCK }; final SearchRequest searchRequest = - new SearchRequest(config.getUsersDN(), - SearchScope.SUB, filter, attributes); + new SearchRequest(usersDN, SearchScope.ONE, filter, attributes); try { final SearchResult searchResult = - getConnection().search(searchRequest); + getConnection().search(searchRequest); LdapDAO.checkLdapResult(searchResult.getResultCode()); for (SearchResultEntry next : searchResult.getSearchEntries()) { - if (!next.hasAttribute(LDAP_NSACCOUNTLOCK)) - { - final String firstName = - next.getAttributeValue(LDAP_FIRST_NAME).trim(); - final String lastName = - next.getAttributeValue(LDAP_LAST_NAME).trim(); - final String uid = next.getAttributeValue(LDAP_UID).trim(); - User<Principal> user = new User<Principal>(new HttpPrincipal(uid)); - PersonalDetails pd = new PersonalDetails(firstName, lastName); - user.details.add(pd); - users.add(user); - } + final String firstName = + next.getAttributeValue(LDAP_FIRST_NAME).trim(); + final String lastName = + next.getAttributeValue(LDAP_LAST_NAME).trim(); + final String uid = next.getAttributeValue(LDAP_UID).trim(); + User<Principal> user = new User<Principal>(new HttpPrincipal(uid)); + PersonalDetails pd = new PersonalDetails(firstName, lastName); + user.details.add(pd); + users.add(user); } } catch (LDAPSearchException e) @@ -669,10 +600,10 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO } catch (LDAPException e1) { - logger.debug("getGroupNames Exception: " + e1, e1); + logger.debug("getUsers Exception: " + e1, e1); LdapDAO.checkLdapResult(e1.getResultCode()); - throw new IllegalStateException("Unexpected exception: " + e1 - .getMatchedDN(), e1); + throw new IllegalStateException( + "Unexpected exception: " + e1.getMatchedDN(), e1); } return users; @@ -765,7 +696,8 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO Control[] controls = new Control[] {control}; PasswordModifyExtendedRequest passwordModifyRequest = - new PasswordModifyExtendedRequest(userDN.toNormalizedString(), oldPassword, newPassword, controls); + new PasswordModifyExtendedRequest( + userDN.toNormalizedString(), oldPassword, newPassword, controls); PasswordModifyExtendedResult passwordModifyResult = (PasswordModifyExtendedResult) getConnection().processExtendedOperation(passwordModifyRequest); @@ -779,7 +711,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO } /** - * Delete the user specified by userID. + * Delete the user specified by userID from the active user tree. * * @param userID The userID. * @throws UserNotFoundException when the user is not found. @@ -790,7 +722,55 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO throws UserNotFoundException, TransientException, AccessControlException { + deleteUser(userID, config.getUsersDN()); + } + + /** + * Delete the user specified by userID from the pending user tree. + * + * @param userID The userID. + * @throws UserNotFoundException when the user is not found. + * @throws TransientException If an temporary, unexpected problem occurred. + * @throws AccessControlException If the operation is not permitted. + */ + public void deletePendingUser(final T userID) + throws UserNotFoundException, TransientException, + AccessControlException + { + deleteUser(userID, config.getUserRequestsDN()); + } + + private void deleteUser(final T userID, final String usersDN) + throws UserNotFoundException, AccessControlException, TransientException + { + getUser(userID, usersDN); + try + { + DN userDN = getUserDN(userID.getName(), usersDN); + List<Modification> modifs = new ArrayList<Modification>(); + modifs.add(new Modification(ModificationType.ADD, "nsaccountlock", "true")); + + ModifyRequest modifyRequest = new ModifyRequest(userDN, modifs); + modifyRequest.addControl( + new ProxiedAuthorizationV2RequestControl( + "dn:" + getSubjectDN().toNormalizedString())); + LDAPResult result = getConnection().modify(modifyRequest); + LdapDAO.checkLdapResult(result.getResultCode()); + } + catch (LDAPException e1) + { + logger.debug("Delete Exception: " + e1, e1); + LdapDAO.checkLdapResult(e1.getResultCode()); + } + + try + { + getUser(userID, usersDN); + throw new RuntimeException( + "BUG: " + userID.getName() + " not deleted in " + usersDN); + } + catch (UserNotFoundException ignore) {} } /** @@ -936,10 +916,10 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO { Filter filter = Filter.createEqualityFilter(LDAP_ENTRYDN, - userDN.toNormalizedString()); + userDN.toNormalizedString()); SearchRequest searchRequest = - new SearchRequest(this.config.getUsersDN(), SearchScope.SUB, + new SearchRequest(config.getUsersDN(), SearchScope.ONE, filter, memberAttribs); SearchResultEntry searchResult = @@ -947,7 +927,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO if (searchResult == null) { - String msg = "Member not found " + userDN; + String msg = "User not found " + userDN; logger.debug(msg); throw new UserNotFoundException(msg); } @@ -970,42 +950,33 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO DN getUserDN(User<? extends Principal> user) throws UserNotFoundException, TransientException { - String searchField = - userLdapAttrib.get(user.getUserID().getClass()); + String searchField = userLdapAttrib.get(user.getUserID().getClass()); if (searchField == null) { throw new IllegalArgumentException( - "Unsupported principal type " + user.getUserID() - .getClass()); + "Unsupported principal type " + user.getUserID().getClass()); } // change the DN to be in the 'java' format + Filter filter; if (user.getUserID() instanceof X500Principal) { X500Principal orderedPrincipal = AuthenticationUtil.getOrderedForm( - (X500Principal) user.getUserID()); - searchField = "(" + searchField + "=" + orderedPrincipal - .toString() + ")"; + (X500Principal) user.getUserID()); + filter = Filter.createEqualityFilter(searchField, orderedPrincipal.toString()); } else { - searchField = "(" + searchField + "=" + user.getUserID().getName() - + ")"; + filter = Filter.createEqualityFilter(searchField, user.getUserID().getName()); } - - logger.debug("Search field is: " + searchField); + logger.debug("search filter: " + filter); SearchResultEntry searchResult = null; try { - SearchRequest searchRequest = - new SearchRequest(this.config.getUsersDN(), SearchScope.SUB, - searchField, LDAP_ENTRYDN); - - - searchResult = - getConnection().searchForEntry(searchRequest); - + SearchRequest searchRequest = new SearchRequest( + config.getUsersDN(), SearchScope.SUB, filter, LDAP_ENTRYDN); + searchResult = getConnection().searchForEntry(searchRequest); } catch (LDAPException e) { @@ -1021,12 +992,12 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO return searchResult.getAttributeValueAsDN(LDAP_ENTRYDN); } - protected DN getUserDN(final String userID) + protected DN getUserDN(final String userID, final String usersDN) throws LDAPException, TransientException { try { - return new DN(LDAP_UID + "=" + userID + "," + config.getUsersDN()); + return new DN(LDAP_UID + "=" + userID + "," + usersDN); } catch (LDAPException e) { @@ -1036,22 +1007,6 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO throw new IllegalArgumentException(userID + " not a valid user ID"); } - protected DN getUserRequestsDN(final String userID) - throws LDAPException, TransientException - { - try - { - return new DN(LDAP_UID + "=" + userID + "," + config - .getUserRequestsDN()); - } - catch (LDAPException e) - { - logger.debug("getUserRequestsDN Exception: " + e, e); - LdapDAO.checkLdapResult(e.getResultCode()); - } - throw new IllegalArgumentException(userID + " not a valid user ID"); - } - private void addAttribute(List<Attribute> attributes, final String name, final String value) { if (value != null && !value.isEmpty()) diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserPersistence.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserPersistence.java index cd8fde670bda3e86d22f00cc7e3dbd14b35d2fd8..8089d7fca6471c238a4e4f067ff212671ca0dd32 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserPersistence.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserPersistence.java @@ -117,9 +117,9 @@ public class LdapUserPersistence<T extends Principal> } /** - * Add the new user. + * Add the user to the active user tree. * - * @param user + * @param user The user request to put into the active user tree. * * @return User instance. * @@ -145,6 +145,35 @@ public class LdapUserPersistence<T extends Principal> } } + /** + * Add the user to the pending user tree. + * + * @param user The user request to put into the pending user tree. + * + * @return User instance. + * + * @throws TransientException If an temporary, unexpected problem occurred. + * @throws AccessControlException If the operation is not permitted. + */ + public void addPendingUser(UserRequest<T> user) + throws TransientException, AccessControlException, + UserAlreadyExistsException + { + LdapUserDAO<T> userDAO = null; + try + { + userDAO = new LdapUserDAO<T>(this.config); + userDAO.addPendingUser(user); + } + finally + { + if (userDAO != null) + { + userDAO.close(); + } + } + } + /** * Get the user specified by userID. * @@ -183,9 +212,8 @@ public class LdapUserPersistence<T extends Principal> * @throws TransientException If an temporary, unexpected problem occurred. * @throws AccessControlException If the operation is not permitted. */ - public User<T> getPendingUser(final T userID) throws UserNotFoundException, - TransientException, - AccessControlException + public User<T> getPendingUser(final T userID) + throws UserNotFoundException, TransientException, AccessControlException { LdapUserDAO<T> userDAO = null; try diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/CreateUserAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/CreateUserAction.java index 03c09628ebf54a14651daea88d0046e801624de3..14f3e4ed579a24bd5a029f9e7fb90c131f8e60bb 100644 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/CreateUserAction.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/CreateUserAction.java @@ -93,7 +93,7 @@ public class CreateUserAction extends AbstractUserAction { final UserPersistence<Principal> userPersistence = getUserPersistence(); final UserRequest<Principal> userRequest = readUserRequest(this.inputStream); - userPersistence.addUser(userRequest); + userPersistence.addPendingUser(userRequest); syncOut.setCode(201); logUserInfo(userRequest.getUser().getUserID().getName()); diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/DeleteUserAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/DeleteUserAction.java index aa74d299c1798e2799a66e60606a3def3097cc78..9b17c8765e5a0377665d0d5e743fae128f7f1e09 100644 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/DeleteUserAction.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/DeleteUserAction.java @@ -68,8 +68,8 @@ */ package ca.nrc.cadc.ac.server.web.users; -import ca.nrc.cadc.ac.User; import ca.nrc.cadc.ac.server.UserPersistence; + import java.security.Principal; public class DeleteUserAction extends AbstractUserAction @@ -85,8 +85,7 @@ public class DeleteUserAction extends AbstractUserAction public void doAction() throws Exception { UserPersistence userPersistence = getUserPersistence(); - User<? extends Principal> deletedUser = userPersistence.getUser(userID); - userPersistence.deleteUser(deletedUser.getUserID()); + userPersistence.deleteUser(userID); } } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/GetUserAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/GetUserAction.java index ee81cfd60b063125547483e437c89e58a1d5cb13..852b730458a79910e25ab90c0dcbe50620e835b0 100644 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/GetUserAction.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/GetUserAction.java @@ -156,7 +156,6 @@ public class GetUserAction extends AbstractUserAction user.details.clear(); user.details.add(new PersonalDetails(pd.getFirstName(), pd.getLastName())); } - } return user; 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 f812b3ccac62ea9c31029ceab9bfdf600db0652c..604e1cc533f41901c575af0baf1943b881818ee6 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 @@ -106,6 +106,7 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest static final String testUserX509DN = "cn=cadcdaotest1,ou=cadc,o=hia,c=ca"; static final String testUser1EntryDN = "uid=cadcdaotest1,ou=users,ou=ds,dc=testcanfar"; static final String testUser2EntryDN = "uid=cadcdaotest2,ou=users,ou=ds,dc=testcanfar"; + static final String testPendingUserEntryDN = "uid=cadctestrequest,ou=users,ou=ds,dc=testcanfar"; static int nextUserNumericID = 666; static String testUserDN; @@ -114,6 +115,7 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest static User<HttpPrincipal> testPendingUser; static DNPrincipal testUser1DNPrincipal; static DNPrincipal testUser2DNPrincipal; + static DNPrincipal testPendingUserDNPrincipal; static LdapConfig config; static Random ran = new Random(); // source of randomness for numeric ids @@ -155,6 +157,7 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest testUser1DNPrincipal = new DNPrincipal(testUser1EntryDN); testUser2DNPrincipal = new DNPrincipal(testUser2EntryDN); + testPendingUserDNPrincipal = new DNPrincipal(testPendingUserEntryDN); } <T extends Principal> LdapUserDAO<T> getUserDAO() throws Exception @@ -179,33 +182,141 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest public void testAddUser() throws Exception { String userID = createUserID(); - final User<HttpPrincipal> expected = new User<HttpPrincipal>(new HttpPrincipal(userID)); - expected.getIdentities().add(new HttpPrincipal(userID)); - expected.getIdentities().add(new X500Principal("cn=" + userID + ",ou=cadc,o=hia,c=ca")); - nextUserNumericID = ran.nextInt(Integer.MAX_VALUE); - expected.getIdentities().add(new NumericPrincipal(nextUserNumericID)); + + HttpPrincipal httpPrincipal = new HttpPrincipal(userID); + X500Principal x500Principal = new X500Principal("cn=" + userID + ",ou=cadc,o=hia,c=ca"); + NumericPrincipal numericPrincipal = new NumericPrincipal(ran.nextInt(Integer.MAX_VALUE)); + + final User<Principal> expected = new User<Principal>(httpPrincipal); + expected.getIdentities().add(httpPrincipal); + expected.getIdentities().add(x500Principal); + expected.getIdentities().add(numericPrincipal); expected.details.add(new PersonalDetails("foo", "bar")); - final UserRequest<HttpPrincipal> userRequest = - new UserRequest<HttpPrincipal>(expected, "123456".toCharArray()); + final UserRequest<Principal> userRequest = + new UserRequest<Principal>(expected, "123456".toCharArray()); + + final LdapUserDAO<Principal> userDAO = getUserDAO(); + userDAO.addUser(userRequest); + DNPrincipal dnPrincipal = new DNPrincipal("uid=" + userID + "," + config.getUsersDN()); Subject subject = new Subject(); - subject.getPrincipals().add(testUser.getUserID()); + subject.getPrincipals().add(dnPrincipal); - final LdapUserDAO<HttpPrincipal> userDAO = getUserDAO(); - userDAO.addUser(userRequest); + // do everything as owner + Subject.doAs(subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + final LdapUserDAO<Principal> userDAO = getUserDAO(); + final User<Principal> actual = + userDAO.getUser(expected.getUserID()); + check(expected, actual); + + return null; + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + } + }); + } + + /** + * Test of addPendingUser method, of class LdapUserDAO. + */ + @Test + public void testAddPendingUser() throws Exception + { + String userID = createUserID(); + + HttpPrincipal httpPrincipal = new HttpPrincipal(userID); + X500Principal x500Principal = new X500Principal("cn=" + userID + ",ou=cadc,o=hia,c=ca"); + NumericPrincipal numericPrincipal = new NumericPrincipal(ran.nextInt(Integer.MAX_VALUE)); + + final User<Principal> expected = new User<Principal>(httpPrincipal); + expected.getIdentities().add(httpPrincipal); + expected.getIdentities().add(x500Principal); + expected.getIdentities().add(numericPrincipal); + + expected.details.add(new PersonalDetails("foo", "bar")); + + final UserRequest<Principal> userRequest = + new UserRequest<Principal>(expected, "123456".toCharArray()); + + final LdapUserDAO<Principal> userDAO = getUserDAO(); + userDAO.addPendingUser(userRequest); + + DNPrincipal dnPrincipal = new DNPrincipal("uid=" + userID + "," + config.getUserRequestsDN()); + Subject subject = new Subject(); + subject.getPrincipals().add(dnPrincipal); + + // do everything as owner + Subject.doAs(subject, new PrivilegedExceptionAction<Object>() + { + public Object run() + throws Exception + { + try + { + final LdapUserDAO<Principal> userDAO = getUserDAO(); + final User<Principal> actual = + userDAO.getPendingUser(expected.getUserID()); + check(expected, actual); + + return null; + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + } + }); + } + + /** + * Test of getUser method, of class LdapUserDAO. + */ + @Test + public void testGetUser() throws Exception + { + Subject subject = new Subject(); + subject.getPrincipals().add(testUser.getUserID()); + subject.getPrincipals().add(testUser1DNPrincipal); - User<HttpPrincipal> actual = userDAO.getPendingUser(userRequest.getUser().getUserID()); + // do everything as owner + Subject.doAs(subject, new PrivilegedExceptionAction<Object>() + { + public Object run() + throws Exception + { + try + { + final LdapUserDAO<X500Principal> userDAO = getUserDAO(); + final User<X500Principal> actual = + userDAO.getUser(testUser.getUserID()); + check(testUser, actual); - check(expected, actual); + return null; + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + } + }); } @Test public void testGetPendingUser() throws Exception { final Subject subject = new Subject(); - subject.getPrincipals().add(testUser.getUserID()); + subject.getPrincipals().add(testPendingUser.getUserID()); + subject.getPrincipals().add(testPendingUserDNPrincipal); // do everything as owner Subject.doAs(subject, new PrivilegedExceptionAction<Object>() @@ -229,28 +340,189 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest }); } + @Test + public void testUpdateUser() throws Exception + { + // Create a test user + final User<HttpPrincipal> testUser2; + final String username = createUserID(); + final char[] password = "foo".toCharArray(); + + HttpPrincipal principal = new HttpPrincipal(username); + testUser2 = new User<HttpPrincipal>(principal); + testUser2.getIdentities().add(principal); + testUser2.getIdentities().add(new X500Principal("cn=" + username + ",ou=cadc,o=hia,c=ca")); + // update nextNumericId + nextUserNumericID = ran.nextInt(Integer.MAX_VALUE); + testUser2.getIdentities().add(new NumericPrincipal(nextUserNumericID)); + testUser2.details.add(new PersonalDetails("firstName", "lastName")); + final UserRequest<HttpPrincipal> userRequest = + new UserRequest<HttpPrincipal>(testUser2, password); + + // add the user + Subject subject = new Subject(); + subject.getPrincipals().add(testUser2.getUserID()); + subject.getPrincipals().add(testUser2DNPrincipal); + Subject.doAs(subject, new PrivilegedExceptionAction<Object>() + { + public Object run() + throws Exception + { + try + { + final LdapUserDAO<HttpPrincipal> userDAO = getUserDAO(); + userDAO.addUser(userRequest); + } + catch (Exception e) + { + fail("exception updating user: " + e.getMessage()); + } + return null; + } + }); + + // update the user + for (UserDetails details : testUser2.details) + { + if (details instanceof PersonalDetails) + { + PersonalDetails pd = (PersonalDetails) details; + pd.email = "email2"; + pd.address = "address2"; + pd.institute = "institute2"; + pd.city = "city2"; + pd.country = "country2"; + } + } + + // anonymous access should throw exception + subject = new Subject(); + Subject.doAs(subject, new PrivilegedExceptionAction<Object>() + { + public Object run() + throws Exception + { + try + { + final LdapUserDAO<HttpPrincipal> userDAO = getUserDAO(); + userDAO.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()); + subject.getPrincipals().add(testUser2DNPrincipal); + User<? extends Principal> updatedUser = + (User<? extends Principal>) Subject.doAs(subject, new PrivilegedExceptionAction<Object>() + { + public Object run() + throws Exception + { + try + { + final LdapUserDAO<HttpPrincipal> userDAO = getUserDAO(); + return userDAO.modifyUser(testUser2); + } + catch (Exception e) + { + e.printStackTrace(); + fail("exception updating user: " + e.getMessage()); + } + return null; + } + }); + assertNotNull(updatedUser); + check(testUser2, updatedUser); + } + /** - * Test of getUser method, of class LdapUserDAO. + * Test of deleteUser method, of class LdapUserDAO. */ @Test - public void testGetUser() throws Exception + public void deleteUser() throws Exception { + String userID = createUserID(); + + HttpPrincipal httpPrincipal = new HttpPrincipal(userID); + X500Principal x500Principal = new X500Principal("cn=" + userID + ",ou=cadc,o=hia,c=ca"); + + final User<HttpPrincipal> expected = new User<HttpPrincipal>(httpPrincipal); + expected.getIdentities().add(httpPrincipal); + expected.getIdentities().add(x500Principal); + expected.details.add(new PersonalDetails("foo", "bar")); + + final UserRequest<HttpPrincipal> userRequest = + new UserRequest<HttpPrincipal>(expected, "123456".toCharArray()); + + final LdapUserDAO<HttpPrincipal> userDAO = getUserDAO(); + userDAO.addUser(userRequest); + + DNPrincipal dnPrincipal = new DNPrincipal("uid=" + userID + "," + config.getUsersDN()); Subject subject = new Subject(); - subject.getPrincipals().add(testUser.getUserID()); - subject.getPrincipals().add(testUser1DNPrincipal); + subject.getPrincipals().add(dnPrincipal); // do everything as owner Subject.doAs(subject, new PrivilegedExceptionAction<Object>() { - public Object run() throws Exception + public Object run() + throws Exception { try { - final LdapUserDAO<X500Principal> userDAO = getUserDAO(); - final User<X500Principal> actual = - userDAO.getUser(testUser.getUserID()); - check(testUser, actual); + final LdapUserDAO<Principal> userDAO = getUserDAO(); + userDAO.deleteUser(expected.getUserID()); + return null; + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + } + }); + } + + /** + * Test of deletePendingUser method, of class LdapUserDAO. + */ + @Test + public void deletePendingUser() throws Exception + { + String userID = createUserID(); + + HttpPrincipal httpPrincipal = new HttpPrincipal(userID); + X500Principal x500Principal = new X500Principal("cn=" + userID + ",ou=cadc,o=hia,c=ca"); + + final User<HttpPrincipal> expected = new User<HttpPrincipal>(httpPrincipal); + expected.getIdentities().add(httpPrincipal); + expected.getIdentities().add(x500Principal); + expected.details.add(new PersonalDetails("foo", "bar")); + + final UserRequest<HttpPrincipal> userRequest = + new UserRequest<HttpPrincipal>(expected, "123456".toCharArray()); + + final LdapUserDAO<HttpPrincipal> userDAO = getUserDAO(); + userDAO.addPendingUser(userRequest); + + DNPrincipal dnPrincipal = new DNPrincipal("uid=" + userID + "," + config.getUserRequestsDN()); + Subject subject = new Subject(); + subject.getPrincipals().add(dnPrincipal); + // do everything as owner + Subject.doAs(subject, new PrivilegedExceptionAction<Object>() + { + public Object run() + throws Exception + { + try + { + final LdapUserDAO<Principal> userDAO = getUserDAO(); + userDAO.deletePendingUser(expected.getUserID()); return null; } catch (Exception e) @@ -288,7 +560,7 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest } groups = getUserDAO().getUserGroups(testUser.getUserID(), - true); + true); assertNotNull("Groups should not be null.", groups); for (DN groupDN : groups) { @@ -444,6 +716,28 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest users1, users2); } + @Test + public void testGetUsers() throws Exception + { + final LdapUserDAO<Principal> userDAO = getUserDAO(); + final Collection<User<Principal>> users = userDAO.getUsers(); + + assertNotNull("returned users is null", users); + assertFalse("no users found", users.isEmpty()); + log.debug("# users found: " + users.size()); + } + + @Test + public void testGetPendingUsers() throws Exception + { + final LdapUserDAO<Principal> userDAO = getUserDAO(); + final Collection<User<Principal>> users = userDAO.getPendingUsers(); + + assertNotNull("returned users is null", users); + assertFalse("no users found", users.isEmpty()); + log.debug("# pending users found: " + users.size()); + } + // @Test public void testSetPassword() throws Exception { @@ -464,16 +758,19 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest final char[] password = "foo".toCharArray(); final char[] newPassword = "bar".toCharArray(); - HttpPrincipal principal = new HttpPrincipal(username); - testUser2 = new User<HttpPrincipal>(principal); - testUser2.getIdentities().add(principal); + HttpPrincipal httpPrincipal = new HttpPrincipal(username); + + testUser2 = new User<HttpPrincipal>(httpPrincipal); + testUser2.getIdentities().add(httpPrincipal); testUser2.details.add(new PersonalDetails("firstName", "lastName")); final UserRequest<HttpPrincipal> userRequest = new UserRequest<HttpPrincipal>(testUser2, password); // add the user + DNPrincipal dnPrincipal = new DNPrincipal("uid=" + username + "," + config.getUsersDN()); Subject subject = new Subject(); subject.getPrincipals().add(testUser2.getUserID()); + subject.getPrincipals().add(dnPrincipal); Subject.doAs(subject, new PrivilegedExceptionAction<Object>() { public Object run() @@ -482,7 +779,7 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest try { final LdapUserDAO<HttpPrincipal> userDAO = getUserDAO(); - return userDAO.newUser(userRequest); + userDAO.addUser(userRequest); } catch (Exception e) { @@ -514,22 +811,26 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest subject = new Subject(); Subject.doAs(subject, new PrivilegedExceptionAction<Object>() { - public Object run() throws Exception + public Object run() + throws Exception { try { final LdapUserDAO<HttpPrincipal> userDAO = getUserDAO(); userDAO.setPassword(testUser2, String.valueOf(password), - String.valueOf(newPassword)); + String.valueOf(newPassword)); fail("should throw exception if subject and user are not the same"); } - catch (Exception ignore){} + catch (Exception ignore) + { + } return null; } }); // change the password subject.getPrincipals().add(testUser2.getUserID()); + subject.getPrincipals().add(dnPrincipal); Subject.doAs(subject, new PrivilegedExceptionAction<Object>() { public Object run() @@ -539,7 +840,7 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest { final LdapUserDAO<HttpPrincipal> userDAO = getUserDAO(); userDAO.setPassword(testUser2, String.valueOf(password), - String.valueOf(newPassword)); + String.valueOf(newPassword)); } catch (Exception e) { @@ -570,107 +871,6 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest } - @Test - public void testUpdateUser() throws Exception - { - // Create a test user - final User<HttpPrincipal> testUser2; - final String username = createUserID(); - final char[] password = "foo".toCharArray(); - - HttpPrincipal principal = new HttpPrincipal(username); - testUser2 = new User<HttpPrincipal>(principal); - testUser2.getIdentities().add(principal); - testUser2.getIdentities().add(new X500Principal("cn=" + username + ",ou=cadc,o=hia,c=ca")); - // update nextNumericId - nextUserNumericID = ran.nextInt(Integer.MAX_VALUE); - testUser2.getIdentities().add(new NumericPrincipal(nextUserNumericID)); - testUser2.details.add(new PersonalDetails("firstName", "lastName")); - final UserRequest<HttpPrincipal> userRequest = - new UserRequest<HttpPrincipal>(testUser2, password); - - // add the user - Subject subject = new Subject(); - subject.getPrincipals().add(testUser2.getUserID()); - subject.getPrincipals().add(testUser2DNPrincipal); - Subject.doAs(subject, new PrivilegedExceptionAction<Object>() - { - public Object run() - throws Exception - { - try - { - final LdapUserDAO<HttpPrincipal> userDAO = getUserDAO(); - return userDAO.newUser(userRequest); - } - catch (Exception e) - { - fail("exception updating user: " + e.getMessage()); - } - return null; - } - }); - - // update the user - for (UserDetails details : testUser2.details) - { - if (details instanceof PersonalDetails) - { - PersonalDetails pd = (PersonalDetails) details; - pd.email = "email2"; - pd.address = "address2"; - pd.institute = "institute2"; - pd.city = "city2"; - pd.country = "country2"; - } - } - - // anonymous access should throw exception - subject = new Subject(); - Subject.doAs(subject, new PrivilegedExceptionAction<Object>() - { - public Object run() - throws Exception - { - try - { - final LdapUserDAO<HttpPrincipal> userDAO = getUserDAO(); - userDAO.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()); - subject.getPrincipals().add(testUser2DNPrincipal); - User<? extends Principal> updatedUser = - (User<? extends Principal>) Subject.doAs(subject, new PrivilegedExceptionAction<Object>() - { - public Object run() - throws Exception - { - try - { - final LdapUserDAO<HttpPrincipal> userDAO = getUserDAO(); - return userDAO.modifyUser(testUser2); - } - catch (Exception e) - { - e.printStackTrace(); - 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) { @@ -685,7 +885,11 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest { if (princ2.getClass() == princ1.getClass()) { - assertEquals(princ1, princ2); + // NumericPrincipals are server generated, can't compare + if (princ2.getClass() != NumericPrincipal.class) + { + assertEquals(princ1, princ2); + } found = true; } } diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/WhoAmIServletTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/WhoAmIServletTest.java index 35ad6d450fc2d529e9b74f8b6ca369d8716242ba..a3e789ebea9549fb41ee4cc770fc4365d19a0c4a 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/WhoAmIServletTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/WhoAmIServletTest.java @@ -71,6 +71,10 @@ package ca.nrc.cadc.ac.server.web; import ca.nrc.cadc.ac.AC; import ca.nrc.cadc.auth.HttpPrincipal; import ca.nrc.cadc.reg.client.RegistryClient; +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; @@ -83,9 +87,16 @@ import java.security.PrivilegedExceptionAction; import static org.easymock.EasyMock.*; - public class WhoAmIServletTest { + private static final Logger log = Logger.getLogger(WhoAmIServletTest.class); + @BeforeClass + public static void setUpBeforeClass() + throws Exception + { + Log4jInit.setLevel("ca.nrc.cadc.ac", Level.INFO); + } + @Test public void doGet() throws Exception { @@ -114,10 +125,8 @@ public class WhoAmIServletTest } }; - final HttpServletRequest mockRequest = - createMock(HttpServletRequest.class); - final HttpServletResponse mockResponse = - createMock(HttpServletResponse.class); + final HttpServletRequest mockRequest = createMock(HttpServletRequest.class); + final HttpServletResponse mockResponse = createMock(HttpServletResponse.class); expect(mockRequest.getPathInfo()).andReturn("users/CADCtest").once(); expect(mockRequest.getMethod()).andReturn("GET").once(); @@ -127,7 +136,7 @@ public class WhoAmIServletTest expectLastCall().once(); expect(mockRegistry.getServiceURL(URI.create(AC.GMS_SERVICE_URI), - "http", "/users/%s?idType=HTTP")). + "https", "/users/%s?idType=HTTP")). andReturn(new URL("https://mysite.com/ac/users/CADCtest?idType=HTTP")).once(); replay(mockRequest, mockResponse, mockRegistry);