diff --git a/projects/cadcAccessControl-Server/build.xml b/projects/cadcAccessControl-Server/build.xml index 12e688469aee1444d7027bef89f048af9de33f88..39cce90c8e2f2e8c6a52777adad23ec353c5d8f0 100644 --- a/projects/cadcAccessControl-Server/build.xml +++ b/projects/cadcAccessControl-Server/build.xml @@ -139,7 +139,7 @@ <property name="testingJars" value="${lib.commons-logging}:${dev.junit}:${dev.jsonassert}:${dev.httpunit}:${dev.easyMock}:${dev.selenium.server}:${dev.objenesis}:${lib.js}:${lib.nekoHTML}:${lib.xerces}"/> - <target name="test" depends="compile,compile-test"> + <target name="single-test" depends="compile,compile-test"> <echo message="Running test suite..." /> <junit printsummary="yes" haltonfailure="yes" fork="yes"> <classpath> @@ -148,8 +148,7 @@ <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" /> + <test name="ca.nrc.cadc.ac.server.web.users.GetUserListActionTest" /> <formatter type="plain" usefile="false" /> </junit> </target> diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/GroupPersistence.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/GroupPersistence.java index bdfa4e05c79516396085e5ffb90d031dc2d7c3e2..4da9df744f39564fc7bbd3343aa089b9505008e9 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/GroupPersistence.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/GroupPersistence.java @@ -79,7 +79,7 @@ import ca.nrc.cadc.ac.Role; import ca.nrc.cadc.ac.UserNotFoundException; import ca.nrc.cadc.net.TransientException; -public abstract interface GroupPersistence<T extends Principal> +public interface GroupPersistence<T extends Principal> { /** * Get all group names. @@ -88,7 +88,7 @@ public abstract interface GroupPersistence<T extends Principal> * @throws TransientException If an temporary, unexpected problem occurred. * @throws AccessControlException If the operation is not permitted. */ - public Collection<String> getGroupNames() + Collection<String> getGroupNames() throws TransientException, AccessControlException; /** @@ -102,7 +102,7 @@ public abstract interface GroupPersistence<T extends Principal> * @throws TransientException If an temporary, unexpected problem occurred. * @throws AccessControlException If the operation is not permitted. */ - public abstract Group getGroup(String groupID) + Group getGroup(String groupID) throws GroupNotFoundException, TransientException, AccessControlException; @@ -121,7 +121,7 @@ public abstract interface GroupPersistence<T extends Principal> * @throws GroupNotFoundException if one of the groups in group members or * group admins does not exist in the server. */ - public abstract Group addGroup(Group group) + Group addGroup(Group group) throws GroupAlreadyExistsException, TransientException, AccessControlException, UserNotFoundException, GroupNotFoundException; @@ -135,7 +135,7 @@ public abstract interface GroupPersistence<T extends Principal> * @throws TransientException If an temporary, unexpected problem occurred. * @throws AccessControlException If the operation is not permitted. */ - public abstract void deleteGroup(String groupID) + void deleteGroup(String groupID) throws GroupNotFoundException, TransientException, AccessControlException; @@ -151,7 +151,7 @@ public abstract interface GroupPersistence<T extends Principal> * @throws AccessControlException If the operation is not permitted. * @throws UserNotFoundException If owner or group members not valid users. */ - public abstract Group modifyGroup(Group group) + Group modifyGroup(Group group) throws GroupNotFoundException, TransientException, AccessControlException, UserNotFoundException; @@ -170,9 +170,24 @@ public abstract interface GroupPersistence<T extends Principal> * @throws TransientException If an temporary, unexpected problem occurred. * @throws AccessControlException If the operation is not permitted. */ - public abstract Collection<Group> getGroups(T userID, Role role, - String groupID) + Collection<Group> getGroups(T userID, Role role, String groupID) throws UserNotFoundException, GroupNotFoundException, TransientException, AccessControlException; + /** + * Check whether the user is a member of the group. + * + * @param userID The userID. + * @param groupID The groupID. + * + * @return true or false + * + * @throws UserNotFoundException If the user is not found. + * @throws TransientException If an temporary, unexpected problem occurred. + * @throws AccessControlException If the operation is not permitted. + */ + boolean isMember(T userID, String groupID) + throws UserNotFoundException, TransientException, + AccessControlException; + } 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 1b369f709fc643f55e6713dfe80fcee4cdc38cbe..f88faffeb2851833b99c606de1f63e317703960f 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 @@ -70,14 +70,11 @@ package ca.nrc.cadc.ac.server; import java.security.AccessControlException; import java.security.Principal; -import java.util.Collection; import java.util.Map; import ca.nrc.cadc.ac.*; import ca.nrc.cadc.net.TransientException; -import com.unboundid.ldap.sdk.DN; - public interface UserPersistence<T extends Principal> { @@ -94,7 +91,7 @@ public interface UserPersistence<T extends Principal> /** * Add the new user. * - * @param user + * @param user The user request to put into the request tree. * * @return User instance. * @@ -119,6 +116,21 @@ public interface UserPersistence<T extends Principal> User<T> getUser(T userID) throws UserNotFoundException, TransientException, AccessControlException; + + /** + * Get the user specified by userID whose account is pending approval. + * + * @param userID The userID. + * + * @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. + */ + User<T> getPendingUser(T userID) + throws UserNotFoundException, TransientException, + AccessControlException; /** * Attempt to login the specified user. @@ -132,14 +144,14 @@ public interface UserPersistence<T extends Principal> * @throws TransientException If an temporary, unexpected problem occurred. * @throws AccessControlException If the operation is not permitted. */ - Boolean loginUser(String userID, String password) + Boolean doLogin(String userID, String password) throws UserNotFoundException, TransientException, AccessControlException; /** * Updated the user specified by User. * - * @param user + * @param user The user instance to modify. * * @return User instance. * @@ -163,37 +175,4 @@ public interface UserPersistence<T extends Principal> void deleteUser(T userID) throws UserNotFoundException, TransientException, AccessControlException; - - /** - * Get all groups the user specified by userID belongs to. - * - * @param userID The userID. - * @param isAdmin return only admin Groups when true, else return non-admin - * Groups. - * - * @return Collection of group DN. - * - * @throws UserNotFoundException when the user is not found. - * @throws TransientException If an temporary, unexpected problem occurred. - * @throws AccessControlException If the operation is not permitted. - */ - Collection<DN> getUserGroups(T userID, boolean isAdmin) - throws UserNotFoundException, TransientException, - AccessControlException; - - /** - * Check whether the user is a member of the group. - * - * @param userID The userID. - * @param groupID The groupID. - * - * @return true or false - * - * @throws UserNotFoundException If the user is not found. - * @throws TransientException If an temporary, unexpected problem occurred. - * @throws AccessControlException If the operation is not permitted. - */ - boolean isMember(T userID, String groupID) - throws UserNotFoundException, TransientException, - AccessControlException; } 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 726b5f94cfda210c83e26d7f46327d29268f1baa..71ddf32316e6de250ab5ef5b9a9c2afdb26657b6 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 @@ -77,32 +77,14 @@ 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; -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.*; 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; +import java.util.*; public class LdapGroupDAO<T extends Principal> extends LdapDAO { @@ -323,49 +305,47 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO * * @throws TransientException If an temporary, unexpected problem occurred. */ - public Collection<String> getGroupNames() - throws TransientException + public Collection<String> getGroupNames() throws TransientException { try { - Filter filter = Filter.createPresenceFilter("cn"); - String [] attributes = new String[] {"cn", "nsaccountlock"}; - - SearchRequest searchRequest = - new SearchRequest(config.getGroupsDN(), - SearchScope.SUB, filter, attributes); - - SearchResult searchResult = null; - try - { - searchResult = getConnection().search(searchRequest); - } - catch (LDAPSearchException e) + final Filter filter = Filter.createPresenceFilter("cn"); + final String [] attributes = new String[] {"cn", "nsaccountlock"}; + final Collection<String> groupNames = new ArrayList<String>(); + final long begin = System.currentTimeMillis(); + + final SearchResult searchResult = + getConnection().search(new SearchResultListener() { - if (e.getResultCode() == ResultCode.NO_SUCH_OBJECT) + @Override + public void searchEntryReturned( + final SearchResultEntry searchEntry) { - logger.debug("Could not find groups root", e); - throw new IllegalStateException("Could not find groups root"); + groupNames.add(searchEntry.getAttributeValue("cn")); } - } - - LdapDAO.checkLdapResult(searchResult.getResultCode()); - List<String> groupNames = new ArrayList<String>(); - for (SearchResultEntry next : searchResult.getSearchEntries()) - { - if (!next.hasAttribute("nsaccountlock")) + + @Override + public void searchReferenceReturned( + final SearchResultReference searchReference) { - groupNames.add(next.getAttributeValue("cn")); + } - } - + }, config.getGroupsDN(), SearchScope.ONE, filter, attributes); + + LdapDAO.checkLdapResult(searchResult.getResultCode()); + long end = System.currentTimeMillis(); + + logger.info("<-- groupNames in " + ((new Long(end).doubleValue() + - new Long(begin).doubleValue()) + / 1000.0) + " seconds."); return groupNames; } catch (LDAPException e1) { logger.debug("getGroupNames Exception: " + e1, e1); LdapDAO.checkLdapResult(e1.getResultCode()); - throw new IllegalStateException("Unexpected exception: " + e1.getMatchedDN(), e1); + throw new IllegalStateException("Unexpected exception: " + + e1.getMatchedDN(), e1); } } @@ -492,7 +472,7 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO User<X500Principal> owner; try { - owner = userPersist.getMember(groupOwner); + owner = userPersist.getX500User(groupOwner); } catch (UserNotFoundException e) { @@ -524,7 +504,7 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO User<X500Principal> user; try { - user = userPersist.getMember(memberDN); + user = userPersist.getX500User(memberDN); } catch (UserNotFoundException e) { @@ -992,9 +972,9 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO } Group group = new Group(searchResult.getAttributeValue("cn"), - userPersist.getMember( - new DN(searchResult.getAttributeValue( - "owner")))); + userPersist.getX500User( + new DN(searchResult.getAttributeValue( + "owner")))); group.description = searchResult.getAttributeValue("description"); return group; } @@ -1096,7 +1076,7 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO try { User<X500Principal> subjectUser = - userPersist.getMember(getSubjectDN()); + userPersist.getX500User(getSubjectDN()); if (subjectUser.equals(owner)) { return true; diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupPersistence.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupPersistence.java index f59bc1518d82c3522bf0cd104bc3ca8fecfc7ebf..e66dc2e5960f289be4050c3d87429b0a3f93c38d 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupPersistence.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupPersistence.java @@ -249,4 +249,12 @@ public class LdapGroupPersistence<T extends Principal> } } + public boolean isMember(T userID, String groupID) + throws UserNotFoundException, TransientException, + AccessControlException + { + return (new LdapUserPersistence<T>()).isMember(userID, groupID); + } + + } 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 2bf4a1d06b7c42e454569b6b7bd9b234d1f4e345..3340db29ed0bf544ae4937855a0c1d9b2471f956 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 @@ -127,6 +127,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO // Returned User attributes protected static final String LDAP_OBJECT_CLASS = "objectClass"; + protected static final String LDAP_INET_USER = "inetuser"; protected static final String LDAP_INET_ORG_PERSON = "inetOrgPerson"; protected static final String LDAP_CADC_ACCOUNT = "cadcaccount"; protected static final String LDAP_NSACCOUNTLOCK = "nsaccountlock"; @@ -150,7 +151,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO { LDAP_FIRST_NAME, LDAP_LAST_NAME, LDAP_ADDRESS, LDAP_CITY, LDAP_COUNTRY, - LDAP_EMAIL, LDAP_INSTITUTE, LDAP_UID + LDAP_EMAIL, LDAP_INSTITUTE }; private String[] memberAttribs = new String[] { @@ -189,7 +190,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO * @throws TransientException * @throws UserNotFoundException */ - public Boolean loginUser(final String username, final String password) + public Boolean doLogin(final String username, final String password) throws TransientException, UserNotFoundException { try @@ -208,7 +209,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO } catch (LDAPException e) { - logger.debug("loginUser Exception: " + e, e); + logger.debug("doLogin Exception: " + e, e); if (e.getResultCode() == ResultCode.INVALID_CREDENTIALS) { @@ -362,11 +363,12 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO 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, userRequest - .getPassword()); + addAttribute(attributes, LADP_USER_PASSWORD, new String(userRequest + .getPassword())); addAttribute(attributes, LDAP_NUMERICID, String.valueOf(genNextNumericId())); for (Principal princ : user.getIdentities()) @@ -414,7 +416,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO * * @param userID The userID. * @return User instance. - * @throws UserNotFoundException when the user is not found. + * @throws UserNotFoundException when the user is not found in the main tree. * @throws TransientException If an temporary, unexpected problem occurred. * @throws AccessControlException If the operation is not permitted. */ @@ -425,6 +427,23 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO return getUser(userID, config.getUsersDN()); } + /** + * Obtain a user who is awaiting approval. + * + * @param userID The user ID of the pending user. + * @return A User instance awaiting approval. + * + * @throws UserNotFoundException when the user is not found in the user request tree. + * @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 + { + return getUser(userID, config.getUserRequestsDN()); + } + /** * Get the user specified by userID. @@ -447,7 +466,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO "Unsupported principal type " + userID.getClass()); } - searchField = "(&(objectclass=inetorgperson)(" + + searchField = "(&(objectclass=inetorgperson)(objectclass=cadcaccount)(" + searchField + "=" + userID.getName() + "))"; logger.debug(searchField); @@ -697,7 +716,8 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO } /** - * Get all groups the user specified by userID belongs to. + * Get all groups the user specified by userID belongs to. This method is created + * to provide optimization for the LDAP server. * * @param userID The userID. * @param isAdmin @@ -706,7 +726,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO * @throws TransientException If an temporary, unexpected problem occurred., e.getMessage( * @throws AccessControlException If the operation is not permitted. */ - public Collection<DN> getUserGroups(final T userID, final boolean isAdmin) + protected Collection<DN> getUserGroups(final T userID, final boolean isAdmin) throws UserNotFoundException, TransientException, AccessControlException { @@ -773,7 +793,8 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO } /** - * Check whether the user is a member of the group. + * Check whether the user is a member of the group. This method is created + * to provide optimization for the LDAP server. * * @param userID The userID. * @param groupID The groupID. @@ -832,7 +853,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO * @throws UserNotFoundException * @throws LDAPException */ - User<X500Principal> getMember(DN userDN) + User<X500Principal> getX500User(DN userDN) throws UserNotFoundException, LDAPException { Filter filter = 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 05aedbac0b4c6e4eaae1f4cfbd1e09b7ebcf568f..6a042cc3785193c354f28626a785e803c8190f88 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 @@ -134,8 +134,7 @@ public class LdapUserPersistence<T extends Principal> try { userDAO = new LdapUserDAO<T>(this.config); - User<T> ret = userDAO.addUser(user); - return ret; + return userDAO.addUser(user); } finally { @@ -164,8 +163,36 @@ public class LdapUserPersistence<T extends Principal> try { userDAO = new LdapUserDAO<T>(this.config); - User<T> ret = userDAO.getUser(userID); - return ret; + return userDAO.getUser(userID); + } + finally + { + if (userDAO != null) + { + userDAO.close(); + } + } + } + + /** + * Get the user specified by userID whose account is pending approval. + * + * @param userID The userID. + * @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. + */ + @Override + public User<T> getPendingUser(final T userID) throws UserNotFoundException, + TransientException, + AccessControlException + { + LdapUserDAO<T> userDAO = null; + try + { + userDAO = new LdapUserDAO<T>(this.config); + return userDAO.getPendingUser(userID); } finally { @@ -187,14 +214,14 @@ public class LdapUserPersistence<T extends Principal> * @throws TransientException If an temporary, unexpected problem occurred. * @throws AccessControlException If the operation is not permitted. */ - public Boolean loginUser(String userID, String password) + public Boolean doLogin(String userID, String password) throws UserNotFoundException, TransientException, AccessControlException { LdapUserDAO<T> userDAO = null; try { userDAO = new LdapUserDAO<T>(this.config); - return userDAO.loginUser(userID, password); + return userDAO.doLogin(userID, password); } finally { @@ -204,11 +231,11 @@ public class LdapUserPersistence<T extends Principal> } } } - + /** * Updated the user specified by User. * - * @param user + * @param user The user to update. * * @return User instance. * @@ -224,8 +251,35 @@ public class LdapUserPersistence<T extends Principal> try { userDAO = new LdapUserDAO<T>(this.config); - User<T> ret = userDAO.modifyUser(user); - return ret; + return userDAO.modifyUser(user); + } + finally + { + if (userDAO != null) + { + userDAO.close(); + } + } + } + + /** + * 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 + { + LdapUserDAO<T> userDAO = null; + try + { + userDAO = new LdapUserDAO<T>(this.config); + userDAO.setPassword(user, oldPassword, newPassword); } finally { @@ -265,7 +319,8 @@ public class LdapUserPersistence<T extends Principal> } /** - * Get all groups the user specified by userID belongs to. + * Get all groups the user specified by userID belongs to. This method is created + * to provide optimization for the LDAP server. * * @param userID The userID. * @param isAdmin return only admin Groups when true, else return non-admin @@ -277,15 +332,14 @@ public class LdapUserPersistence<T extends Principal> * @throws TransientException If an temporary, unexpected problem occurred. * @throws AccessControlException If the operation is not permitted. */ - public Collection<DN> getUserGroups(T userID, boolean isAdmin) + Collection<DN> getUserGroups(T userID, boolean isAdmin) throws UserNotFoundException, TransientException, AccessControlException { LdapUserDAO<T> userDAO = null; try { userDAO = new LdapUserDAO<T>(this.config); - Collection<DN> ret = userDAO.getUserGroups(userID, isAdmin); - return ret; + return userDAO.getUserGroups(userID, isAdmin); } finally { @@ -297,7 +351,8 @@ public class LdapUserPersistence<T extends Principal> } /** - * Check whether the user is a member of the group. + * Check whether the user is a member of the group. This method is created + * to provide optimization for the LDAP server. * * @param userID The userID. * @param groupID The groupID. @@ -308,7 +363,7 @@ public class LdapUserPersistence<T extends Principal> * @throws TransientException If an temporary, unexpected problem occurred. * @throws AccessControlException If the operation is not permitted. */ - public boolean isMember(T userID, String groupID) + boolean isMember(T userID, String groupID) throws UserNotFoundException, TransientException, AccessControlException { @@ -316,8 +371,7 @@ public class LdapUserPersistence<T extends Principal> try { userDAO = new LdapUserDAO<T>(this.config); - boolean ret = userDAO.isMember(userID, groupID); - return ret; + return userDAO.isMember(userID, groupID); } finally { @@ -327,5 +381,4 @@ public class LdapUserPersistence<T extends Principal> } } } - } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/SyncOutput.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/SyncOutput.java new file mode 100644 index 0000000000000000000000000000000000000000..9ebd42f75c00d63f1ccc05a6cee320bb8e3b6d7f --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/SyncOutput.java @@ -0,0 +1,127 @@ +/* +************************************************************************ +******************* CANADIAN ASTRONOMY DATA CENTRE ******************* +************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +* +* (c) 2011. (c) 2011. +* Government of Canada Gouvernement du Canada +* National Research Council Conseil national de recherches +* Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +* All rights reserved Tous droits réservés +* +* NRC disclaims any warranties, Le CNRC dénie toute garantie +* expressed, implied, or énoncée, implicite ou légale, +* statutory, of any kind with de quelque nature que ce +* respect to the software, soit, concernant le logiciel, +* including without limitation y compris sans restriction +* any warranty of merchantability toute garantie de valeur +* or fitness for a particular marchande ou de pertinence +* purpose. NRC shall not be pour un usage particulier. +* liable in any event for any Le CNRC ne pourra en aucun cas +* damages, whether direct or être tenu responsable de tout +* indirect, special or general, dommage, direct ou indirect, +* consequential or incidental, particulier ou général, +* arising from the use of the accessoire ou fortuit, résultant +* software. Neither the name de l'utilisation du logiciel. Ni +* of the National Research le nom du Conseil National de +* Council of Canada nor the Recherches du Canada ni les noms +* names of its contributors may de ses participants ne peuvent +* be used to endorse or promote être utilisés pour approuver ou +* products derived from this promouvoir les produits dérivés +* software without specific prior de ce logiciel sans autorisation +* written permission. préalable et particulière +* par écrit. +* +* This file is part of the Ce fichier fait partie du projet +* OpenCADC project. OpenCADC. +* +* OpenCADC is free software: OpenCADC est un logiciel libre ; +* you can redistribute it and/or vous pouvez le redistribuer ou le +* modify it under the terms of modifier suivant les termes de +* the GNU Affero General Public la “GNU Affero General Public +* License as published by the License” telle que publiée +* Free Software Foundation, par la Free Software Foundation +* either version 3 of the : soit la version 3 de cette +* License, or (at your option) licence, soit (à votre gré) +* any later version. toute version ultérieure. +* +* OpenCADC is distributed in the OpenCADC est distribué +* hope that it will be useful, dans l’espoir qu’il vous +* but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +* without even the implied GARANTIE : sans même la garantie +* warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +* or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +* PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +* General Public License for Générale Publique GNU Affero +* more details. pour plus de détails. +* +* You should have received Vous devriez avoir reçu une +* a copy of the GNU Affero copie de la Licence Générale +* General Public License along Publique GNU Affero avec +* with OpenCADC. If not, see OpenCADC ; si ce n’est +* <http://www.gnu.org/licenses/>. pas le cas, consultez : +* <http://www.gnu.org/licenses/>. +* +* $Revision: 5 $ +* +************************************************************************ +*/ + +package ca.nrc.cadc.ac.server.web; + +import java.io.IOException; +import java.io.PrintWriter; +import javax.servlet.http.HttpServletResponse; +import org.apache.log4j.Logger; + +/** + * + * @author majorb + */ +public class SyncOutput +{ + private static final Logger log = Logger.getLogger(SyncOutput.class); + + protected HttpServletResponse response; + protected PrintWriter writer; + + public SyncOutput(HttpServletResponse response) + { + this.response = response; + } + + public boolean isOpen() + { + return (writer != null); + } + + public void setCode(int code) + { + if (writer != null) + return; + + response.setStatus(code); + } + + public void setHeader(String key, Object value) + { + if (writer != null) + return; + + if (value == null) + response.setHeader(key, null); + else + response.setHeader(key, value.toString()); + } + + public PrintWriter getWriter() + throws IOException + { + if (writer == null) + { + log.debug("opening writer"); + writer = response.getWriter(); + } + return writer; + } +} diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/WebUtil.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/WebUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..9a19dcff8360b26c255a0744f195d66a5526ab1b --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/WebUtil.java @@ -0,0 +1,100 @@ +/* + ************************************************************************ + ******************* CANADIAN ASTRONOMY DATA CENTRE ******************* + ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** + * + * (c) 2014. (c) 2014. + * Government of Canada Gouvernement du Canada + * National Research Council Conseil national de recherches + * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 + * All rights reserved Tous droits réservés + * + * NRC disclaims any warranties, Le CNRC dénie toute garantie + * expressed, implied, or énoncée, implicite ou légale, + * statutory, of any kind with de quelque nature que ce + * respect to the software, soit, concernant le logiciel, + * including without limitation y compris sans restriction + * any warranty of merchantability toute garantie de valeur + * or fitness for a particular marchande ou de pertinence + * purpose. NRC shall not be pour un usage particulier. + * liable in any event for any Le CNRC ne pourra en aucun cas + * damages, whether direct or être tenu responsable de tout + * indirect, special or general, dommage, direct ou indirect, + * consequential or incidental, particulier ou général, + * arising from the use of the accessoire ou fortuit, résultant + * software. Neither the name de l'utilisation du logiciel. Ni + * of the National Research le nom du Conseil National de + * Council of Canada nor the Recherches du Canada ni les noms + * names of its contributors may de ses participants ne peuvent + * be used to endorse or promote être utilisés pour approuver ou + * products derived from this promouvoir les produits dérivés + * software without specific prior de ce logiciel sans autorisation + * written permission. préalable et particulière + * par écrit. + * + * This file is part of the Ce fichier fait partie du projet + * OpenCADC project. OpenCADC. + * + * OpenCADC is free software: OpenCADC est un logiciel libre ; + * you can redistribute it and/or vous pouvez le redistribuer ou le + * modify it under the terms of modifier suivant les termes de + * the GNU Affero General Public la “GNU Affero General Public + * License as published by the License” telle que publiée + * Free Software Foundation, par la Free Software Foundation + * either version 3 of the : soit la version 3 de cette + * License, or (at your option) licence, soit (à votre gré) + * any later version. toute version ultérieure. + * + * OpenCADC is distributed in the OpenCADC est distribué + * hope that it will be useful, dans l’espoir qu’il vous + * but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE + * without even the implied GARANTIE : sans même la garantie + * warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ + * or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF + * PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence + * General Public License for Générale Publique GNU Affero + * more details. pour plus de détails. + * + * You should have received Vous devriez avoir reçu une + * a copy of the GNU Affero copie de la Licence Générale + * General Public License along Publique GNU Affero avec + * with OpenCADC. If not, see OpenCADC ; si ce n’est + * <http://www.gnu.org/licenses/>. pas le cas, consultez : + * <http://www.gnu.org/licenses/>. + * + * $Revision: 4 $ + * + ************************************************************************ + */ + +package ca.nrc.cadc.ac.server.web; + +import ca.nrc.cadc.util.StringUtil; + +/** + * Utility methods for the ac web classes. + */ +public class WebUtil +{ + public static String[] getPathSegments(String path) + { + String[] segments = new String[0]; + if (path == null) + { + return segments; + } + if (path.startsWith("/")) + { + path = path.substring(1); + } + if (path.endsWith("/")) + { + path = path.substring(0, path.length() - 1); + } + if (StringUtil.hasText(path)) + { + segments = path.split("/"); + } + return segments; + } +} diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/ACSearchRunner.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/ACSearchRunner.java index a6409ad49a03dfa8167385d66256577d3ae235f3..f576ec6ba47de6cf4cff2ee3e8fb394d142e3a32 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/ACSearchRunner.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/ACSearchRunner.java @@ -74,7 +74,7 @@ import ca.nrc.cadc.ac.UserNotFoundException; import ca.nrc.cadc.ac.server.GroupPersistence; import ca.nrc.cadc.ac.server.PluginFactory; import ca.nrc.cadc.ac.server.RequestValidator; -import ca.nrc.cadc.ac.xml.GroupsWriter; +import ca.nrc.cadc.ac.xml.GroupListWriter; import ca.nrc.cadc.auth.AuthenticationUtil; import ca.nrc.cadc.auth.HttpPrincipal; import ca.nrc.cadc.net.TransientException; @@ -236,7 +236,8 @@ public class ACSearchRunner implements JobRunner groups = new ArrayList<Group>(); } syncOut.setResponseCode(HttpServletResponse.SC_OK); - GroupsWriter.write(groups, syncOut.getOutputStream()); + GroupListWriter groupListWriter = new GroupListWriter(); + groupListWriter.write(groups, syncOut.getOutputStream()); // Mark the Job as completed. // jobUpdater.setPhase(job.getID(), ExecutionPhase.EXECUTING, diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GroupsAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/AbstractGroupAction.java similarity index 86% rename from projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GroupsAction.java rename to projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/AbstractGroupAction.java index 4ef1811573d47b135823e0e584ae9b2ace14b720..2805eda54b4e7bebfe5f0fc719c84085651f6dfd 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GroupsAction.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/AbstractGroupAction.java @@ -76,6 +76,7 @@ import java.security.PrivilegedExceptionAction; import java.util.List; import javax.security.auth.Subject; +import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; @@ -88,47 +89,42 @@ import ca.nrc.cadc.ac.UserNotFoundException; import ca.nrc.cadc.ac.server.GroupPersistence; import ca.nrc.cadc.ac.server.PluginFactory; import ca.nrc.cadc.ac.server.UserPersistence; +import ca.nrc.cadc.ac.server.web.SyncOutput; import ca.nrc.cadc.net.TransientException; -public abstract class GroupsAction - implements PrivilegedExceptionAction<Object> +public abstract class AbstractGroupAction implements PrivilegedExceptionAction<Object> { - private static final Logger log = Logger.getLogger(GroupsAction.class); + private static final Logger log = Logger.getLogger(AbstractGroupAction.class); protected GroupLogInfo logInfo; - protected HttpServletResponse response; + protected HttpServletRequest request; + protected SyncOutput syncOut; - GroupsAction(GroupLogInfo logInfo) + public AbstractGroupAction() + { + } + + abstract void doAction() throws Exception; + + void setLogInfo(GroupLogInfo logInfo) { this.logInfo = logInfo; } - public void doAction(Subject subject, HttpServletResponse response) - throws IOException + void setHttpServletRequest(HttpServletRequest request) + { + this.request = request; + } + + void setSyncOut(SyncOutput syncOut) + { + this.syncOut = syncOut; + } + + public Object run() throws PrivilegedActionException { try { - try - { - this.response = response; - - if (subject == null) - { - run(); - } - else - { - Subject.doAs(subject, this); - } - } - catch (PrivilegedActionException e) - { - Throwable cause = e.getCause(); - if (cause != null) - { - throw cause; - } - throw e; - } + doAction(); } catch (AccessControlException e) { @@ -201,30 +197,29 @@ public abstract class GroupsAction log.error(message, t); sendError(500, message); } + return null; } private void sendError(int responseCode) - throws IOException { sendError(responseCode, null); } private void sendError(int responseCode, String message) - throws IOException { - if (!this.response.isCommitted()) + syncOut.setHeader("Content-Type", "text/plain"); + if (message != null) { - this.response.setContentType("text/plain"); - if (message != null) + try { - this.response.getWriter().write(message); + syncOut.getWriter() .write(message); + } + catch (IOException e) + { + log.warn("Could not write error message to output stream"); } - this.response.setStatus(responseCode); - } - else - { - log.warn("Could not send error " + responseCode + " (" + message + ") because the response is already committed."); } + syncOut.setCode(responseCode); } <T extends Principal> GroupPersistence<T> getGroupPersistence() diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/AddGroupMemberAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/AddGroupMemberAction.java index 61669fa27d74b9f372b10fe30c4225c1e63d6a6b..0f5d204b5a0d8d70845f6ec58241e49d2a3f3008 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/AddGroupMemberAction.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/AddGroupMemberAction.java @@ -74,21 +74,20 @@ import ca.nrc.cadc.ac.server.GroupPersistence; import java.util.ArrayList; import java.util.List; -public class AddGroupMemberAction extends GroupsAction +public class AddGroupMemberAction extends AbstractGroupAction { private final String groupName; private final String groupMemberName; - AddGroupMemberAction(GroupLogInfo logInfo, String groupName, + AddGroupMemberAction(String groupName, String groupMemberName) { - super(logInfo); + super(); this.groupName = groupName; this.groupMemberName = groupMemberName; } - public Object run() - throws Exception + public void doAction() throws Exception { GroupPersistence groupPersistence = getGroupPersistence(); Group group = groupPersistence.getGroup(this.groupName); @@ -102,7 +101,6 @@ public class AddGroupMemberAction extends GroupsAction List<String> addedMembers = new ArrayList<String>(); addedMembers.add(toAdd.getID()); logGroupInfo(group.getID(), null, addedMembers); - return null; } } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/AddUserMemberAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/AddUserMemberAction.java index cdf6093abea691a7412e1fd0a4a6bacd36c12cd4..30c4b8be94e9931f4e5b073bcddde315ccffcc98 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/AddUserMemberAction.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/AddUserMemberAction.java @@ -77,24 +77,23 @@ import java.security.Principal; import java.util.ArrayList; import java.util.List; -public class AddUserMemberAction extends GroupsAction +public class AddUserMemberAction extends AbstractGroupAction { private final String groupName; private final String userID; private final String userIDType; - AddUserMemberAction(GroupLogInfo logInfo, String groupName, String userID, + AddUserMemberAction(String groupName, String userID, String userIDType) { - super(logInfo); + super(); this.groupName = groupName; this.userID = userID; this.userIDType = userIDType; } @SuppressWarnings("unchecked") - public Object run() - throws Exception + public void doAction() throws Exception { GroupPersistence groupPersistence = getGroupPersistence(); Group group = groupPersistence.getGroup(this.groupName); @@ -104,13 +103,12 @@ public class AddUserMemberAction extends GroupsAction { throw new MemberAlreadyExistsException(); } - + groupPersistence.modifyGroup(group); List<String> addedMembers = new ArrayList<String>(); addedMembers.add(toAdd.getUserID().getName()); logGroupInfo(group.getID(), null, addedMembers); - return null; } } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/CreateGroupAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/CreateGroupAction.java index f282d722627e25796756e8921ae77ca2fb4f3940..a4341c40aa82975b1aebf363794f30dc1a00d95c 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/CreateGroupAction.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/CreateGroupAction.java @@ -78,24 +78,25 @@ import ca.nrc.cadc.ac.server.GroupPersistence; import ca.nrc.cadc.ac.xml.GroupReader; import ca.nrc.cadc.ac.xml.GroupWriter; -public class CreateGroupAction extends GroupsAction +public class CreateGroupAction extends AbstractGroupAction { private final InputStream inputStream; - CreateGroupAction(GroupLogInfo logInfo, InputStream inputStream) + CreateGroupAction(InputStream inputStream) { - super(logInfo); + super(); this.inputStream = inputStream; } - public Object run() - throws Exception + public void doAction() throws Exception { GroupPersistence groupPersistence = getGroupPersistence(); - Group group = GroupReader.read(this.inputStream); + GroupReader groupReader = new GroupReader(); + Group group = groupReader.read(this.inputStream); Group newGroup = groupPersistence.addGroup(group); - this.response.setContentType("application/xml"); - GroupWriter.write(newGroup, this.response.getOutputStream()); + syncOut.setHeader("Content-Type", "application/xml"); + GroupWriter groupWriter = new GroupWriter(); + groupWriter.write(newGroup, syncOut.getWriter()); List<String> addedMembers = null; if ((newGroup.getUserMembers().size() > 0) || (newGroup.getGroupMembers().size() > 0)) @@ -111,7 +112,6 @@ public class CreateGroupAction extends GroupsAction } } logGroupInfo(newGroup.getID(), null, addedMembers); - return null; } } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/DeleteGroupAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/DeleteGroupAction.java index 2c96f279f30a5108de5be505761094a2c4e5bf9a..52928fbd95aa5c2cffe90c663d41a1ed4b55ce51 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/DeleteGroupAction.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/DeleteGroupAction.java @@ -74,18 +74,17 @@ import ca.nrc.cadc.ac.Group; import ca.nrc.cadc.ac.User; import ca.nrc.cadc.ac.server.GroupPersistence; -public class DeleteGroupAction extends GroupsAction +public class DeleteGroupAction extends AbstractGroupAction { private final String groupName; - DeleteGroupAction(GroupLogInfo logInfo, String groupName) + DeleteGroupAction(String groupName) { - super(logInfo); + super(); this.groupName = groupName; } - public Object run() - throws Exception + public void doAction() throws Exception { GroupPersistence groupPersistence = getGroupPersistence(); Group deletedGroup = groupPersistence.getGroup(this.groupName); @@ -102,7 +101,6 @@ public class DeleteGroupAction extends GroupsAction this.logInfo.deletedMembers.add(usr.getUserID().getName()); } } - return null; } } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GetGroupAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GetGroupAction.java index 3d7d9646f6692d46f3c76e2943702a7d55707bb2..990411864d359c02b8c5edb78c80e7b41a6a5ade 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GetGroupAction.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GetGroupAction.java @@ -71,24 +71,23 @@ import ca.nrc.cadc.ac.Group; import ca.nrc.cadc.ac.server.GroupPersistence; import ca.nrc.cadc.ac.xml.GroupWriter; -public class GetGroupAction extends GroupsAction +public class GetGroupAction extends AbstractGroupAction { private final String groupName; - GetGroupAction(GroupLogInfo logInfo, String groupName) + GetGroupAction( String groupName) { - super(logInfo); + super(); this.groupName = groupName; } - public Object run() - throws Exception + public void doAction() throws Exception { GroupPersistence groupPersistence = getGroupPersistence(); Group group = groupPersistence.getGroup(this.groupName); - this.response.setContentType("application/xml"); - GroupWriter.write(group, this.response.getOutputStream()); - return null; + syncOut.setHeader("Content-Type", "application/xml"); + GroupWriter groupWriter = new GroupWriter(); + groupWriter.write(group, syncOut.getWriter()); } } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GetGroupNamesAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GetGroupNamesAction.java index a62ef9526d1ff961f6f9b0a88ea82283762f061c..ff26ddd8d19de845b6d6b7cc502f18f96c14b2a8 100644 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GetGroupNamesAction.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GetGroupNamesAction.java @@ -76,25 +76,24 @@ import org.apache.log4j.Logger; import ca.nrc.cadc.ac.server.GroupPersistence; -public class GetGroupNamesAction extends GroupsAction +public class GetGroupNamesAction extends AbstractGroupAction { - + private static final Logger log = Logger.getLogger(GetGroupNamesAction.class); - GetGroupNamesAction(GroupLogInfo logInfo) + GetGroupNamesAction() { - super(logInfo); + super(); } - public Object run() - throws Exception + public void doAction() throws Exception { GroupPersistence groupPersistence = getGroupPersistence(); Collection<String> groups = groupPersistence.getGroupNames(); log.debug("Found " + groups.size() + " group names"); - response.setContentType("text/plain"); + syncOut.setHeader("Content-Type", "text/plain"); log.debug("Set content-type to text/plain"); - Writer writer = response.getWriter(); + Writer writer = syncOut.getWriter(); boolean start = true; for (final String group : groups) { @@ -105,7 +104,5 @@ public class GetGroupNamesAction extends GroupsAction writer.write(group); start = false; } - - return null; } } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GroupLogInfo.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GroupLogInfo.java index 38739a0849e2755fdcd6c42503a9e402a3cae8dd..7840104fdeb406edfeac5be1999a37916f8361bd 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GroupLogInfo.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GroupLogInfo.java @@ -72,6 +72,10 @@ import ca.nrc.cadc.log.ServletLogInfo; import java.util.List; import javax.servlet.http.HttpServletRequest; +/** + * Extension of regular servlet log info that tracks + * group membership changes. + */ public class GroupLogInfo extends ServletLogInfo { public String groupID; diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GroupsServlet.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GroupServlet.java similarity index 75% rename from projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GroupsServlet.java rename to projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GroupServlet.java index cd4682325e14892bdb73c8cd96c7ed1782368730..096b5827a25ad73b5efcb91427879d0c3cd28943 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GroupsServlet.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GroupServlet.java @@ -69,6 +69,7 @@ package ca.nrc.cadc.ac.server.web.groups; import java.io.IOException; +import java.security.PrivilegedActionException; import javax.security.auth.Subject; import javax.servlet.http.HttpServlet; @@ -77,16 +78,24 @@ import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; +import ca.nrc.cadc.ac.server.web.SyncOutput; import ca.nrc.cadc.auth.AuthenticationUtil; +import ca.nrc.cadc.util.StringUtil; -public class GroupsServlet extends HttpServlet +/** + * Servlet for handling all requests to /groups + * + * @author majorb + */ +public class GroupServlet extends HttpServlet { - private static final Logger log = Logger.getLogger(GroupsServlet.class); + private static final long serialVersionUID = 7854660717655869213L; + private static final Logger log = Logger.getLogger(GroupServlet.class); /** * Create a GroupAction and run the action safely. */ - private void doAction(HttpServletRequest request, HttpServletResponse response) + private void doAction(GroupsActionFactory factory, HttpServletRequest request, HttpServletResponse response) throws IOException { long start = System.currentTimeMillis(); @@ -96,14 +105,44 @@ public class GroupsServlet extends HttpServlet log.info(logInfo.start()); Subject subject = AuthenticationUtil.getSubject(request); logInfo.setSubject(subject); - GroupsAction action = GroupsActionFactory.getGroupsAction(request, logInfo); - action.doAction(subject, response); + + AbstractGroupAction action = factory.createAction(request); + + action.setLogInfo(logInfo); + action.setHttpServletRequest(request); + SyncOutput syncOut = new SyncOutput(response); + action.setSyncOut(syncOut); + + try + { + if (subject == null) + { + action.run(); + } + else + { + Subject.doAs(subject, action); + } + } + catch (PrivilegedActionException e) + { + Throwable cause = e.getCause(); + if (cause != null) + { + throw cause; + } + Exception exception = e.getException(); + if (exception != null) + { + throw exception; + } + throw e; + } } catch (IllegalArgumentException e) { log.debug(e.getMessage(), e); logInfo.setMessage(e.getMessage()); - logInfo.setSuccess(false); response.getWriter().write(e.getMessage()); response.setStatus(400); } @@ -124,38 +163,38 @@ public class GroupsServlet extends HttpServlet } @Override - public void doGet(HttpServletRequest request, HttpServletResponse response) + public void doGet(final HttpServletRequest request, HttpServletResponse response) throws IOException { - doAction(request, response); + doAction(GroupsActionFactory.httpGetFactory(), request, response); } @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { - doAction(request, response); + doAction(GroupsActionFactory.httpPostFactory(), request, response); } @Override public void doDelete(HttpServletRequest request, HttpServletResponse response) throws IOException { - doAction(request, response); + doAction(GroupsActionFactory.httpDeleteFactory(), request, response); } @Override public void doPut(HttpServletRequest request, HttpServletResponse response) throws IOException { - doAction(request, response); + doAction(GroupsActionFactory.httpPutFactory(), request, response); } @Override public void doHead(HttpServletRequest request, HttpServletResponse response) throws IOException { - doAction(request, response); + doAction(GroupsActionFactory.httpHeadFactory(), request, response); } } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GroupsActionFactory.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GroupsActionFactory.java index c2aaf942be82e190f33b7f9e1f7cb40aa6fafe97..5cf7a054c70568d75fdddfa964a2a6334eb1c401 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GroupsActionFactory.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/GroupsActionFactory.java @@ -76,126 +76,206 @@ import javax.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; +import ca.nrc.cadc.ac.server.web.WebUtil; import ca.nrc.cadc.util.StringUtil; -public class GroupsActionFactory +/** + * This class provides static methods for each of the http methods for + * creating a factory object that will in turn create the correct group + * action. + * + * @author majorb + */ +public abstract class GroupsActionFactory { private static final Logger log = Logger.getLogger(GroupsActionFactory.class); - static GroupsAction getGroupsAction(HttpServletRequest request, GroupLogInfo logInfo) - throws IOException - { - GroupsAction action = null; - String method = request.getMethod(); - String path = request.getPathInfo(); - log.debug("method: " + method); - log.debug("path: " + path); - - if (path == null) - { - path = ""; - } + public abstract AbstractGroupAction createAction(HttpServletRequest request) + throws IllegalArgumentException, IOException; - if (path.startsWith("/")) + public static GroupsActionFactory httpGetFactory() + { + return new GroupsActionFactory() { - path = path.substring(1); - } + public AbstractGroupAction createAction(HttpServletRequest request) + throws IllegalArgumentException, IOException + { + AbstractGroupAction action = null; + String path = request.getPathInfo(); + log.debug("path: " + path); - if (path.endsWith("/")) - { - path = path.substring(0, path.length() - 1); - } + String[] segments = WebUtil.getPathSegments(path); - String[] segments = new String[0]; - if (StringUtil.hasText(path)) - { - segments = path.split("/"); - } + if (segments.length == 0) + { + action = new GetGroupNamesAction(); + } + else if (segments.length == 1) + { + String groupName = segments[0]; + action = new GetGroupAction(groupName); + } - if (segments.length == 0) - { - if (method.equals("GET")) - { - action = new GetGroupNamesAction(logInfo); - } - else if (method.equals("PUT")) - { - action = new CreateGroupAction(logInfo, request.getInputStream()); + if (action != null) + { + log.debug("Returning action: " + action.getClass()); + return action; + } + throw new IllegalArgumentException("Bad GET request to " + path); } + }; + } - } - else if (segments.length == 1) + public static GroupsActionFactory httpPutFactory() + { + return new GroupsActionFactory() { - String groupName = segments[0]; - if (method.equals("GET")) - { - action = new GetGroupAction(logInfo, groupName); - } - else if (method.equals("DELETE")) + public AbstractGroupAction createAction(HttpServletRequest request) + throws IllegalArgumentException, IOException { - action = new DeleteGroupAction(logInfo, groupName); - } - else if (method.equals("POST")) - { - final URL requestURL = new URL(request.getRequestURL().toString()); - final StringBuilder sb = new StringBuilder(); - sb.append(requestURL.getProtocol()); - sb.append("://"); - sb.append(requestURL.getHost()); - if (requestURL.getPort() > 0) + AbstractGroupAction action = null; + String path = request.getPathInfo(); + log.debug("path: " + path); + + String[] segments = WebUtil.getPathSegments(path); + + if (segments.length == 0) { - sb.append(":"); - sb.append(requestURL.getPort()); + action = new CreateGroupAction(request.getInputStream()); + } + else if (segments.length == 3) + { + String groupName = segments[0]; + String memberCategory = segments[1]; + if (memberCategory.equals("groupMembers")) + { + String groupMemberName = segments[2]; + action = new AddGroupMemberAction(groupName, groupMemberName); + } + else if (memberCategory.equals("userMembers")) + { + String userMemberID = segments[2]; + String userMemberIDType = request.getParameter("idType"); + action = new AddUserMemberAction(groupName, userMemberID, userMemberIDType); + } } - sb.append(request.getContextPath()); - sb.append(request.getServletPath()); - sb.append("/"); - sb.append(path); - action = new ModifyGroupAction(logInfo, groupName, sb.toString(), - request.getInputStream()); + if (action != null) + { + log.debug("Returning action: " + action.getClass()); + return action; + } + throw new IllegalArgumentException("Bad PUT request to " + path); } - } - else if (segments.length == 3) + }; + } + + public static GroupsActionFactory httpPostFactory() + { + return new GroupsActionFactory() { - String groupName = segments[0]; - String memberCategory = segments[1]; - if (method.equals("PUT")) + public AbstractGroupAction createAction(HttpServletRequest request) + throws IllegalArgumentException, IOException { - if (memberCategory.equals("groupMembers")) + AbstractGroupAction action = null; + String path = request.getPathInfo(); + log.debug("path: " + path); + + String[] segments = WebUtil.getPathSegments(path); + + if (segments.length == 1) { - String groupMemberName = segments[2]; - action = new AddGroupMemberAction(logInfo, groupName, groupMemberName); + + + String groupName = segments[0]; + + final URL requestURL = new URL(request.getRequestURL().toString()); + final StringBuilder sb = new StringBuilder(); + sb.append(requestURL.getProtocol()); + sb.append("://"); + sb.append(requestURL.getHost()); + if (requestURL.getPort() > 0) + { + sb.append(":"); + sb.append(requestURL.getPort()); + } + sb.append(request.getContextPath()); + sb.append(request.getServletPath()); + sb.append("/"); + sb.append(path); + + action = new ModifyGroupAction(groupName, sb.toString(), request.getInputStream()); } - else if (memberCategory.equals("userMembers")) + + if (action != null) { - String userMemberID = URLDecoder.decode(segments[2], "UTF-8"); - String userMemberIDType = request.getParameter("idType"); - action = new AddUserMemberAction(logInfo, groupName, userMemberID, userMemberIDType); + log.debug("Returning action: " + action.getClass()); + return action; } + throw new IllegalArgumentException("Bad POST request to " + path); } - else if (method.equals("DELETE")) + }; + + } + + public static GroupsActionFactory httpDeleteFactory() + { + return new GroupsActionFactory() + { + public AbstractGroupAction createAction(HttpServletRequest request) + throws IllegalArgumentException, IOException { - if (memberCategory.equals("groupMembers")) + AbstractGroupAction action = null; + String path = request.getPathInfo(); + log.debug("path: " + path); + + String[] segments = WebUtil.getPathSegments(path); + + if (segments.length == 1) { - String groupMemberName = segments[2]; - action = new RemoveGroupMemberAction(logInfo, groupName, groupMemberName); + String groupName = segments[0]; + action = new DeleteGroupAction(groupName); } - else if (memberCategory.equals("userMembers")) + else if (segments.length == 3) + { + String groupName = segments[0]; + String memberCategory = segments[1]; + + if (memberCategory.equals("groupMembers")) + { + String groupMemberName = segments[2]; + action = new RemoveGroupMemberAction(groupName, groupMemberName); + } + else if (memberCategory.equals("userMembers")) + { + String memberUserID = segments[2]; + String memberUserIDType = request.getParameter("idType"); + action = new RemoveUserMemberAction(groupName, memberUserID, memberUserIDType); + } + } + + if (action != null) { - String memberUserID = URLDecoder.decode(segments[2], "UTF-8"); - String memberUserIDType = request.getParameter("idType"); - action = new RemoveUserMemberAction(logInfo, groupName, memberUserID, memberUserIDType); + log.debug("Returning action: " + action.getClass()); + return action; } + throw new IllegalArgumentException("Bad DELETE request to " + path); } - } + }; - if (action != null) - { - log.debug("Returning action: " + action.getClass()); - return action; - } - throw new IllegalArgumentException("Bad groups request: " + method + " on " + path); } + public static GroupsActionFactory httpHeadFactory() + { + return new GroupsActionFactory() + { + public AbstractGroupAction createAction(HttpServletRequest request) + throws IllegalArgumentException, IOException + { + // http head not supported + throw new UnsupportedOperationException(); + } + }; + + } } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/ModifyGroupAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/ModifyGroupAction.java index 444e335dc3594ec7543872a5f77db25ef0cc4c32..f4094251a8e57c4f7a351ff40b12d357157df1ab 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/ModifyGroupAction.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/ModifyGroupAction.java @@ -77,26 +77,25 @@ import ca.nrc.cadc.ac.User; import ca.nrc.cadc.ac.server.GroupPersistence; import ca.nrc.cadc.ac.xml.GroupReader; -public class ModifyGroupAction extends GroupsAction +public class ModifyGroupAction extends AbstractGroupAction { private final String groupName; private final String request; private final InputStream inputStream; - ModifyGroupAction(GroupLogInfo logInfo, String groupName, - final String request, InputStream inputStream) + ModifyGroupAction(String groupName, final String request, InputStream inputStream) { - super(logInfo); + super(); this.groupName = groupName; this.request = request; this.inputStream = inputStream; } - public Object run() - throws Exception + public void doAction() throws Exception { GroupPersistence groupPersistence = getGroupPersistence(); - Group group = GroupReader.read(this.inputStream); + GroupReader groupReader = new GroupReader(); + Group group = groupReader.read(this.inputStream); Group oldGroup = groupPersistence.getGroup(this.groupName); groupPersistence.modifyGroup(group); @@ -134,9 +133,8 @@ public class ModifyGroupAction extends GroupsAction } logGroupInfo(group.getID(), deletedMembers, addedMembers); - this.response.sendRedirect(request); - - return null; + syncOut.setHeader("Location", "/" + group.getID()); + syncOut.setCode(303); } } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/RemoveGroupMemberAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/RemoveGroupMemberAction.java index a05d17f93d73a061e96bb44975b3f68548b3b7c5..e1b5848bdcab28c79d103972de9aab461568e82b 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/RemoveGroupMemberAction.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/RemoveGroupMemberAction.java @@ -74,20 +74,19 @@ import ca.nrc.cadc.ac.server.GroupPersistence; import java.util.ArrayList; import java.util.List; -public class RemoveGroupMemberAction extends GroupsAction +public class RemoveGroupMemberAction extends AbstractGroupAction { private final String groupName; private final String groupMemberName; - RemoveGroupMemberAction(GroupLogInfo logInfo, String groupName, String groupMemberName) + RemoveGroupMemberAction(String groupName, String groupMemberName) { - super(logInfo); + super(); this.groupName = groupName; this.groupMemberName = groupMemberName; } - public Object run() - throws Exception + public void doAction() throws Exception { GroupPersistence groupPersistence = getGroupPersistence(); Group group = groupPersistence.getGroup(this.groupName); @@ -101,7 +100,6 @@ public class RemoveGroupMemberAction extends GroupsAction List<String> deletedMembers = new ArrayList<String>(); deletedMembers.add(toRemove.getID()); logGroupInfo(group.getID(), deletedMembers, null); - return null; } } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/RemoveUserMemberAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/RemoveUserMemberAction.java index 20dcf8b4a32af6119d4033ea5b72db0389218ba1..d04fe4a6cfe0172eeb574caa82c92ce750e80c53 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/RemoveUserMemberAction.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/groups/RemoveUserMemberAction.java @@ -77,23 +77,22 @@ import java.security.Principal; import java.util.ArrayList; import java.util.List; -public class RemoveUserMemberAction extends GroupsAction +public class RemoveUserMemberAction extends AbstractGroupAction { private final String groupName; private final String userID; private final String userIDType; - RemoveUserMemberAction(GroupLogInfo logInfo, String groupName, String userID, String userIDType) + RemoveUserMemberAction(String groupName, String userID, String userIDType) { - super(logInfo); + super(); this.groupName = groupName; this.userID = userID; this.userIDType = userIDType; } @SuppressWarnings("unchecked") - public Object run() - throws Exception + public void doAction() throws Exception { GroupPersistence groupPersistence = getGroupPersistence(); Group group = groupPersistence.getGroup(this.groupName); @@ -108,7 +107,6 @@ public class RemoveUserMemberAction extends GroupsAction List<String> deletedMembers = new ArrayList<String>(); deletedMembers.add(toRemove.getUserID().getName()); logGroupInfo(group.getID(), deletedMembers, null); - return null; } } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UsersAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/AbstractUserAction.java similarity index 68% rename from projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UsersAction.java rename to projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/AbstractUserAction.java index df6880b92f0ab5c5bf2116e956b3d88bfc7c5798..07a83782a467cf199f1106d3a21df5481fa67561 100644 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UsersAction.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/AbstractUserAction.java @@ -72,65 +72,75 @@ import ca.nrc.cadc.ac.PersonalDetails; import ca.nrc.cadc.ac.User; import ca.nrc.cadc.ac.UserNotFoundException; import ca.nrc.cadc.ac.UserRequest; +import ca.nrc.cadc.ac.json.JsonUserListWriter; +import ca.nrc.cadc.ac.json.JsonUserReader; +import ca.nrc.cadc.ac.json.JsonUserRequestReader; +import ca.nrc.cadc.ac.json.JsonUserWriter; import ca.nrc.cadc.ac.server.PluginFactory; import ca.nrc.cadc.ac.server.UserPersistence; +import ca.nrc.cadc.ac.server.web.SyncOutput; +import ca.nrc.cadc.auth.AuthenticationUtil; +import ca.nrc.cadc.ac.xml.UserListWriter; +import ca.nrc.cadc.ac.xml.UserReader; +import ca.nrc.cadc.ac.xml.UserRequestReader; +import ca.nrc.cadc.ac.xml.UserWriter; import ca.nrc.cadc.net.TransientException; import org.apache.log4j.Logger; -import javax.security.auth.Subject; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.io.Writer; import java.security.AccessControlException; import java.security.Principal; -import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; +import java.util.Iterator; import java.util.Map; +import java.util.Set; -public abstract class UsersAction - implements PrivilegedExceptionAction<Object> +public abstract class AbstractUserAction implements PrivilegedExceptionAction<Object> { - private static final Logger log = Logger.getLogger(UsersAction.class); + private static final Logger log = Logger.getLogger(AbstractUserAction.class); static final String DEFAULT_CONTENT_TYPE = "text/xml"; static final String JSON_CONTENT_TYPE = "application/json"; + protected String augmentUserDN; protected UserLogInfo logInfo; - protected HttpServletResponse response; + protected SyncOutput syncOut; + protected String acceptedContentType = DEFAULT_CONTENT_TYPE; - UsersAction(UserLogInfo logInfo) + AbstractUserAction() + { + } + + public abstract void doAction() throws Exception; + + public void setAugmentUserDN(final String dn) + { + this.augmentUserDN = dn; + } + + public String getAugmentUserDN() + { + return this.augmentUserDN; + } + + public void setLogInfo(UserLogInfo logInfo) { this.logInfo = logInfo; } - public void doAction(Subject subject, HttpServletResponse response) - throws IOException + public void setSyncOut(SyncOutput syncOut) + { + this.syncOut = syncOut; + } + + public Object run() throws IOException { try { - try - { - this.response = response; - - if (subject == null) - { - run(); - } - else - { - Subject.doAs(subject, this); - } - } - catch (PrivilegedActionException e) - { - Throwable cause = e.getCause(); - if (cause != null) - { - throw cause; - } - throw e; - } + doAction(); } catch (AccessControlException e) { @@ -175,6 +185,7 @@ public abstract class UsersAction log.error(message, t); sendError(500, message); } + return null; } private void sendError(int responseCode) @@ -184,21 +195,20 @@ public abstract class UsersAction } private void sendError(int responseCode, String message) - throws IOException { - if (!this.response.isCommitted()) + syncOut.setHeader("Content-Type", "text/plain"); + if (message != null) { - this.response.setContentType("text/plain"); - if (message != null) + try { - this.response.getWriter().write(message); + syncOut.getWriter() .write(message); + } + catch (IOException e) + { + log.warn("Could not write error message to output stream"); } - this.response.setStatus(responseCode); - } - else - { - log.warn("Could not send error " + responseCode + " (" + message + ") because the response is already committed."); } + syncOut.setCode(responseCode); } @SuppressWarnings("unchecked") @@ -233,12 +243,13 @@ public abstract class UsersAction if (acceptedContentType.equals(DEFAULT_CONTENT_TYPE)) { - userRequest = ca.nrc.cadc.ac.xml.UserRequestReader.read(inputStream); + UserRequestReader requestReader = new UserRequestReader(); + userRequest = requestReader.read(inputStream); } else if (acceptedContentType.equals(JSON_CONTENT_TYPE)) { - userRequest = - ca.nrc.cadc.ac.json.UserRequestReader.read(inputStream); + JsonUserRequestReader requestReader = new JsonUserRequestReader(); + userRequest = requestReader.read(inputStream); } else { @@ -250,6 +261,40 @@ public abstract class UsersAction return userRequest; } + /** + * Read the user from the given stream of marshalled data. + * + * @param inputStream The stream to read in. + * @return User instance, never null. + * + * @throws IOException Any errors in reading the stream. + */ + protected final User<Principal> readUser(final InputStream inputStream) + throws IOException + { + syncOut.setHeader("Content-Type", acceptedContentType); + final User<Principal> user; + + if (acceptedContentType.equals(DEFAULT_CONTENT_TYPE)) + { + UserReader userReader = new UserReader(); + user = userReader.read(inputStream); + } + else if (acceptedContentType.equals(JSON_CONTENT_TYPE)) + { + JsonUserReader userReader = new JsonUserReader(); + user = userReader.read(inputStream); + } + else + { + // Should never happen. + throw new IOException("Unknown content being asked for: " + + acceptedContentType); + } + + return user; + } + /** * Write a user to the response's writer. * @@ -259,16 +304,18 @@ public abstract class UsersAction protected final <T extends Principal> void writeUser(final User<T> user) throws IOException { - response.setContentType(acceptedContentType); - final Writer writer = response.getWriter(); + syncOut.setHeader("Content-Type", acceptedContentType); + final Writer writer = syncOut.getWriter(); if (acceptedContentType.equals(DEFAULT_CONTENT_TYPE)) { - ca.nrc.cadc.ac.xml.UserWriter.write(user, writer); + UserWriter userWriter = new UserWriter(); + userWriter.write(user, writer); } else if (acceptedContentType.equals(JSON_CONTENT_TYPE)) { - ca.nrc.cadc.ac.json.UserWriter.write(user, writer); + JsonUserWriter userWriter = new JsonUserWriter(); + userWriter.write(user, writer); } } @@ -280,16 +327,43 @@ public abstract class UsersAction protected final void writeUsers(final Map<String, PersonalDetails> users) throws IOException { - response.setContentType(acceptedContentType); - final Writer writer = response.getWriter(); + syncOut.setHeader("Content-Type", acceptedContentType); + final Writer writer = syncOut.getWriter(); if (acceptedContentType.equals(DEFAULT_CONTENT_TYPE)) { - ca.nrc.cadc.ac.xml.UsersWriter.write(users, writer); + UserListWriter userListWriter = new UserListWriter(); + userListWriter.write(users, writer); } else if (acceptedContentType.equals(JSON_CONTENT_TYPE)) { - ca.nrc.cadc.ac.json.UsersWriter.write(users, writer); + JsonUserListWriter userListWriter = new JsonUserListWriter(); + userListWriter.write(users, writer); + } + } + + void redirectGet(User<?> user) throws Exception + { + final Set<Principal> httpPrincipals = user.getIdentities(); + + String id = null; + String idType = null; + Iterator<Principal> i = httpPrincipals.iterator(); + Principal next = null; + while (idType == null && i.hasNext()) + { + next = i.next(); + idType = AuthenticationUtil.getPrincipalType(next); + id = next.getName(); } + + if (idType == null) + { + throw new IllegalStateException("No identities found."); + } + + final String redirectURL = "/" + id + "?idType=" + idType; + syncOut.setHeader("Location", redirectURL); + syncOut.setCode(303); } } 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 d53ad283126b8456164722deabfba261daf877c2..aa40229c9395fbf8eab582749be6fd2ab4c8b690 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 @@ -70,9 +70,7 @@ package ca.nrc.cadc.ac.server.web.users; import java.io.InputStream; -import ca.nrc.cadc.ac.ReaderException; import ca.nrc.cadc.ac.User; -import ca.nrc.cadc.ac.UserAlreadyExistsException; import ca.nrc.cadc.ac.UserRequest; import ca.nrc.cadc.ac.server.UserPersistence; @@ -80,42 +78,25 @@ import javax.servlet.http.HttpServletResponse; import java.security.Principal; -public class CreateUserAction extends UsersAction +public class CreateUserAction extends AbstractUserAction { private final InputStream inputStream; - CreateUserAction(UserLogInfo logInfo, InputStream inputStream) + CreateUserAction(final InputStream inputStream) { - super(logInfo); + super(); this.inputStream = inputStream; } - public Object run() - throws Exception - { - try - { - final UserPersistence<Principal> userPersistence = - getUserPersistence(); - final UserRequest<Principal> userRequest = - readUserRequest(this.inputStream); - final User<Principal> newUser = - userPersistence.addUser(userRequest); - writeUser(newUser); - logUserInfo(newUser.getUserID().getName()); - } - catch (UserAlreadyExistsException e) - { - response.setStatus(HttpServletResponse.SC_CONFLICT); - response.getWriter().write("User already exists"); - } - catch (ReaderException e) - { - throw new IllegalArgumentException("Invalid input", e); - } + public void doAction() throws Exception + { + final UserPersistence<Principal> userPersistence = getUserPersistence(); + final UserRequest<Principal> userRequest = readUserRequest(this.inputStream); + final User<Principal> newUser = userPersistence.addUser(userRequest); - return null; + syncOut.setCode(201); + logUserInfo(newUser.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 806e8f9812bec8751246ef1f7f8a84b8081a2d29..aa74d299c1798e2799a66e60606a3def3097cc78 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 @@ -72,23 +72,21 @@ import ca.nrc.cadc.ac.User; import ca.nrc.cadc.ac.server.UserPersistence; import java.security.Principal; -public class DeleteUserAction extends UsersAction +public class DeleteUserAction extends AbstractUserAction { private final Principal userID; - DeleteUserAction(UserLogInfo logInfo, Principal userID) + DeleteUserAction(Principal userID) { - super(logInfo); + super(); this.userID = userID; } - public Object run() - throws Exception + public void doAction() throws Exception { UserPersistence userPersistence = getUserPersistence(); User<? extends Principal> deletedUser = userPersistence.getUser(userID); userPersistence.deleteUser(deletedUser.getUserID()); - return null; } } 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 d4ee1d0efe03a6bf8fecc24790caa7e0636f07e4..4793c719fb078488473eaca1bbb215c17a9a2aac 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 @@ -68,27 +68,88 @@ */package ca.nrc.cadc.ac.server.web.users; import ca.nrc.cadc.ac.User; +import ca.nrc.cadc.ac.UserNotFoundException; import ca.nrc.cadc.ac.server.UserPersistence; +import java.security.AccessControlContext; +import java.security.AccessController; import java.security.Principal; +import java.security.PrivilegedExceptionAction; +import javax.security.auth.Subject; -public class GetUserAction extends UsersAction +import org.apache.log4j.Logger; + + +public class GetUserAction extends AbstractUserAction { + private static final Logger log = Logger.getLogger(GetUserAction.class); private final Principal userID; - GetUserAction(UserLogInfo logInfo, Principal userID) + GetUserAction(Principal userID) { - super(logInfo); + super(); this.userID = userID; } - public Object run() throws Exception + public void doAction() throws Exception { - UserPersistence<Principal> userPersistence = getUserPersistence(); - User<Principal> user = userPersistence.getUser(userID); + User<Principal> user; + + if (isServops()) + { + Subject subject = new Subject(); + subject.getPrincipals().add(this.userID); + user = (User<Principal>) Subject.doAs(subject, new PrivilegedExceptionAction<Object>() + { + @Override + public Object run() throws Exception + { + return getUser(userID); + } + + }); + } + else + { + user = getUser(this.userID); + } + writeUser(user); - return null; } + protected User<Principal> getUser(Principal principal) throws Exception + { + final UserPersistence<Principal> userPersistence = getUserPersistence(); + User<Principal> user; + + try + { + user = userPersistence.getUser(principal); + } + catch (UserNotFoundException e) + { + user = userPersistence.getPendingUser(principal); + } + + return user; + } + + protected boolean isServops() + { + log.debug("alinga-- isServops(): augmentUserDN = " + this.augmentUserDN); + boolean isServops = false; + AccessControlContext acc = AccessController.getContext(); + Subject subject = Subject.getSubject(acc); + for (Principal principal : subject.getPrincipals()) + { + if (principal.getName().equals(this.getAugmentUserDN())) + { + isServops = true; + break; + } + } + + return isServops; + } } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/GetUsersAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/GetUserListAction.java similarity index 94% rename from projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/GetUsersAction.java rename to projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/GetUserListAction.java index 008a8572ec167b146db84497e82df94e4d95aee0..c601bd33737758fa0739e6ed6064c16392cc1cde 100644 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/GetUsersAction.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/GetUserListAction.java @@ -75,22 +75,18 @@ import org.apache.log4j.Logger; import ca.nrc.cadc.ac.server.UserPersistence; -public class GetUsersAction extends UsersAction +public class GetUserListAction extends AbstractUserAction { - - private static final Logger log = Logger.getLogger(GetUsersAction.class); - GetUsersAction(UserLogInfo logInfo) + private static final Logger log = Logger.getLogger(GetUserListAction.class); + + GetUserListAction() { - super(logInfo); } - public Object run() - throws Exception + public void doAction() throws Exception { final UserPersistence userPersistence = getUserPersistence(); - writeUsers(userPersistence.getUsers()); - return null; } } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/LoginServlet.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/LoginServlet.java index 0b1a4c303ff98c46618cd07640f48daa9ba6b84e..f1daa9db4f5c8870590ca10c0698b5cbe55ce33c 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/LoginServlet.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/LoginServlet.java @@ -106,7 +106,7 @@ public class LoginServlet extends HttpServlet { if (StringUtil.hasText(password)) { - if (new LdapUserPersistence().loginUser(userID, password)) + if (new LdapUserPersistence().doLogin(userID, password)) { String token = new SSOCookieManager().generate(new HttpPrincipal(userID)); response.setContentType(CONTENT_TYPE); @@ -135,9 +135,10 @@ public class LoginServlet extends HttpServlet catch (AccessControlException e) { log.debug(e.getMessage(), e); - logInfo.setMessage(e.getMessage()); + String message = "Invalid credentials"; + logInfo.setMessage(message); response.setContentType(CONTENT_TYPE); - response.getWriter().write(e.getMessage()); + response.getWriter().write(message); response.setStatus(401); } catch (Throwable t) diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/ModifyUserAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/ModifyUserAction.java index c98c29683542a64d608bcaf623dc7bbfdfb13125..4e7ebe372ba2a3c0feb149274bf8bbfcbb38b58f 100644 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/ModifyUserAction.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/ModifyUserAction.java @@ -68,41 +68,53 @@ */ package ca.nrc.cadc.ac.server.web.users; -import java.io.InputStream; import ca.nrc.cadc.ac.User; import ca.nrc.cadc.ac.server.UserPersistence; -import ca.nrc.cadc.ac.xml.UserReader; +import ca.nrc.cadc.auth.AuthenticationUtil; +import ca.nrc.cadc.auth.HttpPrincipal; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; import java.security.Principal; +import java.util.Iterator; +import java.util.Set; + -public class ModifyUserAction extends UsersAction +public class ModifyUserAction extends AbstractUserAction { - private final Principal userID; - private final String request; private final InputStream inputStream; - ModifyUserAction(UserLogInfo logInfo, Principal userID, - final String request, InputStream inputStream) + + ModifyUserAction(final InputStream inputStream) { - super(logInfo); - this.userID = userID; - this.request = request; + super(); + this.inputStream = inputStream; } - public Object run() - throws Exception - { - UserPersistence userPersistence = getUserPersistence(); - User<? extends Principal> user = UserReader.read(this.inputStream); - User<? extends Principal> oldUser = userPersistence.getUser(userID); - userPersistence.modifyUser(user); - - logUserInfo(user.getUserID().getName()); - this.response.sendRedirect(request); + public void doAction() throws Exception + { + final User<Principal> user = readUser(this.inputStream); + final User<Principal> modifiedUser = modifyUser(user); + logUserInfo(modifiedUser.getUserID().getName()); - return null; + redirectGet(modifiedUser); } + /** + * Perform the modification at the persistence level. + * + * @param user The user to modify. + * @param <T> The ID (Principal) type. + * @return The modified User. + * @throws Exception Any problems during update. + */ + <T extends Principal> User<T> modifyUser(final User<T> user) + throws Exception + { + final UserPersistence<T> userPersistence = getUserPersistence(); + return userPersistence.modifyUser(user); + } } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/PasswordServlet.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/PasswordServlet.java new file mode 100644 index 0000000000000000000000000000000000000000..5d07ea7147d9581fe140c98956454362652f750e --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/PasswordServlet.java @@ -0,0 +1,179 @@ +/* + ************************************************************************ + ******************* CANADIAN ASTRONOMY DATA CENTRE ******************* + ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** + * + * (c) 2014. (c) 2014. + * Government of Canada Gouvernement du Canada + * National Research Council Conseil national de recherches + * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 + * All rights reserved Tous droits réservés + * + * NRC disclaims any warranties, Le CNRC dénie toute garantie + * expressed, implied, or énoncée, implicite ou légale, + * statutory, of any kind with de quelque nature que ce + * respect to the software, soit, concernant le logiciel, + * including without limitation y compris sans restriction + * any warranty of merchantability toute garantie de valeur + * or fitness for a particular marchande ou de pertinence + * purpose. NRC shall not be pour un usage particulier. + * liable in any event for any Le CNRC ne pourra en aucun cas + * damages, whether direct or être tenu responsable de tout + * indirect, special or general, dommage, direct ou indirect, + * consequential or incidental, particulier ou général, + * arising from the use of the accessoire ou fortuit, résultant + * software. Neither the name de l'utilisation du logiciel. Ni + * of the National Research le nom du Conseil National de + * Council of Canada nor the Recherches du Canada ni les noms + * names of its contributors may de ses participants ne peuvent + * be used to endorse or promote être utilisés pour approuver ou + * products derived from this promouvoir les produits dérivés + * software without specific prior de ce logiciel sans autorisation + * written permission. préalable et particulière + * par écrit. + * + * This file is part of the Ce fichier fait partie du projet + * OpenCADC project. OpenCADC. + * + * OpenCADC is free software: OpenCADC est un logiciel libre ; + * you can redistribute it and/or vous pouvez le redistribuer ou le + * modify it under the terms of modifier suivant les termes de + * the GNU Affero General Public la “GNU Affero General Public + * License as published by the License” telle que publiée + * Free Software Foundation, par la Free Software Foundation + * either version 3 of the : soit la version 3 de cette + * License, or (at your option) licence, soit (à votre gré) + * any later version. toute version ultérieure. + * + * OpenCADC is distributed in the OpenCADC est distribué + * hope that it will be useful, dans l’espoir qu’il vous + * but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE + * without even the implied GARANTIE : sans même la garantie + * warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ + * or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF + * PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence + * General Public License for Générale Publique GNU Affero + * more details. pour plus de détails. + * + * You should have received Vous devriez avoir reçu une + * a copy of the GNU Affero copie de la Licence Générale + * General Public License along Publique GNU Affero avec + * with OpenCADC. If not, see OpenCADC ; si ce n’est + * <http://www.gnu.org/licenses/>. pas le cas, consultez : + * <http://www.gnu.org/licenses/>. + * + * $Revision: 4 $ + * + ************************************************************************ + */ +package ca.nrc.cadc.ac.server.web.users; + +import java.io.IOException; +import java.security.AccessControlException; +import java.util.Set; + +import javax.security.auth.Subject; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; + +import ca.nrc.cadc.ac.User; +import ca.nrc.cadc.ac.server.ldap.LdapUserPersistence; +import ca.nrc.cadc.auth.AuthenticationUtil; +import ca.nrc.cadc.auth.HttpPrincipal; +import ca.nrc.cadc.log.ServletLogInfo; +import ca.nrc.cadc.util.StringUtil; + + +/** + * Servlet to handle password changes. Passwords are an integral part of the + * access control system and are handled differently to accommodate stricter + * guidelines. + * <p/> + * This servlet handles POST only. It relies on the Subject being set higher + * up by the AccessControlFilter as configured in the web descriptor. + */ +public class PasswordServlet extends HttpServlet +{ + private static final Logger log = Logger.getLogger(PasswordServlet.class); + + + /** + * Attempt to change password. + * + * @param request The HTTP Request. + * @param response The HTTP Response. + * @throws IOException Any errors that are not expected. + */ + public void doPost(final HttpServletRequest request, + final HttpServletResponse response) + throws IOException + { + final long start = System.currentTimeMillis(); + final ServletLogInfo logInfo = new ServletLogInfo(request); + log.info(logInfo.start()); + try + { + final Subject subject = AuthenticationUtil.getSubject(request); + if ((subject == null) + || (subject.getPrincipals(HttpPrincipal.class).isEmpty())) + { + logInfo.setMessage("Unauthorized subject"); + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + } + else + { + logInfo.setSubject(subject); + final Set<HttpPrincipal> webPrincipals = + subject.getPrincipals(HttpPrincipal.class); + final User<HttpPrincipal> user = + new User<HttpPrincipal>(webPrincipals.iterator().next()); + String oldPassword = request.getParameter("old_password"); + String newPassword = request.getParameter("new_password"); + if (StringUtil.hasText(oldPassword)) + { + if (StringUtil.hasText(newPassword)) + { + (new LdapUserPersistence<HttpPrincipal>()) + .setPassword(user, oldPassword, newPassword); + } + else + { + throw new IllegalArgumentException("Missing new password"); + } + } + else + { + throw new IllegalArgumentException("Missing old password"); + } + } + } + catch (IllegalArgumentException e) + { + log.debug(e.getMessage(), e); + logInfo.setMessage(e.getMessage()); + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + } + catch (AccessControlException e) + { + log.debug(e.getMessage(), e); + logInfo.setMessage(e.getMessage()); + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + } + catch (Throwable t) + { + String message = "Internal Server Error: " + t.getMessage(); + log.error(message, t); + logInfo.setSuccess(false); + logInfo.setMessage(message); + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + finally + { + logInfo.setElapsedTime(System.currentTimeMillis() - start); + log.info(logInfo.end()); + } + } +} diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UsersActionFactory.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UserActionFactory.java similarity index 56% rename from projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UsersActionFactory.java rename to projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UserActionFactory.java index 37ddf3638cae55e5556f6c10afbeecf00bea82f1..ae8ec41014d2f0ed8d67a7bc50a664c270de1542 100644 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UsersActionFactory.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UserActionFactory.java @@ -70,14 +70,13 @@ package ca.nrc.cadc.ac.server.web.users; import ca.nrc.cadc.ac.IdentityType; import ca.nrc.cadc.ac.User; +import ca.nrc.cadc.ac.server.web.WebUtil; import ca.nrc.cadc.auth.CookiePrincipal; import ca.nrc.cadc.auth.HttpPrincipal; import ca.nrc.cadc.auth.NumericPrincipal; import ca.nrc.cadc.auth.OpenIdPrincipal; -import ca.nrc.cadc.util.StringUtil; import java.io.IOException; -import java.net.URL; import java.security.Principal; import javax.security.auth.x500.X500Principal; import javax.servlet.http.HttpServletRequest; @@ -85,102 +84,150 @@ import javax.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; -public class UsersActionFactory +public abstract class UserActionFactory { - private static final Logger log = Logger - .getLogger(UsersActionFactory.class); + private static final Logger log = Logger.getLogger(UserActionFactory.class); - static UsersAction getUsersAction(HttpServletRequest request, UserLogInfo logInfo) - throws IOException - { - UsersAction action = null; - String method = request.getMethod(); - String path = request.getPathInfo(); - log.debug("method: " + method); - log.debug("path: " + path); + public abstract AbstractUserAction createAction(HttpServletRequest request) + throws IllegalArgumentException, IOException; - if (path == null) + public static UserActionFactory httpGetFactory() + { + return new UserActionFactory() { - path = ""; - } + public AbstractUserAction createAction(HttpServletRequest request) + throws IllegalArgumentException, IOException + { + AbstractUserAction action = null; + String path = request.getPathInfo(); + log.debug("path: " + path); - if (path.startsWith("/")) - { - path = path.substring(1); - } + String[] segments = WebUtil.getPathSegments(path); - if (path.endsWith("/")) - { - path = path.substring(0, path.length() - 1); - } + if (segments.length == 0) + { + action = new GetUserListAction(); + } + else if (segments.length == 1) + { + User user = getUser(segments[0], request.getParameter("idType"), path); + action = new GetUserAction(user.getUserID()); + } - String[] segments = new String[0]; - if (StringUtil.hasText(path)) - { - segments = path.split("/"); - } + if (action != null) + { + log.debug("Returning action: " + action.getClass()); + return action; + } - if (segments.length == 0) - { - if (method.equals("GET")) - { - action = new GetUsersAction(logInfo); - } - else if (method.equals("PUT")) - { - action = new CreateUserAction(logInfo, request - .getInputStream()); + throw new IllegalArgumentException("Bad GET request to " + path); } + }; + } - } - else + public static UserActionFactory httpPutFactory() + { + return new UserActionFactory() { - User user = getUser(segments[0], request.getParameter("idType"), - method, path); - if (method.equals("GET")) + public AbstractUserAction createAction(HttpServletRequest request) + throws IllegalArgumentException, IOException { - action = new GetUserAction(logInfo, user.getUserID()); + AbstractUserAction action = null; + String path = request.getPathInfo(); + log.debug("path: " + path); + + String[] segments = WebUtil.getPathSegments(path); + + if (segments.length == 0) + { + action = new CreateUserAction(request.getInputStream()); + } + + if (action != null) + { + log.debug("Returning action: " + action.getClass()); + return action; + } + + throw new IllegalArgumentException("Bad PUT request to " + path); } - else if (method.equals("DELETE")) + }; + } + + public static UserActionFactory httpPostFactory() + { + return new UserActionFactory() + { + public AbstractUserAction createAction(HttpServletRequest request) + throws IllegalArgumentException, IOException { - action = new DeleteUserAction(logInfo, user.getUserID()); + AbstractUserAction action = null; + String path = request.getPathInfo(); + log.debug("path: " + path); + + String[] segments = WebUtil.getPathSegments(path); + + if (segments.length == 1) + { + action = new ModifyUserAction(request.getInputStream()); + } + + if (action != null) + { + log.debug("Returning action: " + action.getClass()); + return action; + } + + throw new IllegalArgumentException("Bad POST request to " + path); } - else if (method.equals("POST")) + }; + } + + public static UserActionFactory httpDeleteFactory() + { + return new UserActionFactory() + { + public AbstractUserAction createAction(HttpServletRequest request) + throws IllegalArgumentException, IOException { - final URL requestURL = new URL(request.getRequestURL() - .toString()); - final StringBuilder sb = new StringBuilder(); - sb.append(requestURL.getProtocol()); - sb.append("://"); - sb.append(requestURL.getHost()); - if (requestURL.getPort() > 0) + AbstractUserAction action = null; + String path = request.getPathInfo(); + log.debug("path: " + path); + + String[] segments = WebUtil.getPathSegments(path); + + if (segments.length == 1) + { + User user = getUser(segments[0], request.getParameter("idType"), path); + action = new DeleteUserAction(user.getUserID()); + } + + if (action != null) { - sb.append(":"); - sb.append(requestURL.getPort()); + log.debug("Returning action: " + action.getClass()); + return action; } - sb.append(request.getContextPath()); - sb.append(request.getServletPath()); - sb.append("/"); - sb.append(path); - - action = new ModifyUserAction(logInfo, user.getUserID(), sb - .toString(), - request.getInputStream()); + + throw new IllegalArgumentException("Bad DELETE request to " + path); } - } + }; + } - if (action != null) + public static UserActionFactory httpHeadFactory() + { + return new UserActionFactory() { - log.debug("Returning action: " + action.getClass()); - return action; - } - final String error = "Bad users request: " + method + " on " + path; - throw new IllegalArgumentException(error); + public AbstractUserAction createAction(HttpServletRequest request) + throws IllegalArgumentException, IOException + { + // http head not supported + throw new UnsupportedOperationException(); + } + }; } private static User<? extends Principal> getUser(final String userName, final String idType, - final String method, final String path) { if (idType == null || idType.isEmpty()) @@ -210,9 +257,7 @@ public class UsersActionFactory } else { - final String error = "Bad users request: " + method + " on " + path + - " because of unknown principal type " + idType; - throw new IllegalArgumentException(error); + throw new IllegalArgumentException("Unregonized userid"); } } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UsersServlet.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UserServlet.java similarity index 73% rename from projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UsersServlet.java rename to projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UserServlet.java index c3f2e53c75821f6de8d170d5d1a02393196ca316..69a5c20a786b9cf364713c9555fd13a2b195cb60 100644 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UsersServlet.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UserServlet.java @@ -69,27 +69,49 @@ package ca.nrc.cadc.ac.server.web.users; import java.io.IOException; +import java.security.PrivilegedActionException; import javax.security.auth.Subject; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import ca.nrc.cadc.ac.UserAlreadyExistsException; import ca.nrc.cadc.util.StringUtil; + import org.apache.log4j.Logger; +import ca.nrc.cadc.ac.server.web.SyncOutput; import ca.nrc.cadc.auth.AuthenticationUtil; -public class UsersServlet extends HttpServlet +public class UserServlet extends HttpServlet { - private static final Logger log = Logger.getLogger(UsersServlet.class); + private static final long serialVersionUID = 5289130885807305288L; + private static final Logger log = Logger.getLogger(UserServlet.class); + private String augmentUserDN; + + @Override + public void init(final ServletConfig config) throws ServletException + { + super.init(config); + + try + { + this.augmentUserDN = config.getInitParameter(UserServlet.class.getName() + ".augmentUserDN"); + log.info("augmentUserDN: " + augmentUserDN); + } + catch(Exception ex) + { + log.error("failed to init: " + ex); + } + } /** * Create a UserAction and run the action safely. */ - private void doAction(HttpServletRequest request, HttpServletResponse response) + private void doAction(UserActionFactory factory, HttpServletRequest request, HttpServletResponse response) throws IOException { long start = System.currentTimeMillis(); @@ -100,9 +122,40 @@ public class UsersServlet extends HttpServlet log.info(logInfo.start()); Subject subject = AuthenticationUtil.getSubject(request); logInfo.setSubject(subject); - UsersAction action = UsersActionFactory.getUsersAction(request, logInfo); + + AbstractUserAction action = factory.createAction(request); + SyncOutput syncOut = new SyncOutput(response); + + action.setAugmentUserDN(this.augmentUserDN); + action.setLogInfo(logInfo); + action.setSyncOut(syncOut); action.setAcceptedContentType(getAcceptedContentType(request)); - action.doAction(subject, response); + + try + { + if (subject == null) + { + action.run(); + } + else + { + Subject.doAs(subject, action); + } + } + catch (PrivilegedActionException e) + { + Throwable cause = e.getCause(); + if (cause != null) + { + throw cause; + } + Exception exception = e.getException(); + if (exception != null) + { + throw exception; + } + throw e; + } } catch (IllegalArgumentException e) { @@ -132,35 +185,35 @@ public class UsersServlet extends HttpServlet public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { - doAction(request, response); + doAction(UserActionFactory.httpGetFactory(), request, response); } @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { - doAction(request, response); + doAction(UserActionFactory.httpGetFactory(), request, response); } @Override public void doDelete(HttpServletRequest request, HttpServletResponse response) throws IOException { - doAction(request, response); + doAction(UserActionFactory.httpDeleteFactory(), request, response); } @Override public void doPut(HttpServletRequest request, HttpServletResponse response) throws IOException { - doAction(request, response); + doAction(UserActionFactory.httpPutFactory(), request, response); } @Override public void doHead(HttpServletRequest request, HttpServletResponse response) throws IOException { - doAction(request, response); + doAction(UserActionFactory.httpHeadFactory(), request, response); } /** @@ -174,13 +227,13 @@ public class UsersServlet extends HttpServlet final String requestedContentType = request.getHeader("Accept"); if (StringUtil.hasText(requestedContentType) - && requestedContentType.contains(UsersAction.JSON_CONTENT_TYPE)) + && requestedContentType.contains(AbstractUserAction.JSON_CONTENT_TYPE)) { - return UsersAction.JSON_CONTENT_TYPE; + return AbstractUserAction.JSON_CONTENT_TYPE; } else { - return UsersAction.DEFAULT_CONTENT_TYPE; + return AbstractUserAction.DEFAULT_CONTENT_TYPE; } } } diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapDAOTestImpl.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapDAOTestImpl.java index 7d3be479f44fc01e2eaaab7805e645a1dc9f573a..2dd0201455e5fee826af689dc471595545e0669c 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapDAOTestImpl.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapDAOTestImpl.java @@ -70,13 +70,14 @@ package ca.nrc.cadc.ac.server.ldap; import java.security.AccessControlException; +import ca.nrc.cadc.net.TransientException; import com.unboundid.ldap.sdk.LDAPConnection; import com.unboundid.ldap.sdk.LDAPException; public class LdapDAOTestImpl extends LdapDAO { - public LdapDAOTestImpl(LdapConfig config) + public LdapDAOTestImpl(LdapConfig config) throws TransientException { super(config); } 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 2f9bcdf27a8fb962fd5d1645f997975200956706..b5f7b7fc706285aec7404148022f0a4ffae7f2a1 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 @@ -150,7 +150,7 @@ public class LdapGroupDAOTest extends AbstractLdapDAOTest anonSubject.getPrincipals().add(unknownUser.getUserID()); } - LdapGroupDAO<X500Principal> getGroupDAO() + LdapGroupDAO<X500Principal> getGroupDAO() throws Exception { return new LdapGroupDAO<X500Principal>(config, new LdapUserDAO<X500Principal>(config)); 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 78a63a13285e89e87d18806b24dfcbae0c4953f8..cb143e90e8fedc9c87677763f09ac55b3c23b67f 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 @@ -93,11 +93,12 @@ import ca.nrc.cadc.ac.UserDetails; import ca.nrc.cadc.ac.UserRequest; import ca.nrc.cadc.auth.HttpPrincipal; import ca.nrc.cadc.auth.NumericPrincipal; +import ca.nrc.cadc.net.TransientException; import ca.nrc.cadc.util.Log4jInit; import com.unboundid.ldap.sdk.DN; -public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest +public class LdapUserDAOTest extends AbstractLdapDAOTest { private static final Logger log = Logger.getLogger(LdapUserDAOTest.class); @@ -107,9 +108,11 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest static String testUserDN; static User<X500Principal> testUser; static User<X500Principal> testMember; + static User<HttpPrincipal> testPendingUser; static LdapConfig config; static Random ran = new Random(); // source of randomness for numeric ids + @BeforeClass public static void setUpBeforeClass() throws Exception @@ -120,6 +123,17 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest config = getLdapConfig(); X500Principal testUserX500Princ = new X500Principal(testUserX509DN); testUser = new User<X500Principal>(testUserX500Princ); + + testPendingUser = + new User<HttpPrincipal>(new HttpPrincipal("CADCtestRequest")); + testPendingUser.details.add(new PersonalDetails("CADCtest", "Request")); + testPendingUser.getIdentities().add( + new HttpPrincipal("CADCtestRequest")); + testPendingUser.getIdentities().add( + new X500Principal( + "uid=CADCtestRequest,ou=userrequests,ou=ds,dc=testcanfar")); + testPendingUser.getIdentities().add(new NumericPrincipal(66666)); + testUser.details.add(new PersonalDetails("CADC", "DAOTest1")); testUser.getIdentities().add(new HttpPrincipal("CadcDaoTest1")); testUser.getIdentities().add(testUserX500Princ); @@ -136,7 +150,7 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest } - LdapUserDAO getUserDAO() + <T extends Principal> LdapUserDAO<T> getUserDAO() throws Exception { return new LdapUserDAO(config){ protected int genNextNumericId() @@ -146,7 +160,7 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest }; } - String getUserID() + String createUserID() { return "CadcDaoTestUser-" + System.currentTimeMillis(); } @@ -157,7 +171,7 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest @Test public void testAddUser() throws Exception { - String userID = getUserID(); + 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")); @@ -167,15 +181,44 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest expected.details.add(new PersonalDetails("foo", "bar")); final UserRequest<HttpPrincipal> userRequest = - new UserRequest<HttpPrincipal>(expected, "123456"); + new UserRequest<HttpPrincipal>(expected, "123456".toCharArray()); Subject subject = new Subject(); subject.getPrincipals().add(testUser.getUserID()); - User<HttpPrincipal> actual = getUserDAO().addUser(userRequest); + final LdapUserDAO<HttpPrincipal> userDAO = getUserDAO(); + User<HttpPrincipal> actual = userDAO.addUser(userRequest); check(expected, actual); } + @Test + public void testGetPendingUser() throws Exception + { + final Subject subject = new Subject(); + subject.getPrincipals().add(testUser.getUserID()); + + // do everything as owner + Subject.doAs(subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + final LdapUserDAO<HttpPrincipal> userDAO = getUserDAO(); + final User<HttpPrincipal> actual = + userDAO.getPendingUser(testPendingUser.getUserID()); + check(testPendingUser, actual); + + return null; + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + } + }); + } + /** * Test of getUser method, of class LdapUserDAO. */ @@ -188,12 +231,13 @@ public class LdapUserDAOTest<T extends Principal> 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()); + final LdapUserDAO<X500Principal> userDAO = getUserDAO(); + final User<X500Principal> actual = + userDAO.getUser(testUser.getUserID()); check(testUser, actual); return null; @@ -204,7 +248,6 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest } } }); - } /** @@ -301,7 +344,7 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest { try { - User<X500Principal> actual = getUserDAO().getMember(new DN(testUserDN)); + User<X500Principal> actual = getUserDAO().getX500User(new DN(testUserDN)); check(testMember, actual); return null; } @@ -324,7 +367,7 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest { try { - User<X500Principal> actual = getUserDAO().getMember(new DN(testUserDN)); + User<X500Principal> actual = getUserDAO().getX500User(new DN(testUserDN)); check(testMember, actual); return null; } @@ -404,15 +447,16 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest // Create a test user with a known password final User<HttpPrincipal> testUser2; - final String username = getUserID(); - final String password = "foo"; - final String newPassword = "bar"; + final String username = createUserID(); + final char[] password = "foo".toCharArray(); + final char[] newPassword = "bar".toCharArray(); HttpPrincipal principal = new HttpPrincipal(username); testUser2 = new User<HttpPrincipal>(principal); testUser2.getIdentities().add(principal); testUser2.details.add(new PersonalDetails("firstName", "lastName")); - final UserRequest userRequest = new UserRequest(testUser2, password); + final UserRequest<HttpPrincipal> userRequest = + new UserRequest<HttpPrincipal>(testUser2, password); // add the user Subject subject = new Subject(); @@ -424,7 +468,8 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest { try { - return getUserDAO().newUser(userRequest); + final LdapUserDAO<HttpPrincipal> userDAO = getUserDAO(); + return userDAO.newUser(userRequest); } catch (Exception e) { @@ -442,7 +487,7 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest { try { - getUserDAO().loginUser(username, password); + getUserDAO().doLogin(username, String.valueOf(password)); } catch (Exception e) { @@ -460,7 +505,9 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest { try { - getUserDAO().setPassword(testUser2, password, newPassword); + final LdapUserDAO<HttpPrincipal> userDAO = getUserDAO(); + userDAO.setPassword(testUser2, String.valueOf(password), + String.valueOf(newPassword)); fail("should throw exception if subject and user are not the same"); } catch (Exception ignore){} @@ -477,7 +524,9 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest { try { - getUserDAO().setPassword(testUser2, password, newPassword); + final LdapUserDAO<HttpPrincipal> userDAO = getUserDAO(); + userDAO.setPassword(testUser2, String.valueOf(password), + String.valueOf(newPassword)); } catch (Exception e) { @@ -496,7 +545,7 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest { try { - getUserDAO().loginUser(username, password); + getUserDAO().doLogin(username, String.valueOf(password)); } catch (Exception e) { @@ -513,8 +562,8 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest { // Create a test user final User<HttpPrincipal> testUser2; - final String username = getUserID(); - final String password = "foo"; + final String username = createUserID(); + final char[] password = "foo".toCharArray(); HttpPrincipal principal = new HttpPrincipal(username); testUser2 = new User<HttpPrincipal>(principal); @@ -524,7 +573,8 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest nextUserNumericID = ran.nextInt(Integer.MAX_VALUE); testUser2.getIdentities().add(new NumericPrincipal(nextUserNumericID)); testUser2.details.add(new PersonalDetails("firstName", "lastName")); - final UserRequest userRequest = new UserRequest(testUser2, password); + final UserRequest<HttpPrincipal> userRequest = + new UserRequest<HttpPrincipal>(testUser2, password); // add the user Subject subject = new Subject(); @@ -536,7 +586,8 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest { try { - return getUserDAO().newUser(userRequest); + final LdapUserDAO<HttpPrincipal> userDAO = getUserDAO(); + return userDAO.newUser(userRequest); } catch (Exception e) { @@ -569,7 +620,8 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest { try { - getUserDAO().modifyUser(testUser2); + final LdapUserDAO<HttpPrincipal> userDAO = getUserDAO(); + userDAO.modifyUser(testUser2); fail("should throw exception if subject and user are not the same"); } catch (Exception ignore) @@ -589,7 +641,8 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest { try { - return getUserDAO().modifyUser(testUser2); + final LdapUserDAO<HttpPrincipal> userDAO = getUserDAO(); + return userDAO.modifyUser(testUser2); } catch (Exception e) { @@ -603,7 +656,8 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest check(testUser2, updatedUser); } - private static void check(final User<? extends Principal> user1, final User<? extends Principal> user2) + private static void check(final User<? extends Principal> user1, + final User<? extends Principal> user2) { assertEquals(user1, user2); assertEquals(user1.details, user2.details); diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/GroupsActionTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/AbstractGroupActionTest.java similarity index 89% rename from projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/GroupsActionTest.java rename to projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/AbstractGroupActionTest.java index def8852585eaf9d5102a31ede3712bb7214504f0..502e314d2992ee758465b10252986e13cc486220 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/GroupsActionTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/AbstractGroupActionTest.java @@ -91,10 +91,10 @@ import static org.junit.Assert.*; * * @author jburke */ -public class GroupsActionTest +public class AbstractGroupActionTest { - private final static Logger log = Logger.getLogger(GroupsActionTest.class); - + private final static Logger log = Logger.getLogger(AbstractGroupActionTest.class); + @BeforeClass public static void setUpClass() { @@ -109,7 +109,7 @@ public class GroupsActionTest Exception e = new AccessControlException(""); testDoAction(message, responseCode, e); } - + @Test public void testDoActionIllegalArgumentException() throws Exception { @@ -118,7 +118,7 @@ public class GroupsActionTest Exception e = new IllegalArgumentException("message"); testDoAction(message, responseCode, e); } - + @Test public void testDoActionMemberNotFoundException() throws Exception { @@ -127,7 +127,7 @@ public class GroupsActionTest Exception e = new MemberNotFoundException("foo"); testDoAction(message, responseCode, e); } - + @Test public void testDoActionGroupNotFoundException() throws Exception { @@ -136,7 +136,7 @@ public class GroupsActionTest Exception e = new GroupNotFoundException("foo"); testDoAction(message, responseCode, e); } - + @Test public void testDoActionUserNotFoundException() throws Exception { @@ -154,7 +154,7 @@ public class GroupsActionTest Exception e = new MemberAlreadyExistsException("foo"); testDoAction(message, responseCode, e); } - + @Test public void testDoActionGroupAlreadyExistsException() throws Exception { @@ -163,7 +163,7 @@ public class GroupsActionTest Exception e = new GroupAlreadyExistsException("foo"); testDoAction(message, responseCode, e); } - + @Test public void testDoActionUnsupportedOperationException() throws Exception { @@ -172,7 +172,7 @@ public class GroupsActionTest Exception e = new UnsupportedOperationException(); testDoAction(message, responseCode, e); } - + @Test public void testDoActionTransientException() throws Exception { @@ -188,16 +188,9 @@ public class GroupsActionTest EasyMock.expectLastCall().once(); EasyMock.replay(response); - GroupLogInfo logInfo = EasyMock.createMock(GroupLogInfo.class); - logInfo.setSuccess(false); - EasyMock.expectLastCall().once(); - logInfo.setMessage("Internal Transient Error: foo"); - EasyMock.expectLastCall().once(); - EasyMock.replay(logInfo); - - GroupsActionImpl action = new GroupsActionImpl(logInfo); + GroupsActionImpl action = new GroupsActionImpl(); action.setException(new TransientException("foo")); - action.doAction(null, response); + action.doAction(); } catch (Throwable t) { @@ -205,7 +198,7 @@ public class GroupsActionTest fail("unexpected error: " + t.getMessage()); } } - + private void testDoAction(String message, int responseCode, Exception e) throws Exception { @@ -221,14 +214,9 @@ public class GroupsActionTest EasyMock.expectLastCall().once(); EasyMock.replay(response); - GroupLogInfo logInfo = EasyMock.createMock(GroupLogInfo.class); - logInfo.setMessage(message); - EasyMock.expectLastCall().once(); - EasyMock.replay(logInfo); - - GroupsActionImpl action = new GroupsActionImpl(logInfo); + GroupsActionImpl action = new GroupsActionImpl(); action.setException(e); - action.doAction(null, response); + action.doAction(); } catch (Throwable t) { @@ -237,16 +225,16 @@ public class GroupsActionTest } } - public class GroupsActionImpl extends GroupsAction + public class GroupsActionImpl extends AbstractGroupAction { Exception exception; - - public GroupsActionImpl(GroupLogInfo logInfo) + + public GroupsActionImpl() { - super(logInfo); + super(); } - public Object run() throws Exception + public void doAction() throws Exception { throw exception; } @@ -256,5 +244,5 @@ public class GroupsActionTest this.exception = e; } } - + } diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/AddGroupMemberActionTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/AddGroupMemberActionTest.java index 8550e9ba2dfa13797a5da1a34c5a93fcd8261c10..f8075c5abd57eceab1fe478be97bc2060086e3eb 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/AddGroupMemberActionTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/AddGroupMemberActionTest.java @@ -88,7 +88,7 @@ import static org.junit.Assert.*; public class AddGroupMemberActionTest { private final static Logger log = Logger.getLogger(AddGroupMemberActionTest.class); - + @BeforeClass public static void setUpClass() { @@ -103,15 +103,13 @@ public class AddGroupMemberActionTest Group group = new Group("group", null); Group member = new Group("member", null); group.getGroupMembers().add(member); - + final GroupPersistence groupPersistence = createMock(GroupPersistence.class); expect(groupPersistence.getGroup("group")).andReturn(group); expect(groupPersistence.getGroup("member")).andReturn(member); replay(groupPersistence); - - GroupLogInfo logInfo = createMock(GroupLogInfo.class); - - AddGroupMemberAction action = new AddGroupMemberAction(logInfo, "group", "member") + + AddGroupMemberAction action = new AddGroupMemberAction("group", "member") { @Override <T extends Principal> GroupPersistence<T> getGroupPersistence() @@ -119,10 +117,10 @@ public class AddGroupMemberActionTest return groupPersistence; }; }; - + try { - action.run(); + action.doAction(); fail("duplicate group member should throw GroupAlreadyExistsException"); } catch (GroupAlreadyExistsException ignore) {} @@ -133,7 +131,7 @@ public class AddGroupMemberActionTest fail("unexpected error: " + t.getMessage()); } } - + @Test public void testRun() throws Exception { @@ -152,10 +150,8 @@ public class AddGroupMemberActionTest expect(groupPersistence.modifyGroup(group)).andReturn(modified); replay(groupPersistence); - - GroupLogInfo logInfo = createMock(GroupLogInfo.class); - - AddGroupMemberAction action = new AddGroupMemberAction(logInfo, "group", "member") + + AddGroupMemberAction action = new AddGroupMemberAction("group", "member") { @Override <T extends Principal> GroupPersistence<T> getGroupPersistence() @@ -164,7 +160,11 @@ public class AddGroupMemberActionTest }; }; - action.run(); + GroupLogInfo logInfo = createMock(GroupLogInfo.class); + action.setLogInfo(logInfo); + + action.doAction(); + } catch (Throwable t) { @@ -172,5 +172,5 @@ public class AddGroupMemberActionTest fail("unexpected error: " + t.getMessage()); } } - + } diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/AddUserMemberActionTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/AddUserMemberActionTest.java index 1cdb6f4fc1cf397c8388bbb7322fd39cbb845e61..8eae8ace9c01d0fce6d452861e0f61030008e954 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/AddUserMemberActionTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/AddUserMemberActionTest.java @@ -82,6 +82,8 @@ import org.apache.log4j.Logger; import org.easymock.EasyMock; import org.junit.BeforeClass; import org.junit.Test; + +import static org.easymock.EasyMock.createMock; import static org.junit.Assert.*; /** @@ -91,7 +93,7 @@ import static org.junit.Assert.*; public class AddUserMemberActionTest { private final static Logger log = Logger.getLogger(AddUserMemberActionTest.class); - + @BeforeClass public static void setUpClass() { @@ -103,43 +105,42 @@ public class AddUserMemberActionTest public void testExceptions() { try - { + { String userID = "foo"; String userIDType = AuthenticationUtil.AUTH_TYPE_HTTP; Principal userPrincipal = AuthenticationUtil.createPrincipal(userID, userIDType); User<Principal> user = new User<Principal>(userPrincipal); - + Group group = new Group("group", null); group.getUserMembers().add(user); - + final GroupPersistence groupPersistence = EasyMock.createMock(GroupPersistence.class); EasyMock.expect(groupPersistence.getGroup("group")).andReturn(group); EasyMock.replay(groupPersistence); - + final UserPersistence userPersistence = EasyMock.createMock(UserPersistence.class); EasyMock.expect(userPersistence.getUser(userPrincipal)).andReturn(user); EasyMock.replay(userPersistence); - - GroupLogInfo logInfo = EasyMock.createMock(GroupLogInfo.class); - - AddUserMemberAction action = new AddUserMemberAction(logInfo, "group", userID, userIDType) + + + AddUserMemberAction action = new AddUserMemberAction("group", userID, userIDType) { @Override <T extends Principal> GroupPersistence<T> getGroupPersistence() { return groupPersistence; }; - + @Override <T extends Principal> UserPersistence<T> getUserPersistence() { return userPersistence; }; }; - + try { - action.run(); + action.doAction(); fail("duplicate group member should throw MemberAlreadyExistsException"); } catch (MemberAlreadyExistsException ignore) {} @@ -150,7 +151,7 @@ public class AddUserMemberActionTest fail("unexpected error: " + t.getMessage()); } } - + @Test @SuppressWarnings("unchecked") public void testRun() throws Exception @@ -161,38 +162,38 @@ public class AddUserMemberActionTest String userIDType = AuthenticationUtil.AUTH_TYPE_HTTP; Principal userPrincipal = AuthenticationUtil.createPrincipal(userID, userIDType); User<Principal> user = new User<Principal>(userPrincipal); - + Group group = new Group("group", null); Group modified = new Group("group", null); modified.getUserMembers().add(user); - + final GroupPersistence groupPersistence = EasyMock.createMock(GroupPersistence.class); EasyMock.expect(groupPersistence.getGroup("group")).andReturn(group); EasyMock.expect(groupPersistence.modifyGroup(group)).andReturn(modified); EasyMock.replay(groupPersistence); - + final UserPersistence userPersistence = EasyMock.createMock(UserPersistence.class); EasyMock.expect(userPersistence.getUser(userPrincipal)).andReturn(user); EasyMock.replay(userPersistence); - - GroupLogInfo logInfo = EasyMock.createMock(GroupLogInfo.class); - - AddUserMemberAction action = new AddUserMemberAction(logInfo, "group", userID, userIDType) + + AddUserMemberAction action = new AddUserMemberAction("group", userID, userIDType) { @Override <T extends Principal> GroupPersistence<T> getGroupPersistence() { return groupPersistence; }; - + @Override <T extends Principal> UserPersistence<T> getUserPersistence() { return userPersistence; }; }; - - action.run(); + + GroupLogInfo logInfo = createMock(GroupLogInfo.class); + action.setLogInfo(logInfo); + action.doAction(); } catch (Throwable t) { @@ -200,5 +201,5 @@ public class AddUserMemberActionTest fail("unexpected error: " + t.getMessage()); } } - + } diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/DeleteGroupActionTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/DeleteGroupActionTest.java index 0994610208aab34a25f8b521508c6146283df352..ca58a75c3d9760419cb50be1f7c6e5feea82f4fc 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/DeleteGroupActionTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/DeleteGroupActionTest.java @@ -77,6 +77,8 @@ import org.apache.log4j.Logger; import org.easymock.EasyMock; import org.junit.BeforeClass; import org.junit.Test; + +import static org.easymock.EasyMock.createMock; import static org.junit.Assert.*; /** @@ -86,7 +88,7 @@ import static org.junit.Assert.*; public class DeleteGroupActionTest { private final static Logger log = Logger.getLogger(DeleteGroupActionTest.class); - + @BeforeClass public static void setUpClass() { @@ -97,18 +99,16 @@ public class DeleteGroupActionTest public void testRun() { try - { + { Group group = new Group("group", null); - + final GroupPersistence groupPersistence = EasyMock.createMock(GroupPersistence.class); EasyMock.expect(groupPersistence.getGroup("group")).andReturn(group); groupPersistence.deleteGroup("group"); EasyMock.expectLastCall().once(); EasyMock.replay(groupPersistence); - - GroupLogInfo logInfo = EasyMock.createMock(GroupLogInfo.class); - - DeleteGroupAction action = new DeleteGroupAction(logInfo, "group") + + DeleteGroupAction action = new DeleteGroupAction("group") { @Override <T extends Principal> GroupPersistence<T> getGroupPersistence() @@ -117,7 +117,9 @@ public class DeleteGroupActionTest }; }; - action.run(); + GroupLogInfo logInfo = createMock(GroupLogInfo.class); + action.setLogInfo(logInfo); + action.doAction(); } catch (Throwable t) { @@ -125,5 +127,5 @@ public class DeleteGroupActionTest fail("unexpected error: " + t.getMessage()); } } - + } diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/GetGroupNamesActionTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/GetGroupNamesActionTest.java index 1f2d4d67b0f71e4a2734230b8308f04cd27d5353..0ade66ad54e553d496d9df4366ec2698a7130bee 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/GetGroupNamesActionTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/GetGroupNamesActionTest.java @@ -85,6 +85,7 @@ import java.security.Principal; import java.util.ArrayList; import java.util.Collection; +import static org.easymock.EasyMock.createMock; import static org.junit.Assert.fail; /** @@ -134,11 +135,9 @@ public class GetGroupNamesActionTest EasyMock.expectLastCall(); EasyMock.expect(mockResponse.getWriter()).andReturn(mockWriter).once(); - GroupLogInfo mockLog = EasyMock.createMock(GroupLogInfo.class); + EasyMock.replay(mockPersistence, mockWriter, mockResponse); - EasyMock.replay(mockPersistence, mockWriter, mockResponse, mockLog); - - GetGroupNamesAction action = new GetGroupNamesAction(mockLog) + GetGroupNamesAction action = new GetGroupNamesAction() { @Override <T extends Principal> GroupPersistence<T> getGroupPersistence() @@ -147,7 +146,9 @@ public class GetGroupNamesActionTest }; }; - action.run(); + GroupLogInfo logInfo = createMock(GroupLogInfo.class); + action.setLogInfo(logInfo); + action.doAction(); } catch (Throwable t) { diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/GroupActionFactoryTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/GroupActionFactoryTest.java index 3a9b19ccb053c960256ea8c67cd32fe39dac6544..0aad33de8b38c44848aba054f3561874cea02a80 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/GroupActionFactoryTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/GroupActionFactoryTest.java @@ -93,9 +93,8 @@ public class GroupActionFactoryTest { HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); EasyMock.expect(request.getPathInfo()).andReturn("groupName/groupMembers/groupToAdd"); - EasyMock.expect(request.getMethod()).andReturn("PUT"); EasyMock.replay(request); - GroupsAction action = GroupsActionFactory.getGroupsAction(request, null); + AbstractGroupAction action = GroupsActionFactory.httpPutFactory().createAction(request); EasyMock.verify(request); Assert.assertTrue("Wrong action", action instanceof AddGroupMemberAction); } @@ -114,9 +113,8 @@ public class GroupActionFactoryTest HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); EasyMock.expect(request.getPathInfo()).andReturn("groupName/userMembers/userToAdd"); EasyMock.expect(request.getParameter("idType")).andReturn("x509"); - EasyMock.expect(request.getMethod()).andReturn("PUT"); EasyMock.replay(request); - GroupsAction action = GroupsActionFactory.getGroupsAction(request, null); + AbstractGroupAction action = GroupsActionFactory.httpPutFactory().createAction(request); EasyMock.verify(request); Assert.assertTrue("Wrong action", action instanceof AddUserMemberAction); } @@ -134,10 +132,10 @@ public class GroupActionFactoryTest { HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); EasyMock.expect(request.getPathInfo()).andReturn(""); - EasyMock.expect(request.getMethod()).andReturn("PUT"); EasyMock.expect(request.getInputStream()).andReturn(null); EasyMock.replay(request); - GroupsAction action = GroupsActionFactory.getGroupsAction(request, null); + + AbstractGroupAction action = GroupsActionFactory.httpPutFactory().createAction(request); EasyMock.verify(request); Assert.assertTrue("Wrong action", action instanceof CreateGroupAction); } @@ -155,9 +153,9 @@ public class GroupActionFactoryTest { HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); EasyMock.expect(request.getPathInfo()).andReturn("groupName"); - EasyMock.expect(request.getMethod()).andReturn("DELETE"); EasyMock.replay(request); - GroupsAction action = GroupsActionFactory.getGroupsAction(request, null); + + AbstractGroupAction action = GroupsActionFactory.httpDeleteFactory().createAction(request); EasyMock.verify(request); Assert.assertTrue("Wrong action", action instanceof DeleteGroupAction); } @@ -175,9 +173,8 @@ public class GroupActionFactoryTest { HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); EasyMock.expect(request.getPathInfo()).andReturn("groupName"); - EasyMock.expect(request.getMethod()).andReturn("GET"); EasyMock.replay(request); - GroupsAction action = GroupsActionFactory.getGroupsAction(request, null); + AbstractGroupAction action = GroupsActionFactory.httpGetFactory().createAction(request); EasyMock.verify(request); Assert.assertTrue("Wrong action", action instanceof GetGroupAction); } @@ -195,9 +192,8 @@ public class GroupActionFactoryTest { HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); EasyMock.expect(request.getPathInfo()).andReturn(""); - EasyMock.expect(request.getMethod()).andReturn("GET"); EasyMock.replay(request); - GroupsAction action = GroupsActionFactory.getGroupsAction(request, null); + AbstractGroupAction action = GroupsActionFactory.httpGetFactory().createAction(request); EasyMock.verify(request); Assert.assertTrue("Wrong action", action instanceof GetGroupNamesAction); } @@ -218,13 +214,12 @@ public class GroupActionFactoryTest HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); EasyMock.expect(request.getPathInfo()).andReturn("groupName"); - EasyMock.expect(request.getMethod()).andReturn("POST"); EasyMock.expect(request.getRequestURL()).andReturn(sb); EasyMock.expect(request.getContextPath()).andReturn(""); EasyMock.expect(request.getServletPath()).andReturn(""); EasyMock.expect(request.getInputStream()).andReturn(null); EasyMock.replay(request); - GroupsAction action = GroupsActionFactory.getGroupsAction(request, null); + AbstractGroupAction action = GroupsActionFactory.httpPostFactory().createAction(request); EasyMock.verify(request); Assert.assertTrue("Wrong action", action instanceof ModifyGroupAction); } @@ -242,9 +237,8 @@ public class GroupActionFactoryTest { HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); EasyMock.expect(request.getPathInfo()).andReturn("groupName/groupMembers/groupToRenove"); - EasyMock.expect(request.getMethod()).andReturn("DELETE"); EasyMock.replay(request); - GroupsAction action = GroupsActionFactory.getGroupsAction(request, null); + AbstractGroupAction action = GroupsActionFactory.httpDeleteFactory().createAction(request); EasyMock.verify(request); Assert.assertTrue("Wrong action", action instanceof RemoveGroupMemberAction); } @@ -262,10 +256,9 @@ public class GroupActionFactoryTest { HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); EasyMock.expect(request.getPathInfo()).andReturn("groupName/userMembers/userToRemove"); - EasyMock.expect(request.getMethod()).andReturn("DELETE"); EasyMock.expect(request.getParameter("idType")).andReturn("x509"); EasyMock.replay(request); - GroupsAction action = GroupsActionFactory.getGroupsAction(request, null); + AbstractGroupAction action = GroupsActionFactory.httpDeleteFactory().createAction(request); EasyMock.verify(request); Assert.assertTrue("Wrong action", action instanceof RemoveUserMemberAction); } @@ -276,10 +269,7 @@ public class GroupActionFactoryTest } } - @Test - public void testBadRequests() - { - try + /* { TestRequest[] testRequests = { @@ -304,6 +294,151 @@ public class GroupActionFactoryTest new TestRequest("groupName/groupMembers/groupMemberName/tooManySegments", "HEAD"), new TestRequest("groupName/groupMembers/groupMemberName/tooManySegments", "DELETE"), }; + */ + + @Test + public void testBadGetRequests() + { + try + { + TestRequest[] testRequests = + { + new TestRequest("groupName/groupMembers"), + new TestRequest("groupName/misspelled/id"), + new TestRequest("groupName/groupMembers/groupMemberName"), + new TestRequest("groupName/userMembers/userMemberName"), + new TestRequest("groupName/groupMembers/groupMemberName/tooManySegments") + }; + + for (TestRequest testRequest : testRequests) + { + + log.debug("Testing: " + testRequest); + + HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); + EasyMock.expect(request.getPathInfo()).andReturn(testRequest.path); + if (testRequest.paramName != null) + { + EasyMock.expect(request.getParameter(testRequest.paramName)).andReturn(testRequest.paramValue); + } + EasyMock.replay(request); + try + { + GroupsActionFactory.httpGetFactory().createAction(request); + Assert.fail("Should have been a bad request: on " + testRequest.path); + } + catch (IllegalArgumentException e) + { + // expected + } + EasyMock.verify(request); + } + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + Assert.fail("unexpected error: " + t.getMessage()); + } + } + + @Test + public void testBadPutRequests() + { + try + { + TestRequest[] testRequests = + { + new TestRequest("groupName/groupMembers"), + new TestRequest("groupName/groupMembers/groupMemberName/tooManySegments") + }; + + for (TestRequest testRequest : testRequests) + { + + log.debug("Testing: " + testRequest); + + HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); + EasyMock.expect(request.getPathInfo()).andReturn(testRequest.path); + if (testRequest.paramName != null) + { + EasyMock.expect(request.getParameter(testRequest.paramName)).andReturn(testRequest.paramValue); + } + EasyMock.replay(request); + try + { + GroupsActionFactory.httpPutFactory().createAction(request); + Assert.fail("Should have been a bad request: on " + testRequest.path); + } + catch (IllegalArgumentException e) + { + // expected + } + EasyMock.verify(request); + } + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + Assert.fail("unexpected error: " + t.getMessage()); + } + } + + @Test + public void testBadPostRequests() + { + try + { + TestRequest[] testRequests = + { + new TestRequest(""), + new TestRequest("groupName/groupMembers"), + new TestRequest("groupName/groupMembers/groupMemberName"), + new TestRequest("groupName/userMembers/userMemberName"), + new TestRequest("groupName/groupMembers/groupMemberName/tooManySegments") + }; + + for (TestRequest testRequest : testRequests) + { + + log.debug("Testing: " + testRequest); + + HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); + EasyMock.expect(request.getPathInfo()).andReturn(testRequest.path); + if (testRequest.paramName != null) + { + EasyMock.expect(request.getParameter(testRequest.paramName)).andReturn(testRequest.paramValue); + } + EasyMock.replay(request); + try + { + GroupsActionFactory.httpPostFactory().createAction(request); + Assert.fail("Should have been a bad request: on " + testRequest.path); + } + catch (IllegalArgumentException e) + { + // expected + } + EasyMock.verify(request); + } + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + Assert.fail("unexpected error: " + t.getMessage()); + } + } + + @Test + public void testBadDeleteRequests() + { + try + { + TestRequest[] testRequests = + { + new TestRequest(""), + new TestRequest("groupName/groupMembers"), + new TestRequest("groupName/groupMembers/groupMemberName/tooManySegments"), + }; for (TestRequest testRequest : testRequests) { @@ -312,7 +447,6 @@ public class GroupActionFactoryTest HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); EasyMock.expect(request.getPathInfo()).andReturn(testRequest.path); - EasyMock.expect(request.getMethod()).andReturn(testRequest.method); if (testRequest.paramName != null) { EasyMock.expect(request.getParameter(testRequest.paramName)).andReturn(testRequest.paramValue); @@ -320,8 +454,8 @@ public class GroupActionFactoryTest EasyMock.replay(request); try { - GroupsActionFactory.getGroupsAction(request, null); - Assert.fail("Should have been a bad request: " + testRequest.method + " on " + testRequest.path); + GroupsActionFactory.httpDeleteFactory().createAction(request); + Assert.fail("Should have been a bad request: on " + testRequest.path); } catch (IllegalArgumentException e) { @@ -340,25 +474,23 @@ public class GroupActionFactoryTest private class TestRequest { public String path; - public String method; public String paramName; public String paramValue; - public TestRequest(String path, String method) + public TestRequest(String path) { - this(path, method, null, null); + this(path, null, null); } - public TestRequest(String path, String method, String paramName, String paramValue) + public TestRequest(String path, String paramName, String paramValue) { this.path = path; - this.method = method; this.paramName = paramName; this.paramValue = paramValue; } @Override public String toString() { - return method + " on path " + path + + return "paht " + path + ((paramName == null) ? "" : "?" + paramName + "=" + paramValue); } diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/RemoveGroupMemberActionTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/RemoveGroupMemberActionTest.java index 749d0076eed5527337e293ac48f4b11951d54a55..acb8224e91380a5c03e9d024eae0cd3dfa682298 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/RemoveGroupMemberActionTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/RemoveGroupMemberActionTest.java @@ -78,6 +78,8 @@ import org.apache.log4j.Logger; import org.easymock.EasyMock; import org.junit.BeforeClass; import org.junit.Test; + +import static org.easymock.EasyMock.createMock; import static org.junit.Assert.*; /** @@ -87,7 +89,7 @@ import static org.junit.Assert.*; public class RemoveGroupMemberActionTest { private final static Logger log = Logger.getLogger(RemoveGroupMemberActionTest.class); - + @BeforeClass public static void setUpClass() { @@ -101,15 +103,13 @@ public class RemoveGroupMemberActionTest { Group group = new Group("group", null); Group member = new Group("member", null); - + final GroupPersistence groupPersistence = EasyMock.createMock(GroupPersistence.class); EasyMock.expect(groupPersistence.getGroup("group")).andReturn(group); EasyMock.expect(groupPersistence.getGroup("member")).andReturn(member); EasyMock.replay(groupPersistence); - - GroupLogInfo logInfo = EasyMock.createMock(GroupLogInfo.class); - - RemoveGroupMemberAction action = new RemoveGroupMemberAction(logInfo, "group", "member") + + RemoveGroupMemberAction action = new RemoveGroupMemberAction( "group", "member") { @Override <T extends Principal> GroupPersistence<T> getGroupPersistence() @@ -117,10 +117,10 @@ public class RemoveGroupMemberActionTest return groupPersistence; }; }; - + try { - action.run(); + action.doAction(); fail("unknown group member should throw GroupNotFoundException"); } catch (GroupNotFoundException ignore) {} @@ -131,7 +131,7 @@ public class RemoveGroupMemberActionTest fail("unexpected error: " + t.getMessage()); } } - + @Test public void testRun() throws Exception { @@ -140,19 +140,17 @@ public class RemoveGroupMemberActionTest Group member = new Group("member", null); Group group = new Group("group", null); group.getGroupMembers().add(member); - + Group modified = new Group("group", null); modified.getGroupMembers().add(member); - + final GroupPersistence groupPersistence = EasyMock.createMock(GroupPersistence.class); EasyMock.expect(groupPersistence.getGroup("group")).andReturn(group); EasyMock.expect(groupPersistence.getGroup("member")).andReturn(member); EasyMock.expect(groupPersistence.modifyGroup(group)).andReturn(modified); EasyMock.replay(groupPersistence); - - GroupLogInfo logInfo = EasyMock.createMock(GroupLogInfo.class); - - RemoveGroupMemberAction action = new RemoveGroupMemberAction(logInfo, "group", "member") + + RemoveGroupMemberAction action = new RemoveGroupMemberAction("group", "member") { @Override <T extends Principal> GroupPersistence<T> getGroupPersistence() @@ -161,7 +159,9 @@ public class RemoveGroupMemberActionTest }; }; - action.run(); + GroupLogInfo logInfo = createMock(GroupLogInfo.class); + action.setLogInfo(logInfo); + action.doAction(); } catch (Throwable t) { diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/RemoveUserMemberActionTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/RemoveUserMemberActionTest.java index 05609091e46dba3e1b60d8c307622578d75b62b3..92f5263dabbed86331eb015a9e0098bc02a146b0 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/RemoveUserMemberActionTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/groups/RemoveUserMemberActionTest.java @@ -81,6 +81,8 @@ import org.apache.log4j.Logger; import org.easymock.EasyMock; import org.junit.BeforeClass; import org.junit.Test; + +import static org.easymock.EasyMock.createMock; import static org.junit.Assert.*; /** @@ -90,7 +92,7 @@ import static org.junit.Assert.*; public class RemoveUserMemberActionTest { private final static Logger log = Logger.getLogger(RemoveUserMemberActionTest.class); - + @BeforeClass public static void setUpClass() { @@ -102,42 +104,40 @@ public class RemoveUserMemberActionTest public void testExceptions() { try - { + { String userID = "foo"; String userIDType = AuthenticationUtil.AUTH_TYPE_HTTP; Principal userPrincipal = AuthenticationUtil.createPrincipal(userID, userIDType); User<Principal> user = new User<Principal>(userPrincipal); - + Group group = new Group("group", null); - + final GroupPersistence groupPersistence = EasyMock.createMock(GroupPersistence.class); EasyMock.expect(groupPersistence.getGroup("group")).andReturn(group); EasyMock.replay(groupPersistence); - + final UserPersistence userPersistence = EasyMock.createMock(UserPersistence.class); EasyMock.expect(userPersistence.getUser(userPrincipal)).andReturn(user); EasyMock.replay(userPersistence); - - GroupLogInfo logInfo = EasyMock.createMock(GroupLogInfo.class); - - RemoveUserMemberAction action = new RemoveUserMemberAction(logInfo, "group", userID, userIDType) + + RemoveUserMemberAction action = new RemoveUserMemberAction("group", userID, userIDType) { @Override <T extends Principal> GroupPersistence<T> getGroupPersistence() { return groupPersistence; }; - + @Override <T extends Principal> UserPersistence<T> getUserPersistence() { return userPersistence; }; }; - + try { - action.run(); + action.doAction(); fail("unknown group member should throw MemberNotFoundException"); } catch (MemberNotFoundException ignore) {} @@ -148,7 +148,7 @@ public class RemoveUserMemberActionTest fail("unexpected error: " + t.getMessage()); } } - + @Test @SuppressWarnings("unchecked") public void testRun() throws Exception @@ -159,38 +159,38 @@ public class RemoveUserMemberActionTest String userIDType = AuthenticationUtil.AUTH_TYPE_HTTP; Principal userPrincipal = AuthenticationUtil.createPrincipal(userID, userIDType); User<Principal> user = new User<Principal>(userPrincipal); - + Group group = new Group("group", null); group.getUserMembers().add(user); Group modified = new Group("group", null); - + final GroupPersistence groupPersistence = EasyMock.createMock(GroupPersistence.class); EasyMock.expect(groupPersistence.getGroup("group")).andReturn(group); EasyMock.expect(groupPersistence.modifyGroup(group)).andReturn(modified); EasyMock.replay(groupPersistence); - + final UserPersistence userPersistence = EasyMock.createMock(UserPersistence.class); EasyMock.expect(userPersistence.getUser(userPrincipal)).andReturn(user); EasyMock.replay(userPersistence); - - GroupLogInfo logInfo = EasyMock.createMock(GroupLogInfo.class); - - RemoveUserMemberAction action = new RemoveUserMemberAction(logInfo, "group", userID, userIDType) + + RemoveUserMemberAction action = new RemoveUserMemberAction("group", userID, userIDType) { @Override <T extends Principal> GroupPersistence<T> getGroupPersistence() { return groupPersistence; }; - + @Override <T extends Principal> UserPersistence<T> getUserPersistence() { return userPersistence; }; }; - - action.run(); + + GroupLogInfo logInfo = createMock(GroupLogInfo.class); + action.setLogInfo(logInfo); + action.doAction(); } catch (Throwable t) { @@ -198,5 +198,5 @@ public class RemoveUserMemberActionTest fail("unexpected error: " + t.getMessage()); } } - + } diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UsersActionTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/AbstractUserActionTest.java similarity index 86% rename from projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UsersActionTest.java rename to projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/AbstractUserActionTest.java index 9f68864b52147a94be6ea974d9ae7fd5cdfe178c..4885e98e5687b878074e5bd6efd850ba0cdb98ad 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UsersActionTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/AbstractUserActionTest.java @@ -68,16 +68,12 @@ */ package ca.nrc.cadc.ac.server.web.users; -import ca.nrc.cadc.ac.User; import ca.nrc.cadc.ac.UserNotFoundException; -import ca.nrc.cadc.ac.server.UserPersistence; -import ca.nrc.cadc.auth.HttpPrincipal; import ca.nrc.cadc.net.TransientException; import ca.nrc.cadc.util.Log4jInit; import java.io.*; import java.security.AccessControlException; -import java.security.Principal; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Level; @@ -85,17 +81,14 @@ import org.apache.log4j.Logger; import static org.easymock.EasyMock.*; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; -import static org.junit.Assert.*; - /** * @author jburke */ -public class UsersActionTest +public class AbstractUserActionTest { - private final static Logger log = Logger.getLogger(UsersActionTest.class); + private final static Logger log = Logger.getLogger(AbstractUserActionTest.class); @BeforeClass public static void setUpClass() @@ -153,16 +146,9 @@ public class UsersActionTest expectLastCall().once(); replay(response); - UserLogInfo logInfo = createMock(UserLogInfo.class); - logInfo.setSuccess(false); - expectLastCall().once(); - logInfo.setMessage("Internal Transient Error: foo"); - expectLastCall().once(); - replay(logInfo); - - UsersActionImpl action = new UsersActionImpl(logInfo); + UsersActionImpl action = new UsersActionImpl(); action.setException(new TransientException("foo")); - action.doAction(null, response); + action.doAction(); } private void testDoAction(String message, int responseCode, Exception e) @@ -180,26 +166,21 @@ public class UsersActionTest expectLastCall().once(); replay(response); - UserLogInfo logInfo = createMock(UserLogInfo.class); - logInfo.setMessage(message); - expectLastCall().once(); - replay(logInfo); - - UsersActionImpl action = new UsersActionImpl(logInfo); + UsersActionImpl action = new UsersActionImpl(); action.setException(e); - action.doAction(null, response); + action.doAction(); } - public class UsersActionImpl extends UsersAction + public class UsersActionImpl extends AbstractUserAction { Exception exception; - public UsersActionImpl(UserLogInfo logInfo) + public UsersActionImpl() { - super(logInfo); + super(); } - public Object run() throws Exception + public void doAction() throws Exception { throw exception; } diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/GetUserActionTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/GetUserActionTest.java index e116d69fc410b6e5c740bec4259f440753f03bd7..8fbc0a4a2ae91f65aa5507bb0ec5eb6d0f275c3b 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/GetUserActionTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/GetUserActionTest.java @@ -68,7 +68,10 @@ package ca.nrc.cadc.ac.server.web.users; import ca.nrc.cadc.ac.User; +import ca.nrc.cadc.ac.json.JsonUserWriter; import ca.nrc.cadc.ac.server.UserPersistence; +import ca.nrc.cadc.ac.server.web.SyncOutput; +import ca.nrc.cadc.ac.xml.UserWriter; import ca.nrc.cadc.auth.HttpPrincipal; import org.junit.Test; @@ -78,7 +81,6 @@ import java.io.StringWriter; import java.io.Writer; import static org.easymock.EasyMock.*; -import static org.easymock.EasyMock.verify; import static org.junit.Assert.assertEquals; public class GetUserActionTest @@ -86,13 +88,13 @@ public class GetUserActionTest @Test public void writeUserXML() throws Exception { - final HttpServletResponse mockResponse = - createMock(HttpServletResponse.class); + final SyncOutput mockSyncOut = + createMock(SyncOutput.class); final UserPersistence<HttpPrincipal> mockUserPersistence = createMock(UserPersistence.class); final HttpPrincipal userID = new HttpPrincipal("CADCtest"); - final GetUserAction testSubject = new GetUserAction(null, userID) + final GetUserAction testSubject = new GetUserAction(userID) { @Override UserPersistence<HttpPrincipal> getUserPersistence() @@ -106,34 +108,33 @@ public class GetUserActionTest final PrintWriter printWriter = new PrintWriter(writer); expect(mockUserPersistence.getUser(userID)).andReturn(user).once(); - expect(mockResponse.getWriter()).andReturn(printWriter).once(); - mockResponse.setContentType("text/xml"); + expect(mockSyncOut.getWriter()).andReturn(printWriter).once(); + mockSyncOut.setHeader("Content-Type", "text/xml"); expectLastCall().once(); - replay(mockResponse, mockUserPersistence); + replay(mockSyncOut, mockUserPersistence); - testSubject.doAction(null, mockResponse); + testSubject.setSyncOut(mockSyncOut); + testSubject.doAction(); - assertEquals("Wrong XML output.", - "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" + - "<user>\r\n" + - " <userID>\r\n" + - " <identity type=\"HTTP\">CADCtest</identity>\r\n" + - " </userID>\r\n" + - "</user>\r\n", writer.toString()); - verify(mockResponse, mockUserPersistence); + StringBuilder sb = new StringBuilder(); + UserWriter userWriter = new UserWriter(); + userWriter.write(user, sb); + assertEquals(sb.toString(), writer.toString()); + + verify(mockSyncOut, mockUserPersistence); } @Test public void writeUserJSON() throws Exception { - final HttpServletResponse mockResponse = - createMock(HttpServletResponse.class); + final SyncOutput mockSyncOut = + createMock(SyncOutput.class); final UserPersistence<HttpPrincipal> mockUserPersistence = createMock(UserPersistence.class); final HttpPrincipal userID = new HttpPrincipal("CADCtest"); - final GetUserAction testSubject = new GetUserAction(null, userID) + final GetUserAction testSubject = new GetUserAction(userID) { @Override UserPersistence<HttpPrincipal> getUserPersistence() @@ -142,23 +143,28 @@ public class GetUserActionTest } }; - testSubject.setAcceptedContentType(UsersAction.JSON_CONTENT_TYPE); + testSubject.setAcceptedContentType(AbstractUserAction.JSON_CONTENT_TYPE); final User<HttpPrincipal> user = new User<HttpPrincipal>(userID); final Writer writer = new StringWriter(); final PrintWriter printWriter = new PrintWriter(writer); expect(mockUserPersistence.getUser(userID)).andReturn(user).once(); - expect(mockResponse.getWriter()).andReturn(printWriter).once(); - mockResponse.setContentType("application/json"); + expect(mockSyncOut.getWriter()).andReturn(printWriter).once(); + mockSyncOut.setHeader("Content-Type", "application/json"); expectLastCall().once(); - replay(mockResponse, mockUserPersistence); - testSubject.doAction(null, mockResponse); + replay(mockSyncOut, mockUserPersistence); + testSubject.setSyncOut(mockSyncOut); + UserLogInfo logInfo = createMock(UserLogInfo.class); + testSubject.setLogInfo(logInfo); + testSubject.doAction(); + + StringBuilder sb = new StringBuilder(); + JsonUserWriter userWriter = new JsonUserWriter(); + userWriter.write(user, sb); + assertEquals(sb.toString(), writer.toString()); - assertEquals("Wrong JSON output.", - "{\"user\":{\"userID\":{\"identity\":{\"name\":\"CADCtest\",\"type\":\"HTTP\"}}}}", - writer.toString()); - verify(mockResponse, mockUserPersistence); + verify(mockSyncOut, mockUserPersistence); } } diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/GetUsersActionTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/GetUserListActionTest.java similarity index 66% rename from projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/GetUsersActionTest.java rename to projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/GetUserListActionTest.java index f1dc7a29aeb521d739a16325c62b97af3a83510a..8e3a6db4ccc8259169fbbb50232317d7e0fa9e86 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/GetUsersActionTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/GetUserListActionTest.java @@ -70,7 +70,10 @@ package ca.nrc.cadc.ac.server.web.users; import ca.nrc.cadc.ac.PersonalDetails; +import ca.nrc.cadc.ac.json.JsonUserListWriter; import ca.nrc.cadc.ac.server.UserPersistence; +import ca.nrc.cadc.ac.server.web.SyncOutput; +import ca.nrc.cadc.ac.xml.UserListWriter; import ca.nrc.cadc.auth.HttpPrincipal; import org.apache.log4j.Level; @@ -82,12 +85,11 @@ import javax.servlet.http.HttpServletResponse; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; -import java.util.ArrayList; -import java.util.Collection; import java.util.HashMap; import java.util.Map; import static org.easymock.EasyMock.*; + import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -97,7 +99,7 @@ import org.skyscreamer.jsonassert.JSONAssert; * * @author adriand */ -public class GetUsersActionTest +public class GetUserListActionTest { @BeforeClass public static void setUpClass() @@ -109,8 +111,8 @@ public class GetUsersActionTest @SuppressWarnings("unchecked") public void testWriteUsersJSON() throws Exception { - final HttpServletResponse mockResponse = - createMock(HttpServletResponse.class); + final SyncOutput mockSyncOut = + createMock(SyncOutput.class); final UserPersistence<HttpPrincipal> mockUserPersistence = createMock(UserPersistence.class); final Map<String, PersonalDetails> userEntries = @@ -122,7 +124,7 @@ public class GetUsersActionTest new PersonalDetails("USER", Integer.toString(i))); } - final GetUsersAction testSubject = new GetUsersAction(null) + final GetUserListAction testSubject = new GetUserListAction() { @Override UserPersistence<HttpPrincipal> getUserPersistence() @@ -131,34 +133,38 @@ public class GetUsersActionTest } }; - testSubject.setAcceptedContentType(UsersAction.JSON_CONTENT_TYPE); + testSubject.setAcceptedContentType(AbstractUserAction.JSON_CONTENT_TYPE); - final Writer writer = new StringWriter(); - final PrintWriter printWriter = new PrintWriter(writer); + final Writer actualWriter = new StringWriter(); + final PrintWriter actualPrintWriter = new PrintWriter(actualWriter); expect(mockUserPersistence.getUsers()).andReturn( userEntries).once(); - expect(mockResponse.getWriter()).andReturn(printWriter).once(); - mockResponse.setContentType("application/json"); + expect(mockSyncOut.getWriter()).andReturn(actualPrintWriter).once(); + mockSyncOut.setHeader("Content-Type", "application/json"); expectLastCall().once(); - replay(mockResponse, mockUserPersistence); - testSubject.doAction(null, mockResponse); + replay(mockSyncOut, mockUserPersistence); + testSubject.setSyncOut(mockSyncOut); + UserLogInfo logInfo = createMock(UserLogInfo.class); + testSubject.setLogInfo(logInfo); + testSubject.doAction(); - final JSONArray expected = - new JSONArray("[{\"id\":\"USER_1\",\"firstName\":\"USER\",\"lastName\":\"1\"},{\"id\":\"USER_3\",\"firstName\":\"USER\",\"lastName\":\"3\"},{\"id\":\"USER_2\",\"firstName\":\"USER\",\"lastName\":\"2\"},{\"id\":\"USER_4\",\"firstName\":\"USER\",\"lastName\":\"4\"},{\"id\":\"USER_5\",\"firstName\":\"USER\",\"lastName\":\"5\"}]"); - final JSONArray result = new JSONArray(writer.toString()); + final Writer expectedWriter = new StringWriter(); + final PrintWriter expectedPrintWriter = new PrintWriter(expectedWriter); + JsonUserListWriter userListWriter = new JsonUserListWriter(); + userListWriter.write(userEntries, expectedPrintWriter); + JSONAssert.assertEquals(expectedWriter.toString(), actualWriter.toString(), false); - JSONAssert.assertEquals(expected, result, true); - verify(mockResponse, mockUserPersistence); + verify(mockSyncOut, mockUserPersistence); } @Test @SuppressWarnings("unchecked") public void testWriteUsersXML() throws Exception { - final HttpServletResponse mockResponse = - createMock(HttpServletResponse.class); + final SyncOutput mockSyncOut = + createMock(SyncOutput.class); final UserPersistence<HttpPrincipal> mockUserPersistence = createMock(UserPersistence.class); final Map<String, PersonalDetails> userEntries = @@ -170,7 +176,7 @@ public class GetUsersActionTest new PersonalDetails("USER", Integer.toString(i))); } - final GetUsersAction testSubject = new GetUsersAction(null) + final GetUserListAction testSubject = new GetUserListAction() { @Override UserPersistence<HttpPrincipal> getUserPersistence() @@ -179,44 +185,27 @@ public class GetUsersActionTest } }; - final Writer writer = new StringWriter(); - final PrintWriter printWriter = new PrintWriter(writer); + final Writer actualWriter = new StringWriter(); + final PrintWriter actualPrintWriter = new PrintWriter(actualWriter); expect(mockUserPersistence.getUsers()).andReturn( userEntries).once(); - expect(mockResponse.getWriter()).andReturn(printWriter).once(); - mockResponse.setContentType("text/xml"); + expect(mockSyncOut.getWriter()).andReturn(actualPrintWriter).once(); + mockSyncOut.setHeader("Content-Type", "text/xml"); expectLastCall().once(); - replay(mockResponse, mockUserPersistence); - testSubject.doAction(null, mockResponse); - - final String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" + - "<users>\r\n" + - " <user id=\"USER_1\">\r\n" + - " <firstName>USER</firstName>\r\n" + - " <lastName>1</lastName>\r\n" + - " </user>\r\n" + - " <user id=\"USER_3\">\r\n" + - " <firstName>USER</firstName>\r\n" + - " <lastName>3</lastName>\r\n" + - " </user>\r\n" + - " <user id=\"USER_2\">\r\n" + - " <firstName>USER</firstName>\r\n" + - " <lastName>2</lastName>\r\n" + - " </user>\r\n" + - " <user id=\"USER_4\">\r\n" + - " <firstName>USER</firstName>\r\n" + - " <lastName>4</lastName>\r\n" + - " </user>\r\n" + - " <user id=\"USER_5\">\r\n" + - " <firstName>USER</firstName>\r\n" + - " <lastName>5</lastName>\r\n" + - " </user>\r\n" + - "</users>\r\n"; - final String result = writer.toString(); - - assertEquals("Wrong XML", expected, result); - verify(mockResponse, mockUserPersistence); + replay(mockSyncOut, mockUserPersistence); + testSubject.setSyncOut(mockSyncOut); + UserLogInfo logInfo = createMock(UserLogInfo.class); + testSubject.setLogInfo(logInfo); + testSubject.doAction(); + + final Writer expectedWriter = new StringWriter(); + final PrintWriter expectedPrintWriter = new PrintWriter(expectedWriter); + UserListWriter userListWriter = new UserListWriter(); + userListWriter.write(userEntries, expectedPrintWriter); + assertEquals("Wrong XML", expectedWriter.toString(), actualWriter.toString()); + + verify(mockSyncOut, mockUserPersistence); } } diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/ModifyUserActionTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/ModifyUserActionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ff4538b29c58b0c6a33548b1907f78077309a866 --- /dev/null +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/ModifyUserActionTest.java @@ -0,0 +1,166 @@ +/* + ************************************************************************ + ******************* CANADIAN ASTRONOMY DATA CENTRE ******************* + ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** + * + * (c) 2015. (c) 2015. + * Government of Canada Gouvernement du Canada + * National Research Council Conseil national de recherches + * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 + * All rights reserved Tous droits réservés + * + * NRC disclaims any warranties, Le CNRC dénie toute garantie + * expressed, implied, or énoncée, implicite ou légale, + * statutory, of any kind with de quelque nature que ce + * respect to the software, soit, concernant le logiciel, + * including without limitation y compris sans restriction + * any warranty of merchantability toute garantie de valeur + * or fitness for a particular marchande ou de pertinence + * purpose. NRC shall not be pour un usage particulier. + * liable in any event for any Le CNRC ne pourra en aucun cas + * damages, whether direct or être tenu responsable de tout + * indirect, special or general, dommage, direct ou indirect, + * consequential or incidental, particulier ou général, + * arising from the use of the accessoire ou fortuit, résultant + * software. Neither the name de l'utilisation du logiciel. Ni + * of the National Research le nom du Conseil National de + * Council of Canada nor the Recherches du Canada ni les noms + * names of its contributors may de ses participants ne peuvent + * be used to endorse or promote être utilisés pour approuver ou + * products derived from this promouvoir les produits dérivés + * software without specific prior de ce logiciel sans autorisation + * written permission. préalable et particulière + * par écrit. + * + * This file is part of the Ce fichier fait partie du projet + * OpenCADC project. OpenCADC. + * + * OpenCADC is free software: OpenCADC est un logiciel libre ; + * you can redistribute it and/or vous pouvez le redistribuer ou le + * modify it under the terms of modifier suivant les termes de + * the GNU Affero General Public la “GNU Affero General Public + * License as published by the License” telle que publiée + * Free Software Foundation, par la Free Software Foundation + * either version 3 of the : soit la version 3 de cette + * License, or (at your option) licence, soit (à votre gré) + * any later version. toute version ultérieure. + * + * OpenCADC is distributed in the OpenCADC est distribué + * hope that it will be useful, dans l’espoir qu’il vous + * but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE + * without even the implied GARANTIE : sans même la garantie + * warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ + * or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF + * PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence + * General Public License for Générale Publique GNU Affero + * more details. pour plus de détails. + * + * You should have received Vous devriez avoir reçu une + * a copy of the GNU Affero copie de la Licence Générale + * General Public License along Publique GNU Affero avec + * with OpenCADC. If not, see OpenCADC ; si ce n’est + * <http://www.gnu.org/licenses/>. pas le cas, consultez : + * <http://www.gnu.org/licenses/>. + * + * + ************************************************************************ + */ + +package ca.nrc.cadc.ac.server.web.users; + +import ca.nrc.cadc.ac.PersonalDetails; +import ca.nrc.cadc.ac.User; +import ca.nrc.cadc.ac.json.JsonUserWriter; +import ca.nrc.cadc.ac.server.UserPersistence; +import ca.nrc.cadc.ac.server.web.SyncOutput; +import ca.nrc.cadc.auth.HttpPrincipal; +import org.junit.Test; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.security.Principal; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + + +public class ModifyUserActionTest +{ + @Test + public void run() throws Exception + { + final HttpPrincipal httpPrincipal = new HttpPrincipal("CADCtest"); + User<Principal> expected = new User<Principal>(httpPrincipal); + expected.getIdentities().add(httpPrincipal); + final PersonalDetails pd = new PersonalDetails("CADC", "Test"); + pd.email = "CADC.Test@nrc-cnrc.gc.ca"; + expected.details.add(pd); + + final StringBuilder sb = new StringBuilder(); + final JsonUserWriter userWriter = new JsonUserWriter(); + userWriter.write(expected, sb); + + final byte[] input = sb.toString().getBytes(); + final InputStream inputStream = new ByteArrayInputStream(input); + + // Should match the JSON above, without the e-mail modification. + Principal principal = new HttpPrincipal("CADCtest"); + final User<Principal> userObject = + new User<Principal>(principal); + userObject.getIdentities().add(principal); + final PersonalDetails personalDetail = + new PersonalDetails("CADC", "Test"); + personalDetail.email = "CADC.Test@nrc-cnrc.gc.ca"; + userObject.details.add(personalDetail); + + final HttpServletRequest mockRequest = + createMock(HttpServletRequest.class); + final SyncOutput mockSyncOut = + createMock(SyncOutput.class); + + @SuppressWarnings("unchecked") + final UserPersistence<Principal> mockUserPersistence = + createMock(UserPersistence.class); + + expect(mockUserPersistence.modifyUser(userObject)).andReturn( + userObject).once(); +// +// expect(mockRequest.getRemoteAddr()).andReturn(requestURL). +// once(); + + mockSyncOut.setHeader("Location", "/CADCtest?idType=http"); + expectLastCall().once(); + + mockSyncOut.setCode(303); + expectLastCall().once(); + + mockSyncOut.setHeader("Content-Type", "application/json"); + expectLastCall().once(); + + replay(mockRequest, mockSyncOut, mockUserPersistence); + + final ModifyUserAction testSubject = new ModifyUserAction(inputStream) + { + @Override + @SuppressWarnings("unchecked") + UserPersistence<Principal> getUserPersistence() + { + return mockUserPersistence; + } + }; + + testSubject.setAcceptedContentType("application/json"); + testSubject.syncOut = mockSyncOut; + UserLogInfo logInfo = createMock(UserLogInfo.class); + testSubject.setLogInfo(logInfo); + testSubject.doAction(); + + verify(mockRequest, mockSyncOut, mockUserPersistence); + } +} diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UserActionFactoryTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UserActionFactoryTest.java index 4241c015a6a3f7a2d21b0a0e41f0fac1ff37d45b..131d167a64f5ef259a1fccc97d94ef3523a86d59 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UserActionFactoryTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UserActionFactoryTest.java @@ -92,10 +92,9 @@ public class UserActionFactoryTest { HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); EasyMock.expect(request.getPathInfo()).andReturn(""); - EasyMock.expect(request.getMethod()).andReturn("PUT"); EasyMock.expect(request.getInputStream()).andReturn(null); EasyMock.replay(request); - UsersAction action = UsersActionFactory.getUsersAction(request, null); + AbstractUserAction action = UserActionFactory.httpPutFactory().createAction(request); EasyMock.verify(request); Assert.assertTrue("Wrong action", action instanceof CreateUserAction); } @@ -113,10 +112,9 @@ public class UserActionFactoryTest { HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); EasyMock.expect(request.getPathInfo()).andReturn("userName"); - EasyMock.expect(request.getMethod()).andReturn("DELETE"); EasyMock.expect(request.getParameter("idType")).andReturn("sessionID"); EasyMock.replay(request); - UsersAction action = UsersActionFactory.getUsersAction(request, null); + AbstractUserAction action = UserActionFactory.httpDeleteFactory().createAction(request); EasyMock.verify(request); Assert.assertTrue("Wrong action", action instanceof DeleteUserAction); } @@ -134,10 +132,9 @@ public class UserActionFactoryTest { HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); EasyMock.expect(request.getPathInfo()).andReturn("userName"); - EasyMock.expect(request.getMethod()).andReturn("GET"); EasyMock.expect(request.getParameter("idType")).andReturn("sessionID"); EasyMock.replay(request); - UsersAction action = UsersActionFactory.getUsersAction(request, null); + AbstractUserAction action = UserActionFactory.httpGetFactory().createAction(request); EasyMock.verify(request); Assert.assertTrue("Wrong action", action instanceof GetUserAction); } @@ -155,11 +152,10 @@ public class UserActionFactoryTest { HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); EasyMock.expect(request.getPathInfo()).andReturn(""); - EasyMock.expect(request.getMethod()).andReturn("GET"); EasyMock.replay(request); - UsersAction action = UsersActionFactory.getUsersAction(request, null); + AbstractUserAction action = UserActionFactory.httpGetFactory().createAction(request); EasyMock.verify(request); - Assert.assertTrue("Wrong action", action instanceof GetUsersAction); + Assert.assertTrue("Wrong action", action instanceof GetUserListAction); } catch (Throwable t) { @@ -178,14 +174,13 @@ public class UserActionFactoryTest HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); EasyMock.expect(request.getPathInfo()).andReturn("userName"); - EasyMock.expect(request.getMethod()).andReturn("POST"); - EasyMock.expect(request.getRequestURL()).andReturn(sb); - EasyMock.expect(request.getContextPath()).andReturn(""); - EasyMock.expect(request.getServletPath()).andReturn(""); + //EasyMock.expect(request.getRequestURL()).andReturn(sb); + //EasyMock.expect(request.getContextPath()).andReturn(""); + //EasyMock.expect(request.getServletPath()).andReturn(""); EasyMock.expect(request.getInputStream()).andReturn(null); - EasyMock.expect(request.getParameter("idType")).andReturn("sessionID"); + //EasyMock.expect(request.getParameter("idType")).andReturn("sessionID"); EasyMock.replay(request); - UsersAction action = UsersActionFactory.getUsersAction(request, null); + AbstractUserAction action = UserActionFactory.httpPostFactory().createAction(request); EasyMock.verify(request); Assert.assertTrue("Wrong action", action instanceof ModifyUserAction); } @@ -197,41 +192,23 @@ public class UserActionFactoryTest } @Test - public void testBadRequests() + public void testBadPostRequest() { try { - TestRequest[] testRequests = + HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); + EasyMock.expect(request.getPathInfo()).andReturn(""); + EasyMock.replay(request); + try { - new TestRequest("", "POST"), - new TestRequest("", "DELETE"), - new TestRequest("", "HEAD"), - }; - - for (TestRequest testRequest : testRequests) + UserActionFactory.httpPostFactory().createAction(request); + Assert.fail("Should have been a bad request"); + } + catch (IllegalArgumentException e) { - - log.debug("Testing: " + testRequest); - - HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); - EasyMock.expect(request.getPathInfo()).andReturn(testRequest.path); - EasyMock.expect(request.getMethod()).andReturn(testRequest.method); - if (testRequest.paramName != null) - { - EasyMock.expect(request.getParameter(testRequest.paramName)).andReturn(testRequest.paramValue); - } - EasyMock.replay(request); - try - { - UsersActionFactory.getUsersAction(request, null); - Assert.fail("Should have been a bad request: " + testRequest.method + " on " + testRequest.path); - } - catch (IllegalArgumentException e) - { - // expected - } - EasyMock.verify(request); + // expected } + EasyMock.verify(request); } catch (Throwable t) { @@ -240,31 +217,56 @@ public class UserActionFactoryTest } } - private class TestRequest + @Test + public void testBadDeleteRequest() { - public String path; - public String method; - public String paramName; - public String paramValue; - - public TestRequest(String path, String method) + try + { + HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); + EasyMock.expect(request.getPathInfo()).andReturn(""); + EasyMock.replay(request); + try + { + UserActionFactory.httpDeleteFactory().createAction(request); + Assert.fail("Should have been a bad request"); + } + catch (IllegalArgumentException e) + { + // expected + } + EasyMock.verify(request); + } + catch (Throwable t) { - this(path, method, null, null); + log.error(t.getMessage(), t); + Assert.fail("unexpected error: " + t.getMessage()); } - public TestRequest(String path, String method, String paramName, String paramValue) + } + + @Test + public void testBadHeadRequest() + { + try { - this.path = path; - this.method = method; - this.paramName = paramName; - this.paramValue = paramValue; + HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); + EasyMock.replay(request); + try + { + UserActionFactory.httpHeadFactory().createAction(request); + Assert.fail("Should have been a bad request"); + } + catch (UnsupportedOperationException e) + { + // expected + } + EasyMock.verify(request); } - @Override - public String toString() + catch (Throwable t) { - return method + " on path " + path + - ((paramName == null) ? "" : "?" + paramName + "=" + paramValue); + log.error(t.getMessage(), t); + Assert.fail("unexpected error: " + t.getMessage()); } - } + } diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UsersServletTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UserServletTest.java similarity index 88% rename from projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UsersServletTest.java rename to projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UserServletTest.java index 8e0a27f5b988c9cecbdcbd567d418c8825e4671e..3ab00e88c44a487a6367aec89f39d44ecb9142e9 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UsersServletTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UserServletTest.java @@ -8,14 +8,14 @@ import static org.easymock.EasyMock.*; import static org.junit.Assert.*; -public class UsersServletTest +public class UserServletTest { @Test public void getAcceptedContentTypeJSON() throws Exception { final HttpServletRequest mockRequest = createMock(HttpServletRequest.class); - final UsersServlet testSubject = new UsersServlet(); + final UserServlet testSubject = new UserServlet(); expect(mockRequest.getHeader("Accept")). andReturn("application/json").once(); @@ -33,7 +33,7 @@ public class UsersServletTest { final HttpServletRequest mockRequest = createMock(HttpServletRequest.class); - final UsersServlet testSubject = new UsersServlet(); + final UserServlet testSubject = new UserServlet(); expect(mockRequest.getHeader("Accept")).andReturn(null).once(); diff --git a/projects/cadcAccessControl/build.xml b/projects/cadcAccessControl/build.xml index 3296ce950c082b9ba95b90a8d517461a1d0ca14f..4eab166665173e7055d0335620c699ddf90e1ffc 100644 --- a/projects/cadcAccessControl/build.xml +++ b/projects/cadcAccessControl/build.xml @@ -117,7 +117,7 @@ <property name="testingJars" value="${build}/class:${jars}:${xerces}:${asm}:${cglib}:${easymock}:${junit}:${objenesis}" /> - <target name="test" depends="compile,compile-test"> + <target name="single-test" depends="compile,compile-test"> <echo message="Running test suite..." /> <junit printsummary="yes" haltonfailure="yes" fork="yes"> <classpath> @@ -125,11 +125,7 @@ <pathelement path="${build}/test/class"/> <pathelement path="${testingJars}"/> </classpath> - <test name="ca.nrc.cadc.ac.json.GroupPropertyReaderWriterTest" /> - <test name="ca.nrc.cadc.ac.json.UserDetailsReaderWriterTest" /> - <test name="ca.nrc.cadc.ac.json.IdentityReaderWriterTest" /> - <test name="ca.nrc.cadc.ac.json.UserReaderWriterTest" /> - <test name="ca.nrc.cadc.ac.json.GroupReaderWriterTest" /> + <test name="ca.nrc.cadc.ac.json.JsonGroupReaderWriterTest" /> <formatter type="plain" usefile="false" /> </junit> </target> diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/User.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/User.java index b7ad0bcc44ef8c9da5156bd1c74ee320c3f07150..97a63b6bb2827991999266e3e547cdf4bd31f42d 100644 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/User.java +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/User.java @@ -134,18 +134,15 @@ public class User<T extends Principal> { return false; } - User other = (User) obj; + + final User other = (User) obj; if (userID instanceof X500Principal) { return AuthenticationUtil.equals(userID, other.userID); } else { - if (!userID.equals(other.userID)) - { - return false; - } - return true; + return userID.equals(other.userID); } } @@ -173,4 +170,31 @@ public class User<T extends Principal> return matchedDetails; } + + /** + * Obtain a set of identities whose type match the given one. + * + * @param identityClass The class to search on. + * @param <S> The Principal type. + * @return Set of matched identities, or empty Set. + * Never null. + */ + public <S extends Principal> Set<S> getIdentities( + final Class<S> identityClass) + { + final Set<S> matchedIdentities = new HashSet<S>(); + + for (final Principal p : identities) + { + if (p.getClass() == identityClass) + { + // This casting shouldn't happen, but it's the only way to + // do this without a lot of work. + // jenkinsd 2014.09.26 + matchedIdentities.add((S) p); + } + } + + return matchedIdentities; + } } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/UserAlreadyExistsException.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/UserAlreadyExistsException.java similarity index 100% rename from projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/UserAlreadyExistsException.java rename to projects/cadcAccessControl/src/ca/nrc/cadc/ac/UserAlreadyExistsException.java diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/UserRequest.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/UserRequest.java index d1c28cfac115e291be92c9fc60618f32de33113f..664b18d2a99d3f39e2927e9e7e6e89986371d2b6 100644 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/UserRequest.java +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/UserRequest.java @@ -74,15 +74,15 @@ import java.security.Principal; public class UserRequest<T extends Principal> { private User<T> user; - private String password; + private char[] password; - public UserRequest(final User<T> user, final String password) + public UserRequest(final User<T> user, final char[] password) { if (user == null) { throw new IllegalArgumentException("null user"); } - if (password == null || password.isEmpty()) + if (password == null || password.length == 0) { throw new IllegalArgumentException("null or empty password"); } @@ -95,11 +95,19 @@ public class UserRequest<T extends Principal> return this.user; } - public String getPassword() + public char[] getPassword() { return this.password; } + public void clear() + { + for (int i = 0; i < password.length; i++) + { + password[i] = '0'; + } + } + @Override public boolean equals(Object o) { @@ -115,7 +123,6 @@ public class UserRequest<T extends Principal> UserRequest<?> that = (UserRequest<?>) o; return user.equals(that.user); - } @Override diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/client/GMSClient.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/client/GMSClient.java index 8f4eab02036b1155294d80566c74a434875ad142..bad17d1f5f80cee819082265ca7f344940ac14b1 100755 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/client/GMSClient.java +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/client/GMSClient.java @@ -68,7 +68,34 @@ */ package ca.nrc.cadc.ac.client; -import java.io.*; +import ca.nrc.cadc.ac.Group; +import ca.nrc.cadc.ac.GroupAlreadyExistsException; +import ca.nrc.cadc.ac.GroupNotFoundException; +import ca.nrc.cadc.ac.Role; +import ca.nrc.cadc.ac.User; +import ca.nrc.cadc.ac.UserNotFoundException; +import ca.nrc.cadc.ac.xml.GroupListReader; +import ca.nrc.cadc.ac.xml.GroupReader; +import ca.nrc.cadc.ac.xml.GroupWriter; +import ca.nrc.cadc.auth.AuthenticationUtil; +import ca.nrc.cadc.auth.HttpPrincipal; +import ca.nrc.cadc.auth.SSLUtil; +import ca.nrc.cadc.net.HttpDownload; +import ca.nrc.cadc.net.HttpPost; +import ca.nrc.cadc.net.HttpUpload; +import ca.nrc.cadc.net.InputStreamWrapper; +import ca.nrc.cadc.net.NetUtil; +import org.apache.log4j.Logger; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSocketFactory; +import javax.security.auth.Subject; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; @@ -84,27 +111,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLSocketFactory; -import javax.security.auth.Subject; - -import ca.nrc.cadc.ac.*; -import ca.nrc.cadc.auth.HttpPrincipal; -import ca.nrc.cadc.util.StringUtil; -import org.apache.log4j.Logger; - -import ca.nrc.cadc.ac.xml.GroupReader; -import ca.nrc.cadc.ac.xml.GroupWriter; -import ca.nrc.cadc.ac.xml.GroupsReader; -import ca.nrc.cadc.auth.AuthenticationUtil; -import ca.nrc.cadc.auth.SSLUtil; -import ca.nrc.cadc.net.HttpDownload; -import ca.nrc.cadc.net.HttpPost; -import ca.nrc.cadc.net.HttpUpload; -import ca.nrc.cadc.net.InputStreamWrapper; -import ca.nrc.cadc.net.NetUtil; -import org.json.JSONObject; - /** * Client class for performing group searching and group actions @@ -217,7 +223,7 @@ public class GMSClient { final URL usersListURL = new URL(this.baseURL + "/users"); return new HttpDownload(usersListURL, - new JSONUserListInputStreamWrapper(webUsers)); + new JsonUserListInputStreamWrapper(webUsers)); } /** @@ -242,7 +248,8 @@ public class GMSClient clearCache(); StringBuilder groupXML = new StringBuilder(); - GroupWriter.write(group, groupXML); + GroupWriter groupWriter = new GroupWriter(); + groupWriter.write(group, groupXML); log.debug("createGroup: " + groupXML); byte[] bytes = groupXML.toString().getBytes("UTF-8"); @@ -283,7 +290,8 @@ public class GMSClient try { log.debug("createGroup returned: " + retXML); - return GroupReader.read(retXML); + GroupReader groupReader = new GroupReader(); + return groupReader.read(retXML); } catch (Exception bug) { @@ -339,7 +347,8 @@ public class GMSClient { String groupXML = new String(out.toByteArray(), "UTF-8"); log.debug("getGroup returned: " + groupXML); - return GroupReader.read(groupXML); + GroupReader groupReader = new GroupReader(); + return groupReader.read(groupXML); } catch (Exception bug) { @@ -441,7 +450,8 @@ public class GMSClient clearCache(); StringBuilder groupXML = new StringBuilder(); - GroupWriter.write(group, groupXML); + GroupWriter groupWriter = new GroupWriter(); + groupWriter.write(group, groupXML); log.debug("updateGroup: " + groupXML); HttpPost transfer = new HttpPost(updateGroupURL, groupXML.toString(), @@ -482,7 +492,8 @@ public class GMSClient { String retXML = transfer.getResponseBody(); log.debug("getGroup returned: " + retXML); - return GroupReader.read(retXML); + GroupReader groupReader = new GroupReader(); + return groupReader.read(retXML); } catch (Exception bug) { @@ -887,7 +898,8 @@ public class GMSClient { String groupsXML = new String(out.toByteArray(), "UTF-8"); log.debug("getMemberships returned: " + groupsXML); - List<Group> groups = GroupsReader.read(groupsXML); + GroupListReader groupListReader = new GroupListReader(); + List<Group> groups = groupListReader.read(groupsXML); setCachedGroups(userID, groups, role); return groups; } @@ -1004,7 +1016,8 @@ public class GMSClient { String groupsXML = new String(out.toByteArray(), "UTF-8"); log.debug("getMembership returned: " + groupsXML); - List<Group> groups = GroupsReader.read(groupsXML); + GroupListReader groupListReader = new GroupListReader(); + List<Group> groups = groupListReader.read(groupsXML); if (groups.size() == 0) { return null; diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/client/JSONUserListInputStreamWrapper.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/client/JsonUserListInputStreamWrapper.java similarity index 96% rename from projects/cadcAccessControl/src/ca/nrc/cadc/ac/client/JSONUserListInputStreamWrapper.java rename to projects/cadcAccessControl/src/ca/nrc/cadc/ac/client/JsonUserListInputStreamWrapper.java index 8e3a47447965467f2f822dc5a532fff1ab0571a0..f00b0aeef2821f4740ae2eab7130b33d0001009f 100644 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/client/JSONUserListInputStreamWrapper.java +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/client/JsonUserListInputStreamWrapper.java @@ -82,15 +82,15 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.util.List; -public class JSONUserListInputStreamWrapper implements InputStreamWrapper +public class JsonUserListInputStreamWrapper implements InputStreamWrapper { private static final Logger LOGGER = Logger - .getLogger(JSONUserListInputStreamWrapper.class); + .getLogger(JsonUserListInputStreamWrapper.class); private final List<User<HttpPrincipal>> output; - public JSONUserListInputStreamWrapper( - final List<User<HttpPrincipal>> output) + public JsonUserListInputStreamWrapper( + final List<User<HttpPrincipal>> output) { this.output = output; } diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/GroupReader.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/GroupReader.java deleted file mode 100755 index f726b87a5ea426ffd94bbf914b1da5124bb533ee..0000000000000000000000000000000000000000 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/GroupReader.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - ************************************************************************ - ******************* CANADIAN ASTRONOMY DATA CENTRE ******************* - ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** - * - * (c) 2014. (c) 2014. - * Government of Canada Gouvernement du Canada - * National Research Council Conseil national de recherches - * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 - * All rights reserved Tous droits réservés - * - * NRC disclaims any warranties, Le CNRC dénie toute garantie - * expressed, implied, or énoncée, implicite ou légale, - * statutory, of any kind with de quelque nature que ce - * respect to the software, soit, concernant le logiciel, - * including without limitation y compris sans restriction - * any warranty of merchantability toute garantie de valeur - * or fitness for a particular marchande ou de pertinence - * purpose. NRC shall not be pour un usage particulier. - * liable in any event for any Le CNRC ne pourra en aucun cas - * damages, whether direct or être tenu responsable de tout - * indirect, special or general, dommage, direct ou indirect, - * consequential or incidental, particulier ou général, - * arising from the use of the accessoire ou fortuit, résultant - * software. Neither the name de l'utilisation du logiciel. Ni - * of the National Research le nom du Conseil National de - * Council of Canada nor the Recherches du Canada ni les noms - * names of its contributors may de ses participants ne peuvent - * be used to endorse or promote être utilisés pour approuver ou - * products derived from this promouvoir les produits dérivés - * software without specific prior de ce logiciel sans autorisation - * written permission. préalable et particulière - * par écrit. - * - * This file is part of the Ce fichier fait partie du projet - * OpenCADC project. OpenCADC. - * - * OpenCADC is free software: OpenCADC est un logiciel libre ; - * you can redistribute it and/or vous pouvez le redistribuer ou le - * modify it under the terms of modifier suivant les termes de - * the GNU Affero General Public la “GNU Affero General Public - * License as published by the License” telle que publiée - * Free Software Foundation, par la Free Software Foundation - * either version 3 of the : soit la version 3 de cette - * License, or (at your option) licence, soit (à votre gré) - * any later version. toute version ultérieure. - * - * OpenCADC is distributed in the OpenCADC est distribué - * hope that it will be useful, dans l’espoir qu’il vous - * but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE - * without even the implied GARANTIE : sans même la garantie - * warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ - * or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF - * PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence - * General Public License for Générale Publique GNU Affero - * more details. pour plus de détails. - * - * You should have received Vous devriez avoir reçu une - * a copy of the GNU Affero copie de la Licence Générale - * General Public License along Publique GNU Affero avec - * with OpenCADC. If not, see OpenCADC ; si ce n’est - * <http://www.gnu.org/licenses/>. pas le cas, consultez : - * <http://www.gnu.org/licenses/>. - * - * $Revision: 4 $ - * - ************************************************************************ - */ -package ca.nrc.cadc.ac.json; - -import ca.nrc.cadc.ac.AC; -import ca.nrc.cadc.ac.Group; -import ca.nrc.cadc.ac.ReaderException; -import ca.nrc.cadc.ac.User; -import ca.nrc.cadc.date.DateUtil; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.net.URISyntaxException; -import java.security.Principal; -import java.text.DateFormat; -import java.text.ParseException; -import java.util.Scanner; - -public class GroupReader -{ - /** - * Construct a Group from a InputStream. - * - * @param in InputStream. - * @return Group Group. - * @throws ReaderException - * @throws IOException - * @throws URISyntaxException - */ - public static Group read(InputStream in) - throws ReaderException, IOException - { - if (in == null) - { - throw new IOException("stream closed"); - } - InputStreamReader reader; - - Scanner s = new Scanner(in).useDelimiter("\\A"); - String json = s.hasNext() ? s.next() : ""; - - return read(json); - } - - /** - * Construct a Group from a Reader. - * - * @param reader Reader. - * @return Group Group. - * @throws ReaderException - * @throws IOException - * @throws URISyntaxException - */ - public static Group read(Reader reader) - throws ReaderException, IOException - { - if (reader == null) - { - throw new IllegalArgumentException("reader must not be null"); - } - - Scanner s = new Scanner(reader).useDelimiter("\\A"); - String json = s.hasNext() ? s.next() : ""; - - return read(json); - } - - /** - * Construct a Group from an JSON String source. - * - * @param json String of JSON. - * @return Group Group. - * @throws ReaderException - * @throws IOException - * @throws URISyntaxException - */ - public static Group read(String json) - throws ReaderException, IOException - { - if (json == null) - { - throw new IllegalArgumentException("JSON must not be null"); - } - - // Create a JSONObject from the JSON - try - { - return parseGroup(new JSONObject(json).getJSONObject("group")); - } - catch (JSONException e) - { - String error = "Unable to parse JSON to Group because " + - e.getMessage(); - throw new ReaderException(error, e); - } - } - - protected static Group parseGroup(JSONObject groupObject) - throws ReaderException, JSONException - { - String uri = groupObject.getString("uri"); - - // Group groupID - int index = uri.indexOf(AC.GROUP_URI); - if (index == -1) - { - String error = "group uri attribute malformed: " + uri; - throw new ReaderException(error); - } - String groupID = uri.substring(AC.GROUP_URI.length()); - - // Group owner - User<? extends Principal> user = null; - if (groupObject.has("owner")) - { - JSONObject ownerObject = groupObject.getJSONObject("owner"); - JSONObject userObject = ownerObject.getJSONObject("user"); - user = UserReader.parseUser(userObject); - } - - Group group = new Group(groupID, user); - - // description - if (groupObject.has("description")) - { - group.description = groupObject.getString("description"); - } - - // lastModified - if (groupObject.has("lastModified")) - { - try - { - DateFormat df = DateUtil.getDateFormat(DateUtil.IVOA_DATE_FORMAT, DateUtil.UTC); - group.lastModified = df.parse(groupObject.getString("lastModified")); - } - catch (ParseException e) - { - String error = "Unable to parse group lastModified because " + e.getMessage(); - - throw new ReaderException(error); - } - } - - // properties - if (groupObject.has("description")) - { - JSONArray propertiesArray = groupObject.getJSONArray("properties"); - for (int i = 0; i < propertiesArray.length(); i++) - { - JSONObject propertiesObject = propertiesArray.getJSONObject(i); - JSONObject propertyObject = propertiesObject.getJSONObject("property"); - group.getProperties().add(GroupPropertyReader.read(propertyObject)); - } - } - - // groupMembers - if (groupObject.has("groupMembers")) - { - JSONArray groupMembersArray = groupObject.getJSONArray("groupMembers"); - for (int i = 0; i < groupMembersArray.length(); i++) - { - JSONObject groupMembersObject = groupMembersArray.getJSONObject(i); - JSONObject groupMemberObject = groupMembersObject.getJSONObject("group"); - group.getGroupMembers().add(parseGroup(groupMemberObject)); - } - } - - // userMembers - if (groupObject.has("userMembers")) - { - JSONArray userMembersArray = groupObject.getJSONArray("userMembers"); - for (int i = 0; i < userMembersArray.length(); i++) - { - JSONObject userMemberObject = userMembersArray.getJSONObject(i); - JSONObject userObject = userMemberObject.getJSONObject("user"); - group.getUserMembers().add(UserReader.parseUser(userObject)); - } - } - - // groupAdmins - if (groupObject.has("groupAdmins")) - { - JSONArray groupAdminsArray = groupObject.getJSONArray("groupAdmins"); - for (int i = 0; i < groupAdminsArray.length(); i++) - { - JSONObject groupAdminsObject = groupAdminsArray.getJSONObject(i); - JSONObject groupAdminObject = groupAdminsObject.getJSONObject("group"); - group.getGroupAdmins().add(parseGroup(groupAdminObject)); - } - } - - // userAdmins - if (groupObject.has("userAdmins")) - { - JSONArray userAdminsArray = groupObject.getJSONArray("userAdmins"); - for (int i = 0; i < userAdminsArray.length(); i++) - { - JSONObject userAdminObject = userAdminsArray.getJSONObject(i); - JSONObject userObject = userAdminObject.getJSONObject("user"); - group.getUserAdmins().add(UserReader.parseUser(userObject)); - } - } - - return group; - } -} diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/GroupWriter.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/GroupWriter.java deleted file mode 100755 index d5a1f1b684a75eb1f3fedd04286df23e95cac6e5..0000000000000000000000000000000000000000 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/GroupWriter.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - ************************************************************************ - ******************* CANADIAN ASTRONOMY DATA CENTRE ******************* - ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** - * - * (c) 2014. (c) 2014. - * Government of Canada Gouvernement du Canada - * National Research Council Conseil national de recherches - * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 - * All rights reserved Tous droits réservés - * - * NRC disclaims any warranties, Le CNRC dénie toute garantie - * expressed, implied, or énoncée, implicite ou légale, - * statutory, of any kind with de quelque nature que ce - * respect to the software, soit, concernant le logiciel, - * including without limitation y compris sans restriction - * any warranty of merchantability toute garantie de valeur - * or fitness for a particular marchande ou de pertinence - * purpose. NRC shall not be pour un usage particulier. - * liable in any event for any Le CNRC ne pourra en aucun cas - * damages, whether direct or être tenu responsable de tout - * indirect, special or general, dommage, direct ou indirect, - * consequential or incidental, particulier ou général, - * arising from the use of the accessoire ou fortuit, résultant - * software. Neither the name de l'utilisation du logiciel. Ni - * of the National Research le nom du Conseil National de - * Council of Canada nor the Recherches du Canada ni les noms - * names of its contributors may de ses participants ne peuvent - * be used to endorse or promote être utilisés pour approuver ou - * products derived from this promouvoir les produits dérivés - * software without specific prior de ce logiciel sans autorisation - * written permission. préalable et particulière - * par écrit. - * - * This file is part of the Ce fichier fait partie du projet - * OpenCADC project. OpenCADC. - * - * OpenCADC is free software: OpenCADC est un logiciel libre ; - * you can redistribute it and/or vous pouvez le redistribuer ou le - * modify it under the terms of modifier suivant les termes de - * the GNU Affero General Public la “GNU Affero General Public - * License as published by the License” telle que publiée - * Free Software Foundation, par la Free Software Foundation - * either version 3 of the : soit la version 3 de cette - * License, or (at your option) licence, soit (à votre gré) - * any later version. toute version ultérieure. - * - * OpenCADC is distributed in the OpenCADC est distribué - * hope that it will be useful, dans l’espoir qu’il vous - * but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE - * without even the implied GARANTIE : sans même la garantie - * warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ - * or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF - * PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence - * General Public License for Générale Publique GNU Affero - * more details. pour plus de détails. - * - * You should have received Vous devriez avoir reçu une - * a copy of the GNU Affero copie de la Licence Générale - * General Public License along Publique GNU Affero avec - * with OpenCADC. If not, see OpenCADC ; si ce n’est - * <http://www.gnu.org/licenses/>. pas le cas, consultez : - * <http://www.gnu.org/licenses/>. - * - * $Revision: 4 $ - * - ************************************************************************ - */ -package ca.nrc.cadc.ac.json; - -import ca.nrc.cadc.ac.AC; -import ca.nrc.cadc.ac.Group; -import ca.nrc.cadc.ac.GroupProperty; -import ca.nrc.cadc.ac.User; -import ca.nrc.cadc.ac.WriterException; -import ca.nrc.cadc.date.DateUtil; -import ca.nrc.cadc.util.StringBuilderWriter; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.BufferedWriter; -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.UnsupportedEncodingException; -import java.io.Writer; -import java.security.Principal; -import java.text.DateFormat; - -public class GroupWriter -{ - /** - * Write a Group to a StringBuilder. - * @param group - * @param builder - * @throws IOException - * @throws WriterException - */ - public static void write(Group group, StringBuilder builder) - throws IOException, WriterException - { - write(group, new StringBuilderWriter(builder)); - } - - /** - * Write a Group to an OutputStream. - * - * @param group Group to write. - * @param out OutputStream to write to. - * @throws IOException if the writer fails to write. - * @throws WriterException - */ - public static void write(Group group, OutputStream out) - throws IOException, WriterException - { - OutputStreamWriter outWriter; - try - { - outWriter = new OutputStreamWriter(out, "UTF-8"); - } - catch (UnsupportedEncodingException e) - { - throw new RuntimeException("UTF-8 encoding not supported", e); - } - write(group, new BufferedWriter(outWriter)); - } - - /** - * Write a Group to a Writer. - * - * @param group Group to write. - * @param writer Writer to write to. - * @throws IOException if the writer fails to write. - * @throws WriterException - */ - public static void write(Group group, Writer writer) - throws IOException, WriterException - { - if (group == null) - { - throw new WriterException("null group"); - } - - try - { - getGroupObject(group).write(writer); - } - catch (JSONException e) - { - final String error = "Unable to create JSON for Group " + - " because " + e.getMessage(); - throw new WriterException(error, e); - } - } - - /** - * - * @param group - * @return - * @throws WriterException - */ - public static JSONObject getGroupObject(Group group) - throws WriterException, JSONException - { - return getGroupObject(group, true); - } - - public static JSONObject getGroupObject(Group group, boolean deepCopy) - throws WriterException, JSONException - { - JSONObject groupObject = new JSONObject(); - groupObject.put("uri", AC.GROUP_URI + group.getID()); - - // Group owner - if (group.getOwner() != null) - { - groupObject.put("owner", UserWriter.getUserObject(group.getOwner())); - } - - if (deepCopy) - { - // Group description - if (group.description != null) - { - groupObject.put("description", group.description); - } - - // lastModified - if (group.lastModified != null) - { - DateFormat df = DateUtil.getDateFormat(DateUtil.IVOA_DATE_FORMAT, DateUtil.UTC); - groupObject.put("lastModified", df.format(group.lastModified)); - } - - // Group properties - if (!group.getProperties().isEmpty()) - { - JSONArray propertiesArray = new JSONArray(); - for (GroupProperty property : group.getProperties()) - { - JSONObject propertyObject = new JSONObject(); - propertyObject.put("property", GroupPropertyWriter.write(property)); - propertiesArray.put(propertyObject); - } - groupObject.put("properties", propertiesArray); - } - - // Group groupMembers. - if ((group.getGroupMembers() != null) && (!group.getGroupMembers().isEmpty())) - { - JSONArray groupMembersArray = new JSONArray(); - for (Group groupMember : group.getGroupMembers()) - { - groupMembersArray.put(getGroupObject(groupMember, false)); - } - groupObject.put("groupMembers", groupMembersArray); - } - - // Group userMembers - if ((group.getUserMembers() != null) && (!group.getUserMembers().isEmpty())) - { - JSONArray userMembersArray = new JSONArray(); - for (User<? extends Principal> userMember : group.getUserMembers()) - { - userMembersArray.put(UserWriter.getUserObject(userMember)); - } - groupObject.put("userMembers", userMembersArray); - } - - // Group groupAdmins. - if ((group.getGroupAdmins() != null) && (!group.getGroupAdmins().isEmpty())) - { - JSONArray groupAdminsArray = new JSONArray(); - for (Group groupAdmin : group.getGroupAdmins()) - { - groupAdminsArray.put(getGroupObject(groupAdmin, false)); - } - groupObject.put("groupAdmins", groupAdminsArray); - } - - // Group userAdmins - if ((group.getUserAdmins() != null) && (!group.getUserAdmins().isEmpty())) - { - JSONArray userAdminsArray = new JSONArray(); - for (User<? extends Principal> userAdmin : group.getUserAdmins()) - { - userAdminsArray.put(UserWriter.getUserObject(userAdmin)); - } - groupObject.put("userAdmins", userAdminsArray); - } - } - - return new JSONObject().put("group", groupObject); - } - -} diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonGroupReader.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonGroupReader.java new file mode 100755 index 0000000000000000000000000000000000000000..a240184be0794193897d8924ce1002747b5ecb4c --- /dev/null +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonGroupReader.java @@ -0,0 +1,173 @@ +/* + ************************************************************************ + ******************* CANADIAN ASTRONOMY DATA CENTRE ******************* + ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** + * + * (c) 2014. (c) 2014. + * Government of Canada Gouvernement du Canada + * National Research Council Conseil national de recherches + * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 + * All rights reserved Tous droits réservés + * + * NRC disclaims any warranties, Le CNRC dénie toute garantie + * expressed, implied, or énoncée, implicite ou légale, + * statutory, of any kind with de quelque nature que ce + * respect to the software, soit, concernant le logiciel, + * including without limitation y compris sans restriction + * any warranty of merchantability toute garantie de valeur + * or fitness for a particular marchande ou de pertinence + * purpose. NRC shall not be pour un usage particulier. + * liable in any event for any Le CNRC ne pourra en aucun cas + * damages, whether direct or être tenu responsable de tout + * indirect, special or general, dommage, direct ou indirect, + * consequential or incidental, particulier ou général, + * arising from the use of the accessoire ou fortuit, résultant + * software. Neither the name de l'utilisation du logiciel. Ni + * of the National Research le nom du Conseil National de + * Council of Canada nor the Recherches du Canada ni les noms + * names of its contributors may de ses participants ne peuvent + * be used to endorse or promote être utilisés pour approuver ou + * products derived from this promouvoir les produits dérivés + * software without specific prior de ce logiciel sans autorisation + * written permission. préalable et particulière + * par écrit. + * + * This file is part of the Ce fichier fait partie du projet + * OpenCADC project. OpenCADC. + * + * OpenCADC is free software: OpenCADC est un logiciel libre ; + * you can redistribute it and/or vous pouvez le redistribuer ou le + * modify it under the terms of modifier suivant les termes de + * the GNU Affero General Public la “GNU Affero General Public + * License as published by the License” telle que publiée + * Free Software Foundation, par la Free Software Foundation + * either version 3 of the : soit la version 3 de cette + * License, or (at your option) licence, soit (à votre gré) + * any later version. toute version ultérieure. + * + * OpenCADC is distributed in the OpenCADC est distribué + * hope that it will be useful, dans l’espoir qu’il vous + * but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE + * without even the implied GARANTIE : sans même la garantie + * warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ + * or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF + * PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence + * General Public License for Générale Publique GNU Affero + * more details. pour plus de détails. + * + * You should have received Vous devriez avoir reçu une + * a copy of the GNU Affero copie de la Licence Générale + * General Public License along Publique GNU Affero avec + * with OpenCADC. If not, see OpenCADC ; si ce n’est + * <http://www.gnu.org/licenses/>. pas le cas, consultez : + * <http://www.gnu.org/licenses/>. + * + * $Revision: 4 $ + * + ************************************************************************ + */ +package ca.nrc.cadc.ac.json; + +import ca.nrc.cadc.ac.Group; +import ca.nrc.cadc.ac.ReaderException; +import ca.nrc.cadc.ac.xml.GroupReader; +import ca.nrc.cadc.xml.JsonInputter; +import org.jdom2.Document; +import org.json.JSONException; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.Scanner; + +public class JsonGroupReader extends GroupReader +{ + /** + * Construct a Group from a InputStream. + * + * @param in InputStream. + * @return Group Group. + * @throws ReaderException + * @throws IOException + */ + @Override + public Group read(InputStream in) + throws ReaderException, IOException + { + if (in == null) + { + throw new IOException("stream closed"); + } + InputStreamReader reader; + + Scanner s = new Scanner(in).useDelimiter("\\A"); + String json = s.hasNext() ? s.next() : ""; + + return read(json); + } + + /** + * Construct a Group from a Reader. + * + * @param reader Reader. + * @return Group Group. + * @throws ReaderException + * @throws IOException + */ + @Override + public Group read(Reader reader) + throws ReaderException, IOException + { + if (reader == null) + { + throw new IllegalArgumentException("reader must not be null"); + } + + Scanner s = new Scanner(reader).useDelimiter("\\A"); + String json = s.hasNext() ? s.next() : ""; + + return read(json); + } + + /** + * Construct a Group from an JSON String source. + * + * @param json String of JSON. + * @return Group Group. + * @throws ReaderException + * @throws IOException + */ + @Override + public Group read(String json) + throws ReaderException, IOException + { + if (json == null) + { + throw new IllegalArgumentException("JSON must not be null"); + } + + // Create a JSONObject from the JSON + try + { + JsonInputter jsonInputter = new JsonInputter(); + jsonInputter.getListElementMap().put("identities", "identity"); + jsonInputter.getListElementMap().put("properties", "property"); + jsonInputter.getListElementMap().put("details", "userDetails"); + jsonInputter.getListElementMap().put("groupMembers", "group"); + jsonInputter.getListElementMap().put("groupAdmins", "group"); + jsonInputter.getListElementMap().put("userMembers", "user"); + jsonInputter.getListElementMap().put("userAdmins", "user"); + + Document document = jsonInputter.input(json); + return GroupReader.parseGroup(document.getRootElement()); + } + catch (JSONException e) + { + String error = "Unable to parse JSON to Group because " + + e.getMessage(); + throw new ReaderException(error, e); + } + } + +} diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonGroupWriter.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonGroupWriter.java new file mode 100755 index 0000000000000000000000000000000000000000..2db229327ce52306744846b95f0a4ffb19f310ce --- /dev/null +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonGroupWriter.java @@ -0,0 +1,160 @@ +/* + ************************************************************************ + ******************* CANADIAN ASTRONOMY DATA CENTRE ******************* + ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** + * + * (c) 2014. (c) 2014. + * Government of Canada Gouvernement du Canada + * National Research Council Conseil national de recherches + * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 + * All rights reserved Tous droits réservés + * + * NRC disclaims any warranties, Le CNRC dénie toute garantie + * expressed, implied, or énoncée, implicite ou légale, + * statutory, of any kind with de quelque nature que ce + * respect to the software, soit, concernant le logiciel, + * including without limitation y compris sans restriction + * any warranty of merchantability toute garantie de valeur + * or fitness for a particular marchande ou de pertinence + * purpose. NRC shall not be pour un usage particulier. + * liable in any event for any Le CNRC ne pourra en aucun cas + * damages, whether direct or être tenu responsable de tout + * indirect, special or general, dommage, direct ou indirect, + * consequential or incidental, particulier ou général, + * arising from the use of the accessoire ou fortuit, résultant + * software. Neither the name de l'utilisation du logiciel. Ni + * of the National Research le nom du Conseil National de + * Council of Canada nor the Recherches du Canada ni les noms + * names of its contributors may de ses participants ne peuvent + * be used to endorse or promote être utilisés pour approuver ou + * products derived from this promouvoir les produits dérivés + * software without specific prior de ce logiciel sans autorisation + * written permission. préalable et particulière + * par écrit. + * + * This file is part of the Ce fichier fait partie du projet + * OpenCADC project. OpenCADC. + * + * OpenCADC is free software: OpenCADC est un logiciel libre ; + * you can redistribute it and/or vous pouvez le redistribuer ou le + * modify it under the terms of modifier suivant les termes de + * the GNU Affero General Public la “GNU Affero General Public + * License as published by the License” telle que publiée + * Free Software Foundation, par la Free Software Foundation + * either version 3 of the : soit la version 3 de cette + * License, or (at your option) licence, soit (à votre gré) + * any later version. toute version ultérieure. + * + * OpenCADC is distributed in the OpenCADC est distribué + * hope that it will be useful, dans l’espoir qu’il vous + * but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE + * without even the implied GARANTIE : sans même la garantie + * warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ + * or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF + * PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence + * General Public License for Générale Publique GNU Affero + * more details. pour plus de détails. + * + * You should have received Vous devriez avoir reçu une + * a copy of the GNU Affero copie de la Licence Générale + * General Public License along Publique GNU Affero avec + * with OpenCADC. If not, see OpenCADC ; si ce n’est + * <http://www.gnu.org/licenses/>. pas le cas, consultez : + * <http://www.gnu.org/licenses/>. + * + * $Revision: 4 $ + * + ************************************************************************ + */ +package ca.nrc.cadc.ac.json; + +import ca.nrc.cadc.ac.Group; +import ca.nrc.cadc.ac.WriterException; +import ca.nrc.cadc.ac.xml.GroupWriter; +import ca.nrc.cadc.util.StringBuilderWriter; +import ca.nrc.cadc.xml.JsonOutputter; +import org.jdom2.Document; +import org.jdom2.Element; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; +import java.io.Writer; + +public class JsonGroupWriter extends GroupWriter +{ + /** + * Write a Group to a StringBuilder. + * @param group + * @param builder + * @throws IOException + * @throws WriterException + */ + public void write(Group group, StringBuilder builder) + throws IOException, WriterException + { + write(group, new StringBuilderWriter(builder)); + } + + /** + * Write a Group to an OutputStream. + * + * @param group Group to write. + * @param out OutputStream to write to. + * @throws IOException if the writer fails to write. + * @throws WriterException + */ + @Override + public void write(Group group, OutputStream out) + throws IOException, WriterException + { + OutputStreamWriter outWriter; + try + { + outWriter = new OutputStreamWriter(out, "UTF-8"); + } + catch (UnsupportedEncodingException e) + { + throw new RuntimeException("UTF-8 encoding not supported", e); + } + write(group, new BufferedWriter(outWriter)); + } + + /** + * Write a Group to a Writer. + * + * @param group Group to write. + * @param writer Writer to write to. + * @throws IOException if the writer fails to write. + * @throws WriterException + */ + @Override + public void write(Group group, Writer writer) + throws IOException, WriterException + { + if (group == null) + { + throw new WriterException("null group"); + } + + Element children = GroupWriter.getGroupElement(group); + Element groupElement = new Element("group"); + groupElement.addContent(children); + Document document = new Document(); + document.setRootElement(groupElement); + + JsonOutputter jsonOutputter = new JsonOutputter(); + jsonOutputter.getListElementNames().add("properties"); + jsonOutputter.getListElementNames().add("userMembers"); + jsonOutputter.getListElementNames().add("groupMembers"); + jsonOutputter.getListElementNames().add("userAdmins"); + jsonOutputter.getListElementNames().add("groupAdmins"); + jsonOutputter.getListElementNames().add("identities"); + jsonOutputter.getListElementNames().add("details"); + + jsonOutputter.output(document, writer); + } + +} diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/UsersWriter.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserListWriter.java similarity index 99% rename from projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/UsersWriter.java rename to projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserListWriter.java index 308148bcdadde1530c994bc1bea70a7a61f9cd14..5bf9317a44b6c30c61b50f569471f652dc875daa 100644 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/UsersWriter.java +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserListWriter.java @@ -80,7 +80,7 @@ import java.util.Map; /** * Class to write out, as JSON, a list of user entries. */ -public class UsersWriter +public class JsonUserListWriter { public static void write(final Map<String, PersonalDetails> users, final Writer writer) throws IOException diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/UserReader.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserReader.java similarity index 76% rename from projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/UserReader.java rename to projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserReader.java index b6aedd7f92293b5f7c49580ff44fd5ef20078567..2c4a8e376ec338c5fa2157d08767ca79f8999d5d 100755 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/UserReader.java +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserReader.java @@ -70,10 +70,10 @@ package ca.nrc.cadc.ac.json; import ca.nrc.cadc.ac.ReaderException; import ca.nrc.cadc.ac.User; -import ca.nrc.cadc.ac.UserDetails; -import org.json.JSONArray; +import ca.nrc.cadc.ac.xml.UserReader; +import ca.nrc.cadc.xml.JsonInputter; +import org.jdom2.Document; import org.json.JSONException; -import org.json.JSONObject; import java.io.IOException; import java.io.InputStream; @@ -81,7 +81,7 @@ import java.io.Reader; import java.security.Principal; import java.util.Scanner; -public class UserReader +public class JsonUserReader extends UserReader { /** * Construct a User from a InputStream. @@ -91,7 +91,8 @@ public class UserReader * @throws ReaderException * @throws IOException */ - public static User<Principal> read(InputStream in) + @Override + public User<Principal> read(InputStream in) throws IOException { if (in == null) @@ -113,7 +114,8 @@ public class UserReader * @throws ReaderException * @throws IOException */ - public static User<Principal> read(Reader reader) + @Override + public User<Principal> read(Reader reader) throws IOException { if (reader == null) @@ -135,7 +137,8 @@ public class UserReader * @throws ReaderException * @throws IOException */ - public static User<Principal> read(String json) + @Override + public User<Principal> read(String json) throws IOException { if (json == null || json.isEmpty()) @@ -146,50 +149,19 @@ public class UserReader // Create a JSONObject from the JSON try { - return parseUser(new JSONObject(json).getJSONObject("user")); + JsonInputter jsonInputter = new JsonInputter(); + jsonInputter.getListElementMap().put("identities", "identity"); + jsonInputter.getListElementMap().put("details", "userDetails"); + + Document document = jsonInputter.input(json); + return UserReader.parseUser(document.getRootElement()); } catch (JSONException e) { String error = "Unable to parse JSON to User because " + - e.getMessage(); + e.getMessage(); throw new ReaderException(error, e); } } - protected static User<Principal> parseUser(JSONObject userObject) - throws ReaderException, JSONException - { - JSONObject userIDObject = userObject.getJSONObject("userID"); - JSONObject userIDIdentityObject = userIDObject.getJSONObject("identity"); - - Principal userID = IdentityReader.read(userIDIdentityObject); - User<Principal> user = new User<Principal>(userID); - - // identities - if (userObject.has("identities")) - { - JSONArray identitiesArray = userObject.getJSONArray("identities"); - for (int i = 0; i < identitiesArray.length(); i++) - { - JSONObject identitiesObject = identitiesArray.getJSONObject(i); - JSONObject identityObject = identitiesObject.getJSONObject(("identity")); - user.getIdentities().add(IdentityReader.read(identityObject)); - } - } - - // details - if (userObject.has("details")) - { - JSONArray detailsArray = userObject.getJSONArray("details"); - for (int i = 0; i < detailsArray.length(); i++) - { - JSONObject detailsObject = detailsArray.getJSONObject(i); - JSONObject userDetailsObject = detailsObject.getJSONObject(UserDetails.NAME); - user.details.add(UserDetailsReader.read(userDetailsObject)); - } - } - - return user; - } - } diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/UserRequestReader.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserRequestReader.java similarity index 84% rename from projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/UserRequestReader.java rename to projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserRequestReader.java index 4e0ed7a9d0095fa85fb07c6079c50b2b10dfb359..b8d61e8cea9567a2caac1beb562766a5e05b1bfa 100644 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/UserRequestReader.java +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserRequestReader.java @@ -69,46 +69,20 @@ package ca.nrc.cadc.ac.json; import ca.nrc.cadc.ac.ReaderException; -import ca.nrc.cadc.ac.User; import ca.nrc.cadc.ac.UserRequest; +import ca.nrc.cadc.ac.xml.UserRequestReader; +import ca.nrc.cadc.xml.JsonInputter; +import org.jdom2.Document; import org.json.JSONException; -import org.json.JSONObject; -import java.io.*; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; import java.security.Principal; import java.util.Scanner; -public class UserRequestReader +public class JsonUserRequestReader extends UserRequestReader { - /** - * Construct a UserRequest from an XML String source. - * - * @param json String of the XML. - * @return UserRequest UserRequest. - * @throws IOException - */ - public static UserRequest<Principal> read(String json) - throws IOException - { - if (json == null) - { - throw new IllegalArgumentException("XML must not be null"); - } - else - { - try - { - return parseUserRequest(new JSONObject(json)); - } - catch (JSONException e) - { - String error = "Unable to parse JSON to User because " + - e.getMessage(); - throw new ReaderException(error, e); - } - } - } - /** * Construct a User from a InputStream. * @@ -117,7 +91,8 @@ public class UserRequestReader * @throws ReaderException * @throws IOException */ - public static UserRequest<Principal> read(InputStream in) + @Override + public UserRequest<Principal> read(InputStream in) throws IOException { if (in == null) @@ -139,7 +114,8 @@ public class UserRequestReader * @throws ReaderException * @throws IOException */ - public static UserRequest<Principal> read(Reader reader) + @Override + public UserRequest<Principal> read(Reader reader) throws IOException { if (reader == null) @@ -153,16 +129,39 @@ public class UserRequestReader return read(json); } - - protected static UserRequest<Principal> parseUserRequest( - JSONObject userRequestObject) - throws ReaderException, JSONException + /** + * Construct a UserRequest from an JSON String source. + * + * @param json String of the JSON. + * @return UserRequest UserRequest. + * @throws IOException + */ + @Override + public UserRequest<Principal> read(String json) + throws IOException { - final User<Principal> user = - ca.nrc.cadc.ac.json.UserReader.parseUser( - userRequestObject.getJSONObject("user")); + if (json == null) + { + throw new IllegalArgumentException("JSON must not be null"); + } + else + { + try + { + JsonInputter jsonInputter = new JsonInputter(); + jsonInputter.getListElementMap().put("identities", "identity"); + jsonInputter.getListElementMap().put("details", "userDetails"); - return new UserRequest<Principal>(user, userRequestObject. - getString("password")); + Document document = jsonInputter.input(json); + return UserRequestReader.parseUserRequest(document.getRootElement()); + } + catch (JSONException e) + { + String error = "Unable to parse JSON to User because " + + e.getMessage(); + throw new ReaderException(error, e); + } + } } + } diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserRequestWriter.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserRequestWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..7ebb07a652a9b972252d528e869ac86938d33c12 --- /dev/null +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserRequestWriter.java @@ -0,0 +1,63 @@ +package ca.nrc.cadc.ac.json; + +import ca.nrc.cadc.ac.UserRequest; +import ca.nrc.cadc.ac.WriterException; +import ca.nrc.cadc.ac.xml.UserRequestWriter; +import ca.nrc.cadc.util.StringBuilderWriter; +import ca.nrc.cadc.xml.JsonOutputter; +import org.jdom2.Document; +import org.jdom2.Element; + +import java.io.IOException; +import java.io.Writer; +import java.security.Principal; + +/** + * Class to write a JSON representation of a UserRequest object. + */ +public class JsonUserRequestWriter extends UserRequestWriter +{ + /** + * Write a UserRequest to a StringBuilder. + * + * @param userRequest UserRequest to write. + * @param builder StringBuilder to write to. + * @throws java.io.IOException if the writer fails to write. + * @throws WriterException + */ + public void write(UserRequest<? extends Principal> userRequest, StringBuilder builder) + throws IOException, WriterException + { + write(userRequest, new StringBuilderWriter(builder)); + } + + /** + * Write a UserRequest to a Writer. + * + * @param userRequest UserRequest to write. + * @param writer Writer to write to. + * @throws IOException if the writer fails to write. + * @throws WriterException + */ + public static void write(UserRequest<? extends Principal> userRequest, Writer writer) + throws IOException, WriterException + { + if (userRequest == null) + { + throw new WriterException("null UserRequest"); + } + + Element children = UserRequestWriter.getUserRequestElement(userRequest); + Element userRequestElement = new Element("userRequest"); + userRequestElement.addContent(children); + Document document = new Document(); + document.setRootElement(userRequestElement); + + JsonOutputter jsonOutputter = new JsonOutputter(); + jsonOutputter.getListElementNames().add("identities"); + jsonOutputter.getListElementNames().add("details"); + + jsonOutputter.output(document, writer); + } + +} diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/UserWriter.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserWriter.java similarity index 72% rename from projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/UserWriter.java rename to projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserWriter.java index 2865235807f885d24cbe3986b370c50e5bf8d753..444a670a4453e0bd2e6b7f481fb9247e73df0525 100755 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/UserWriter.java +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/json/JsonUserWriter.java @@ -71,7 +71,12 @@ package ca.nrc.cadc.ac.json; import ca.nrc.cadc.ac.User; import ca.nrc.cadc.ac.UserDetails; import ca.nrc.cadc.ac.WriterException; +import ca.nrc.cadc.ac.xml.GroupWriter; +import ca.nrc.cadc.ac.xml.UserWriter; import ca.nrc.cadc.util.StringBuilderWriter; +import ca.nrc.cadc.xml.JsonOutputter; +import org.jdom2.Document; +import org.jdom2.Element; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -85,7 +90,7 @@ import java.io.Writer; import java.security.Principal; import java.util.Set; -public class UserWriter +public class JsonUserWriter extends UserWriter { /** * Write a User as a JSON string to a StringBuilder. @@ -95,7 +100,8 @@ public class UserWriter * @throws IOException if the writer fails to write. * @throws WriterException */ - public static void write(User<? extends Principal> user, StringBuilder builder) + @Override + public void write(User<? extends Principal> user, StringBuilder builder) throws IOException, WriterException { write(user, new StringBuilderWriter(builder)); @@ -109,7 +115,8 @@ public class UserWriter * @throws IOException if the writer fails to write. * @throws WriterException */ - public static void write(User<? extends Principal> user, OutputStream out) + @Override + public void write(User<? extends Principal> user, OutputStream out) throws IOException, WriterException { OutputStreamWriter outWriter; @@ -132,7 +139,8 @@ public class UserWriter * @throws IOException if the writer fails to write. * @throws WriterException */ - public static void write(User<? extends Principal> user, Writer writer) + @Override + public void write(User<? extends Principal> user, Writer writer) throws IOException, WriterException { if (user == null) @@ -140,62 +148,17 @@ public class UserWriter throw new WriterException("null User"); } - try - { - getUserObject(user).write(writer); - } - catch (JSONException e) - { - final String error = "Unable to create JSON for User " + - " because " + e.getMessage(); - throw new WriterException(error, e); - } - } + Element children = UserWriter.getUserElement(user); + Element userElement = new Element("user"); + userElement.addContent(children); + Document document = new Document(); + document.setRootElement(userElement); - /** - * Build a User JSONObject from a User. - * - * @param user User. - * @return JSONObject. - * @throws WriterException - */ - public static JSONObject getUserObject(User<? extends Principal> user) - throws WriterException, JSONException - { - JSONObject userObject = new JSONObject(); - JSONObject userIDIdentityObject = new JSONObject(); - userIDIdentityObject.put("identity", IdentityWriter.write(user.getUserID())); - userObject.put("userID", userIDIdentityObject); - - // identities - Set<Principal> identities = user.getIdentities(); - if (!identities.isEmpty()) - { - JSONArray identityArray = new JSONArray(); - for (Principal identity : identities) - { - JSONObject identityObject = new JSONObject(); - identityObject.put("identity" , IdentityWriter.write(identity)); - identityArray.put(identityObject); - } - userObject.put("identities", identityArray); - } - - // details - if (!user.details.isEmpty()) - { - JSONArray detailsArray = new JSONArray(); - Set<UserDetails> userDetails = user.details; - for (UserDetails userDetail : userDetails) - { - JSONObject detailsObject = new JSONObject(); - detailsObject.put(UserDetails.NAME , UserDetailsWriter.write(userDetail)); - detailsArray.put(detailsObject); - } - userObject.put("details", detailsArray); - } + JsonOutputter jsonOutputter = new JsonOutputter(); + jsonOutputter.getListElementNames().add("identities"); + jsonOutputter.getListElementNames().add("details"); - return new JSONObject().put("user", userObject); + jsonOutputter.output(document, writer); } } diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/GroupsReader.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/GroupListReader.java similarity index 95% rename from projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/GroupsReader.java rename to projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/GroupListReader.java index c0c31fbe4a2ecfbbb7f44e0baf411cf15f08745c..cd962918e443f8d3db33cd7eead08d475285543d 100755 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/GroupsReader.java +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/GroupListReader.java @@ -84,7 +84,11 @@ import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.JDOMException; -public class GroupsReader +/** + * Class to read an XML representation of a list of Groups + * into a List of Group objects. + */ +public class GroupListReader { /** * Construct a list of Group's from an XML String source. @@ -95,7 +99,7 @@ public class GroupsReader * @throws java.io.IOException * @throws java.net.URISyntaxException */ - public static List<Group> read(String xml) + public List<Group> read(String xml) throws ReaderException, IOException, URISyntaxException { if (xml == null) @@ -114,7 +118,7 @@ public class GroupsReader * @throws java.io.IOException * @throws java.net.URISyntaxException */ - public static List<Group> read(InputStream in) + public List<Group> read(InputStream in) throws ReaderException, IOException, URISyntaxException { if (in == null) @@ -142,7 +146,7 @@ public class GroupsReader * @throws java.io.IOException * @throws java.net.URISyntaxException */ - public static List<Group> read(Reader reader) + public List<Group> read(Reader reader) throws ReaderException, IOException, URISyntaxException { if (reader == null) @@ -182,7 +186,7 @@ public class GroupsReader List<Element> groupElements = groupsElement.getChildren("group"); for (Element groupElement : groupElements) { - groups.add(ca.nrc.cadc.ac.xml.GroupReader.parseGroup(groupElement)); + groups.add(GroupReader.parseGroup(groupElement)); } return groups; diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/GroupsWriter.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/GroupListWriter.java similarity index 90% rename from projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/GroupsWriter.java rename to projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/GroupListWriter.java index fb92d2cd268c54985b379954a90493888043de8e..b3707fb3d7ce6bb3e2f3c16a6e9f59c01606b786 100755 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/GroupsWriter.java +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/GroupListWriter.java @@ -15,7 +15,10 @@ import org.jdom2.Element; import org.jdom2.output.Format; import org.jdom2.output.XMLOutputter; -public class GroupsWriter +/** + * Class to write a XML representation from a Collection of Groups objects. + */ +public class GroupListWriter { /** * Write a List of Group's to a StringBuilder. @@ -24,7 +27,7 @@ public class GroupsWriter * @throws java.io.IOException * @throws WriterException */ - public static void write(Collection<Group> groups, StringBuilder builder) + public void write(Collection<Group> groups, StringBuilder builder) throws IOException, WriterException { write(groups, new StringBuilderWriter(builder)); @@ -38,7 +41,7 @@ public class GroupsWriter * @throws IOException if the writer fails to write. * @throws WriterException */ - public static void write(Collection<Group> groups, OutputStream out) + public void write(Collection<Group> groups, OutputStream out) throws IOException, WriterException { OutputStreamWriter outWriter; @@ -61,7 +64,7 @@ public class GroupsWriter * @throws IOException if the writer fails to write. * @throws WriterException */ - public static void write(Collection<Group> groups, Writer writer) + public void write(Collection<Group> groups, Writer writer) throws IOException, WriterException { if (groups == null) diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/GroupReader.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/GroupReader.java index 8cfc37eec446e677bb9f648cfe4a52d2dc82f2b9..0f0d1dca1233d54a01c9cbb0da2ba9685fffc18c 100755 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/GroupReader.java +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/GroupReader.java @@ -90,6 +90,9 @@ import java.text.DateFormat; import java.text.ParseException; import java.util.List; +/** + * Class to read a XML representation of a Group to a Group object. + */ public class GroupReader { @@ -102,7 +105,7 @@ public class GroupReader * @throws java.io.IOException * @throws java.net.URISyntaxException */ - public static Group read(String xml) + public Group read(String xml) throws ReaderException, IOException, URISyntaxException { if (xml == null) @@ -121,7 +124,7 @@ public class GroupReader * @throws java.io.IOException * @throws java.net.URISyntaxException */ - public static Group read(InputStream in) + public Group read(InputStream in) throws ReaderException, IOException { if (in == null) @@ -149,7 +152,7 @@ public class GroupReader * @throws java.io.IOException * @throws java.net.URISyntaxException */ - public static Group read(Reader reader) + public Group read(Reader reader) throws ReaderException, IOException { if (reader == null) @@ -181,7 +184,7 @@ public class GroupReader return parseGroup(root); } - protected static Group parseGroup(Element groupElement) + public static Group parseGroup(Element groupElement) throws ReaderException { String uri = groupElement.getAttributeValue("uri"); diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/GroupWriter.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/GroupWriter.java index 18f307a80afea5fb5552e34f2b9c9b338e871c1b..380ba79a8d7ec2fa8e203f8e7f6d8bafbb51ff0e 100755 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/GroupWriter.java +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/GroupWriter.java @@ -90,6 +90,9 @@ import java.io.Writer; import java.security.Principal; import java.text.DateFormat; +/** + * Class to write a XML representation of a Group object. + */ public class GroupWriter { /** @@ -99,7 +102,7 @@ public class GroupWriter * @throws java.io.IOException * @throws WriterException */ - public static void write(Group group, StringBuilder builder) + public void write(Group group, StringBuilder builder) throws IOException, WriterException { write(group, new StringBuilderWriter(builder)); @@ -113,7 +116,7 @@ public class GroupWriter * @throws IOException if the writer fails to write. * @throws WriterException */ - public static void write(Group group, OutputStream out) + public void write(Group group, OutputStream out) throws IOException, WriterException { OutputStreamWriter outWriter; @@ -136,7 +139,7 @@ public class GroupWriter * @throws IOException if the writer fails to write. * @throws WriterException */ - public static void write(Group group, Writer writer) + public void write(Group group, Writer writer) throws IOException, WriterException { if (group == null) diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UsersWriter.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UserListWriter.java similarity index 96% rename from projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UsersWriter.java rename to projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UserListWriter.java index 757af4901c0a2572ac563350ca76e142dd7d12ea..f08d4de4c4ba371da692b858c25e51198cb6abe0 100644 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UsersWriter.java +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UserListWriter.java @@ -78,7 +78,10 @@ import java.io.IOException; import java.io.Writer; import java.util.Map; -public class UsersWriter +/** + * Class to write a XML representation of a Collection of User's. + */ +public class UserListWriter { /** * Write the Map of User entries as XML. @@ -87,8 +90,8 @@ public class UsersWriter * @param writer The Writer to output to. * @throws IOException Any writing errors. */ - public static void write(final Map<String, PersonalDetails> users, - final Writer writer) throws IOException + public void write(final Map<String, PersonalDetails> users, + final Writer writer) throws IOException { // Create the root users Element. final Element usersElement = new Element("users"); diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UserReader.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UserReader.java index e9b957c29ed85fcc8133c781a2b8618e15650116..0accd9da28358bd855b9b73c0d10ce8265044872 100755 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UserReader.java +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UserReader.java @@ -85,6 +85,9 @@ import java.net.URISyntaxException; import java.security.Principal; import java.util.List; +/** + * Class to read a XML representation of a User to a User object. + */ public class UserReader { /** @@ -96,7 +99,7 @@ public class UserReader * @throws java.io.IOException * @throws java.net.URISyntaxException */ - public static User<Principal> read(String xml) + public User<Principal> read(String xml) throws IOException, URISyntaxException { if (xml == null) @@ -113,7 +116,7 @@ public class UserReader * @return User User. * @throws java.io.IOException */ - public static User<Principal> read(InputStream in) + public User<Principal> read(InputStream in) throws IOException { if (in == null) @@ -140,7 +143,7 @@ public class UserReader * @throws ReaderException * @throws java.io.IOException */ - public static User<Principal> read(Reader reader) + public User<Principal> read(Reader reader) throws IOException { if (reader == null) @@ -166,7 +169,7 @@ public class UserReader return parseUser(root); } - protected static User<Principal> parseUser(Element userElement) + public static User<Principal> parseUser(Element userElement) throws ReaderException { // userID element of the User element @@ -185,7 +188,8 @@ public class UserReader throw new ReaderException(error); } - Principal userID = IdentityReader.read(userIDIdentityElement); + IdentityReader identityReader = new IdentityReader(); + Principal userID = identityReader.read(userIDIdentityElement); User<Principal> user = new User<Principal>(userID); @@ -196,7 +200,7 @@ public class UserReader List<Element> identityElements = identitiesElement.getChildren("identity"); for (Element identityElement : identityElements) { - user.getIdentities().add(IdentityReader.read(identityElement)); + user.getIdentities().add(identityReader.read(identityElement)); } } @@ -205,10 +209,11 @@ public class UserReader Element detailsElement = userElement.getChild("details"); if (detailsElement != null) { + UserDetailsReader userDetailsReader = new UserDetailsReader(); List<Element> userDetailsElements = detailsElement.getChildren("userDetails"); for (Element userDetailsElement : userDetailsElements) { - user.details.add(UserDetailsReader.read(userDetailsElement)); + user.details.add(userDetailsReader.read(userDetailsElement)); } } diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UserRequestReader.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UserRequestReader.java index da30cafda3aa6e952fa5eec3682318f9543b5555..e44eba1e4dc37fe8f9fa81b0f7b9629bf271e65e 100644 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UserRequestReader.java +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UserRequestReader.java @@ -84,6 +84,9 @@ import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.JDOMException; +/** + * Class to read a XML representation of a UserRequest to a UserRequest object. + */ public class UserRequestReader { /** @@ -93,7 +96,7 @@ public class UserRequestReader * @return UserRequest UserRequest. * @throws java.io.IOException */ - public static UserRequest<Principal> read(String xml) + public UserRequest<Principal> read(String xml) throws IOException { if (xml == null) @@ -111,7 +114,7 @@ public class UserRequestReader * @throws ReaderException * @throws java.io.IOException */ - public static UserRequest<Principal> read(InputStream in) + public UserRequest<Principal> read(InputStream in) throws IOException { if (in == null) @@ -138,7 +141,7 @@ public class UserRequestReader * @throws ReaderException * @throws java.io.IOException */ - public static UserRequest<Principal> read(Reader reader) + public UserRequest<Principal> read(Reader reader) throws IOException { if (reader == null) @@ -186,6 +189,6 @@ public class UserRequestReader } String password = passwordElement.getText(); - return new UserRequest<Principal>(user, password); + return new UserRequest<Principal>(user, password.toCharArray()); } } diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UserRequestWriter.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UserRequestWriter.java index 10aaf852a0fd05e5add47518984e50ce132856cc..fe0ffee96a6fbbd1a9e9a70f77d575dfbdf0a629 100644 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UserRequestWriter.java +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UserRequestWriter.java @@ -81,6 +81,9 @@ import java.io.IOException; import java.io.Writer; import java.security.Principal; +/** + * Class to write a XML representation of a UserRequest object. + */ public class UserRequestWriter { /** @@ -91,7 +94,7 @@ public class UserRequestWriter * @throws java.io.IOException if the writer fails to write. * @throws WriterException */ - public static void write(UserRequest<? extends Principal> userRequest, StringBuilder builder) + public void write(UserRequest<? extends Principal> userRequest, StringBuilder builder) throws IOException, WriterException { write(userRequest, new StringBuilderWriter(builder)); @@ -135,7 +138,7 @@ public class UserRequestWriter // password element Element passwordElement = new Element("password"); - passwordElement.setText(userRequest.getPassword()); + passwordElement.setText(String.valueOf(userRequest.getPassword())); userRequestElement.addContent(passwordElement); return userRequestElement; diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UserWriter.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UserWriter.java index b1d6642de691ebc47e3516054b08bdb0a640976a..86327ad8f27e7e77bfaa4b17291fe4d8830e2fbf 100755 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UserWriter.java +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/xml/UserWriter.java @@ -86,6 +86,9 @@ import java.io.Writer; import java.security.Principal; import java.util.Set; +/** + * Class to write a XML representation of a User object. + */ public class UserWriter { /** @@ -96,7 +99,7 @@ public class UserWriter * @throws java.io.IOException if the writer fails to write. * @throws WriterException */ - public static void write(User<? extends Principal> user, StringBuilder builder) + public void write(User<? extends Principal> user, StringBuilder builder) throws IOException, WriterException { write(user, new StringBuilderWriter(builder)); @@ -110,7 +113,7 @@ public class UserWriter * @throws IOException if the writer fails to write. * @throws WriterException */ - public static void write(User<? extends Principal> user, OutputStream out) + public void write(User<? extends Principal> user, OutputStream out) throws IOException, WriterException { OutputStreamWriter outWriter; @@ -133,7 +136,7 @@ public class UserWriter * @throws IOException if the writer fails to write. * @throws WriterException */ - public static void write(User<? extends Principal> user, Writer writer) + public void write(User<? extends Principal> user, Writer writer) throws IOException, WriterException { if (user == null) @@ -158,8 +161,9 @@ public class UserWriter Element userElement = new Element("user"); // userID element + IdentityWriter identityWriter = new IdentityWriter(); Element userIDElement = new Element("userID"); - userIDElement.addContent(IdentityWriter.write(user.getUserID())); + userIDElement.addContent(identityWriter.write(user.getUserID())); userElement.addContent(userIDElement); // identities @@ -169,7 +173,7 @@ public class UserWriter Element identitiesElement = new Element("identities"); for (Principal identity : identities) { - identitiesElement.addContent(IdentityWriter.write(identity)); + identitiesElement.addContent(identityWriter.write(identity)); } userElement.addContent(identitiesElement); } @@ -177,11 +181,12 @@ public class UserWriter // details if (!user.details.isEmpty()) { + UserDetailsWriter userDetailsWriter = new UserDetailsWriter(); Element detailsElement = new Element("details"); Set<UserDetails> userDetails = user.details; for (UserDetails userDetail : userDetails) { - detailsElement.addContent(UserDetailsWriter.write(userDetail)); + detailsElement.addContent(userDetailsWriter.write(userDetail)); } userElement.addContent(detailsElement); } diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/UserRequestTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/UserRequestTest.java index 9507d25e5b83156d2627652c90560565c4d30ee3..7bc85ed92c3c65e1ddd07c0b4c543ea4e6790a02 100644 --- a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/UserRequestTest.java +++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/UserRequestTest.java @@ -83,7 +83,9 @@ public class UserRequestTest @Test public void simpleEqualityTests() throws Exception { - UserRequest<HttpPrincipal> ur1 = new UserRequest<HttpPrincipal>(new User(new HttpPrincipal(("foo"))), "password"); + UserRequest<HttpPrincipal> ur1 = + new UserRequest<HttpPrincipal>( + new User<HttpPrincipal>(new HttpPrincipal(("foo"))), "password".toCharArray()); UserRequest<HttpPrincipal> ur2 = ur1; assertEquals(ur1, ur2); assertEquals(ur1.getUser(), ur2.getUser()); diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/client/JSONUserListInputStreamWrapperTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/client/JsonUserListInputStreamWrapperTest.java similarity index 96% rename from projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/client/JSONUserListInputStreamWrapperTest.java rename to projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/client/JsonUserListInputStreamWrapperTest.java index fe977e4e3e5120c17b8e407df7bc210767384099..d8bd34ea6a1aae47bc8b0bd4b7182f3838932329 100644 --- a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/client/JSONUserListInputStreamWrapperTest.java +++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/client/JsonUserListInputStreamWrapperTest.java @@ -80,15 +80,15 @@ import org.junit.Test; import static org.junit.Assert.*; -public class JSONUserListInputStreamWrapperTest +public class JsonUserListInputStreamWrapperTest { @Test public void readInputStream() throws Exception { final List<User<HttpPrincipal>> output = new ArrayList<User<HttpPrincipal>>(); - final JSONUserListInputStreamWrapper testSubject = - new JSONUserListInputStreamWrapper(output); + final JsonUserListInputStreamWrapper testSubject = + new JsonUserListInputStreamWrapper(output); final InputStream inputStream = new ByteArrayInputStream("[{\"id\":\"CADCTest\",\"firstName\":\"CADCtest\",\"lastName\":\"USER\"}\n,{\"id\":\"User_2\",\"firstName\":\"User\",\"lastName\":\"2\"}]".getBytes()); diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/GroupReaderWriterTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/JsonGroupReaderWriterTest.java similarity index 74% rename from projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/GroupReaderWriterTest.java rename to projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/JsonGroupReaderWriterTest.java index b60eee86191be9b62deda3174b51b9a1fe55a5e3..1de1fab5bf1cf8acc3e633644719c1204c55fb2f 100644 --- a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/GroupReaderWriterTest.java +++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/JsonGroupReaderWriterTest.java @@ -70,11 +70,16 @@ package ca.nrc.cadc.ac.json; import ca.nrc.cadc.ac.Group; import ca.nrc.cadc.ac.GroupProperty; +import ca.nrc.cadc.ac.PersonalDetails; +import ca.nrc.cadc.ac.PosixDetails; import ca.nrc.cadc.ac.User; import ca.nrc.cadc.ac.WriterException; import ca.nrc.cadc.auth.HttpPrincipal; import ca.nrc.cadc.auth.OpenIdPrincipal; +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.x500.X500Principal; @@ -93,9 +98,15 @@ import static org.junit.Assert.fail; * * @author jburke */ -public class GroupReaderWriterTest +public class JsonGroupReaderWriterTest { - private static Logger log = Logger.getLogger(GroupReaderWriterTest.class); + private static Logger log = Logger.getLogger(JsonGroupReaderWriterTest.class); + + @BeforeClass + public static void setUpClass() + { + Log4jInit.setLevel("ca.nrc.cadc.ac.json", Level.INFO); + } @Test public void testReaderExceptions() @@ -104,7 +115,8 @@ public class GroupReaderWriterTest try { String s = null; - Group g = GroupReader.read(s); + JsonGroupReader reader = new JsonGroupReader(); + Group g = reader.read(s); fail("null String should throw IllegalArgumentException"); } catch (IllegalArgumentException e) {} @@ -112,7 +124,8 @@ public class GroupReaderWriterTest try { InputStream in = null; - Group g = GroupReader.read(in); + JsonGroupReader reader = new JsonGroupReader(); + Group g = reader.read(in); fail("null InputStream should throw IOException"); } catch (IOException e) {} @@ -120,7 +133,8 @@ public class GroupReaderWriterTest try { Reader r = null; - Group g = GroupReader.read(r); + JsonGroupReader reader = new JsonGroupReader(); + Group g = reader.read(r); fail("null element should throw ReaderException"); } catch (IllegalArgumentException e) {} @@ -132,7 +146,8 @@ public class GroupReaderWriterTest { try { - GroupWriter.write(null, new StringBuilder()); + JsonGroupWriter writer = new JsonGroupWriter(); + writer.write(null, new StringBuilder()); fail("null Group should throw WriterException"); } catch (WriterException e) {} @@ -142,41 +157,63 @@ public class GroupReaderWriterTest public void testMinimalReadWrite() throws Exception { - Group expected = new Group("groupID", null); + Group expected = new Group("groupID"); StringBuilder json = new StringBuilder(); - GroupWriter.write(expected, json); + JsonGroupWriter writer = new JsonGroupWriter(); + writer.write(expected, json); assertFalse(json.toString().isEmpty()); - - Group actual = GroupReader.read(json.toString()); + + JsonGroupReader reader = new JsonGroupReader(); + Group actual = reader.read(json.toString()); assertNotNull(actual); assertEquals(expected, actual); } - + @Test public void testMaximalReadWrite() throws Exception { - Group expected = new Group("groupID", new User<Principal>(new HttpPrincipal("foo"))); + User<Principal> owner = new User<Principal>(new HttpPrincipal("foo")); + X500Principal x500Principal = new X500Principal("cn=foo,o=bar"); + owner.getIdentities().add(x500Principal); + PersonalDetails personalDetails = new PersonalDetails("foo", "bar"); + personalDetails.address = "address"; + personalDetails.email = "email"; + personalDetails.institute = "institute"; + personalDetails.city = "city"; + personalDetails.country = "country"; + owner.details.add(personalDetails); + PosixDetails posixDetails = new PosixDetails(123L, 456L, "/dev/null"); + owner.details.add(posixDetails); + + Group expected = new Group("groupID", owner); expected.description = "description"; expected.lastModified = new Date(); - expected.getProperties().add(new GroupProperty("key", "value", true)); - + expected.getProperties().add(new GroupProperty("key1", "value1", true)); + expected.getProperties().add(new GroupProperty("key2", "value2", true)); + expected.getProperties().add(new GroupProperty("key3", "value3", true)); + Group groupMember = new Group("member", new User<Principal>(new OpenIdPrincipal("bar"))); User<Principal> userMember = new User<Principal>(new HttpPrincipal("baz")); Group groupAdmin = new Group("admin", new User<Principal>(new X500Principal("cn=foo,o=ca"))); User<Principal> userAdmin = new User<Principal>(new HttpPrincipal("admin")); - + expected.getGroupMembers().add(groupMember); expected.getUserMembers().add(userMember); expected.getGroupAdmins().add(groupAdmin); expected.getUserAdmins().add(userAdmin); - - StringBuilder json = new StringBuilder(); - GroupWriter.write(expected, json); - assertFalse(json.toString().isEmpty()); - Group actual = GroupReader.read(json.toString()); + JsonGroupWriter writer = new JsonGroupWriter(); + StringBuilder sb = new StringBuilder(); + writer.write(expected, sb); + + String json = sb.toString(); + log.debug(json); + + JsonGroupReader reader = new JsonGroupReader(); + Group actual = reader.read(json); + assertNotNull(actual); assertEquals(expected, actual); assertEquals(expected.description, actual.description); diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/UserReaderWriterTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/JsonUserReaderWriterTest.java similarity index 87% rename from projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/UserReaderWriterTest.java rename to projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/JsonUserReaderWriterTest.java index 6e468da861196bcd48c20c419b02ffa21bb0c684..dccefe894c2a5b2a3addf25e226cee910061ea74 100644 --- a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/UserReaderWriterTest.java +++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/JsonUserReaderWriterTest.java @@ -91,9 +91,9 @@ import static org.junit.Assert.fail; * * @author jburke */ -public class UserReaderWriterTest +public class JsonUserReaderWriterTest { - private static Logger log = Logger.getLogger(UserReaderWriterTest.class); + private static Logger log = Logger.getLogger(JsonUserReaderWriterTest.class); @Test public void testReaderExceptions() @@ -102,7 +102,8 @@ public class UserReaderWriterTest try { String s = null; - User<? extends Principal> u = UserReader.read(s); + JsonUserReader reader = new JsonUserReader(); + User<? extends Principal> u = reader.read(s); fail("null String should throw IllegalArgumentException"); } catch (IllegalArgumentException e) {} @@ -110,7 +111,8 @@ public class UserReaderWriterTest try { InputStream in = null; - User<? extends Principal> u = UserReader.read(in); + JsonUserReader reader = new JsonUserReader(); + User<? extends Principal> u = reader.read(in); fail("null InputStream should throw IOException"); } catch (IOException e) {} @@ -118,7 +120,8 @@ public class UserReaderWriterTest try { Reader r = null; - User<? extends Principal> u = UserReader.read(r); + JsonUserReader reader = new JsonUserReader(); + User<? extends Principal> u = reader.read(r); fail("null Reader should throw IllegalArgumentException"); } catch (IllegalArgumentException e) {} @@ -130,7 +133,8 @@ public class UserReaderWriterTest { try { - UserWriter.write(null, new StringBuilder()); + JsonUserWriter writer = new JsonUserWriter(); + writer.write(null, new StringBuilder()); fail("null User should throw WriterException"); } catch (WriterException e) {} @@ -140,16 +144,18 @@ public class UserReaderWriterTest public void testReadWrite() throws Exception { - User<? extends Principal> expected = new User<Principal>(new HttpPrincipal("foo")); + User<Principal> expected = new User<Principal>(new HttpPrincipal("foo")); expected.getIdentities().add(new NumericPrincipal(123l)); expected.details.add(new PersonalDetails("firstname", "lastname")); expected.details.add(new PosixDetails(123l, 456l, "foo")); StringBuilder json = new StringBuilder(); - UserWriter.write(expected, json); + JsonUserWriter writer = new JsonUserWriter(); + writer.write(expected, json); assertFalse(json.toString().isEmpty()); - - User<? extends Principal> actual = UserReader.read(json.toString()); + + JsonUserReader reader = new JsonUserReader(); + User<Principal> actual = reader.read(json.toString()); assertNotNull(actual); assertEquals(expected, actual); } diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/JsonUserRequestReaderWriterTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/JsonUserRequestReaderWriterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..cd4f6e715dd2a66723ed7a7d612806813b2dea00 --- /dev/null +++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/json/JsonUserRequestReaderWriterTest.java @@ -0,0 +1,157 @@ +/* + ************************************************************************ + ******************* CANADIAN ASTRONOMY DATA CENTRE ******************* + ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** + * + * (c) 2015. (c) 2015. + * Government of Canada Gouvernement du Canada + * National Research Council Conseil national de recherches + * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 + * All rights reserved Tous droits réservés + * + * NRC disclaims any warranties, Le CNRC dénie toute garantie + * expressed, implied, or énoncée, implicite ou légale, + * statutory, of any kind with de quelque nature que ce + * respect to the software, soit, concernant le logiciel, + * including without limitation y compris sans restriction + * any warranty of merchantability toute garantie de valeur + * or fitness for a particular marchande ou de pertinence + * purpose. NRC shall not be pour un usage particulier. + * liable in any event for any Le CNRC ne pourra en aucun cas + * damages, whether direct or être tenu responsable de tout + * indirect, special or general, dommage, direct ou indirect, + * consequential or incidental, particulier ou général, + * arising from the use of the accessoire ou fortuit, résultant + * software. Neither the name de l'utilisation du logiciel. Ni + * of the National Research le nom du Conseil National de + * Council of Canada nor the Recherches du Canada ni les noms + * names of its contributors may de ses participants ne peuvent + * be used to endorse or promote être utilisés pour approuver ou + * products derived from this promouvoir les produits dérivés + * software without specific prior de ce logiciel sans autorisation + * written permission. préalable et particulière + * par écrit. + * + * This file is part of the Ce fichier fait partie du projet + * OpenCADC project. OpenCADC. + * + * OpenCADC is free software: OpenCADC est un logiciel libre ; + * you can redistribute it and/or vous pouvez le redistribuer ou le + * modify it under the terms of modifier suivant les termes de + * the GNU Affero General Public la “GNU Affero General Public + * License as published by the License” telle que publiée + * Free Software Foundation, par la Free Software Foundation + * either version 3 of the : soit la version 3 de cette + * License, or (at your option) licence, soit (à votre gré) + * any later version. toute version ultérieure. + * + * OpenCADC is distributed in the OpenCADC est distribué + * hope that it will be useful, dans l’espoir qu’il vous + * but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE + * without even the implied GARANTIE : sans même la garantie + * warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ + * or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF + * PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence + * General Public License for Générale Publique GNU Affero + * more details. pour plus de détails. + * + * You should have received Vous devriez avoir reçu une + * a copy of the GNU Affero copie de la Licence Générale + * General Public License along Publique GNU Affero avec + * with OpenCADC. If not, see OpenCADC ; si ce n’est + * <http://www.gnu.org/licenses/>. pas le cas, consultez : + * <http://www.gnu.org/licenses/>. + * + * + ************************************************************************ + */ +package ca.nrc.cadc.ac.json; + +import ca.nrc.cadc.ac.PersonalDetails; +import ca.nrc.cadc.ac.User; +import ca.nrc.cadc.ac.UserRequest; +import ca.nrc.cadc.ac.WriterException; +import ca.nrc.cadc.auth.HttpPrincipal; +import org.junit.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.security.Principal; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + + +public class JsonUserRequestReaderWriterTest +{ + @Test + public void testReaderExceptions() + throws Exception + { + try + { + String s = null; + JsonUserRequestReader reader = new JsonUserRequestReader(); + UserRequest u = reader.read(s); + fail("null String should throw IllegalArgumentException"); + } + catch (IllegalArgumentException e) {} + + try + { + InputStream in = null; + JsonUserRequestReader reader = new JsonUserRequestReader(); + UserRequest u = reader.read(in); + fail("null InputStream should throw IOException"); + } + catch (IOException e) {} + + try + { + Reader r = null; + JsonUserRequestReader reader = new JsonUserRequestReader(); + UserRequest u = reader.read(r); + fail("null Reader should throw IllegalArgumentException"); + } + catch (IllegalArgumentException e) {} + } + + @Test + public void testWriterExceptions() + throws Exception + { + try + { + JsonUserRequestWriter writer = new JsonUserRequestWriter(); + writer.write(null, new StringBuilder()); + fail("null User should throw WriterException"); + } + catch (WriterException e) {} + } + + @Test + public void testReadWrite() + throws Exception + { + User<Principal> expectedUser = + new User<Principal>(new HttpPrincipal("CADCtest")); + expectedUser.details.add(new PersonalDetails("CADCtest", "User")); + + UserRequest<Principal> expected = + new UserRequest<Principal>(expectedUser, "MYPASSWORD".toCharArray()); + + StringBuilder json = new StringBuilder(); + JsonUserRequestWriter writer = new JsonUserRequestWriter(); + writer.write(expected, json); + assertFalse(json.toString().isEmpty()); + + JsonUserRequestReader reader = new JsonUserRequestReader(); + UserRequest<Principal> actual = reader.read(json.toString()); + assertNotNull(actual); + assertEquals(expected, actual); + } + +} diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/xml/GroupReaderWriterTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/xml/GroupReaderWriterTest.java index 12f3f5093d5f35c4b98aa0d6bcdaea8b31125477..6aab545506a02e5be27e23a648289c284eef17a5 100644 --- a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/xml/GroupReaderWriterTest.java +++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/xml/GroupReaderWriterTest.java @@ -70,6 +70,8 @@ package ca.nrc.cadc.ac.xml; import ca.nrc.cadc.ac.Group; import ca.nrc.cadc.ac.GroupProperty; +import ca.nrc.cadc.ac.PersonalDetails; +import ca.nrc.cadc.ac.PosixDetails; import ca.nrc.cadc.ac.User; import ca.nrc.cadc.ac.WriterException; import ca.nrc.cadc.auth.HttpPrincipal; @@ -104,7 +106,8 @@ public class GroupReaderWriterTest try { String s = null; - Group g = GroupReader.read(s); + GroupReader groupReader = new GroupReader(); + Group g = groupReader.read(s); fail("null String should throw IllegalArgumentException"); } catch (IllegalArgumentException e) {} @@ -112,7 +115,8 @@ public class GroupReaderWriterTest try { InputStream in = null; - Group g = GroupReader.read(in); + GroupReader groupReader = new GroupReader(); + Group g = groupReader.read(in); fail("null InputStream should throw IOException"); } catch (IOException e) {} @@ -120,7 +124,8 @@ public class GroupReaderWriterTest try { Reader r = null; - Group g = GroupReader.read(r); + GroupReader groupReader = new GroupReader(); + Group g = groupReader.read(r); fail("null element should throw ReaderException"); } catch (IllegalArgumentException e) {} @@ -132,7 +137,8 @@ public class GroupReaderWriterTest { try { - GroupWriter.write(null, new StringBuilder()); + GroupWriter groupWriter = new GroupWriter(); + groupWriter.write(null, new StringBuilder()); fail("null Group should throw WriterException"); } catch (WriterException e) {} @@ -145,10 +151,12 @@ public class GroupReaderWriterTest Group expected = new Group("groupID", null); StringBuilder xml = new StringBuilder(); - GroupWriter.write(expected, xml); + GroupWriter groupWriter = new GroupWriter(); + groupWriter.write(expected, xml); assertFalse(xml.toString().isEmpty()); - - Group actual = GroupReader.read(xml.toString()); + + GroupReader groupReader = new GroupReader(); + Group actual = groupReader.read(xml.toString()); assertNotNull(actual); assertEquals(expected, actual); } @@ -157,10 +165,24 @@ public class GroupReaderWriterTest public void testMaximalReadWrite() throws Exception { - Group expected = new Group("groupID", new User<Principal>(new HttpPrincipal("foo"))); + User<Principal> owner = new User<Principal>(new HttpPrincipal("foo")); + X500Principal x500Principal = new X500Principal("cn=foo,o=bar"); + owner.getIdentities().add(x500Principal); + PersonalDetails personalDetails = new PersonalDetails("foo", "bar"); + personalDetails.address = "address"; + personalDetails.email = "email"; + personalDetails.institute = "institute"; + personalDetails.city = "city"; + personalDetails.country = "country"; + owner.details.add(personalDetails); + PosixDetails posixDetails = new PosixDetails(123L, 456L, "/dev/null"); + owner.details.add(posixDetails); + + Group expected = new Group("groupID", owner); expected.description = "description"; expected.lastModified = new Date(); - expected.getProperties().add(new GroupProperty("key", "value", true)); + expected.getProperties().add(new GroupProperty("key1", "value1", true)); + expected.getProperties().add(new GroupProperty("key2", "value2", false)); Group groupMember = new Group("member", new User<Principal>(new OpenIdPrincipal("bar"))); User<Principal> userMember = new User<Principal>(new HttpPrincipal("baz")); @@ -173,10 +195,12 @@ public class GroupReaderWriterTest expected.getUserAdmins().add(userAdmin); StringBuilder xml = new StringBuilder(); - GroupWriter.write(expected, xml); + GroupWriter groupWriter = new GroupWriter(); + groupWriter.write(expected, xml); assertFalse(xml.toString().isEmpty()); - - Group actual = GroupReader.read(xml.toString()); + + GroupReader groupReader = new GroupReader(); + Group actual = groupReader.read(xml.toString()); assertNotNull(actual); assertEquals(expected, actual); assertEquals(expected.description, actual.description); diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/xml/GroupsReaderWriterTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/xml/GroupsReaderWriterTest.java index 1d4d9f3052d68324ad7db6e332215c985108c9aa..0281eaf87cf1456c0d5781fc187012d3d5c7caa2 100644 --- a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/xml/GroupsReaderWriterTest.java +++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/xml/GroupsReaderWriterTest.java @@ -99,7 +99,8 @@ public class GroupsReaderWriterTest try { String s = null; - List<Group> g = GroupsReader.read(s); + GroupListReader groupListReader = new GroupListReader(); + List<Group> g = groupListReader.read(s); fail("null String should throw IllegalArgumentException"); } catch (IllegalArgumentException e) {} @@ -107,7 +108,8 @@ public class GroupsReaderWriterTest try { InputStream in = null; - List<Group> g = GroupsReader.read(in); + GroupListReader groupListReader = new GroupListReader(); + List<Group> g = groupListReader.read(in); fail("null InputStream should throw IOException"); } catch (IOException e) {} @@ -115,7 +117,8 @@ public class GroupsReaderWriterTest try { Reader r = null; - List<Group> g = GroupsReader.read(r); + GroupListReader groupListReader = new GroupListReader(); + List<Group> g = groupListReader.read(r); fail("null element should throw ReaderException"); } catch (IllegalArgumentException e) {} @@ -127,7 +130,8 @@ public class GroupsReaderWriterTest { try { - GroupsWriter.write(null, new StringBuilder()); + GroupListWriter groupListWriter = new GroupListWriter(); + groupListWriter.write(null, new StringBuilder()); fail("null Group should throw WriterException"); } catch (WriterException e) {} @@ -142,10 +146,12 @@ public class GroupsReaderWriterTest expected.add(new Group("group2", null)); StringBuilder xml = new StringBuilder(); - GroupsWriter.write(expected, xml); + GroupListWriter groupListWriter = new GroupListWriter(); + groupListWriter.write(expected, xml); assertFalse(xml.toString().isEmpty()); - - List<Group> actual = GroupsReader.read(xml.toString()); + + GroupListReader groupListReader = new GroupListReader(); + List<Group> actual = groupListReader.read(xml.toString()); assertNotNull(actual); assertEquals(expected.size(), actual.size()); assertEquals(expected.get(0), actual.get(0)); diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/xml/UserReaderWriterTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/xml/UserReaderWriterTest.java index a0e3d54881d83f310dbc616884dcf37277066cd6..4e8d9f2b066ef053fb815854ee2a3ce03c66e30c 100644 --- a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/xml/UserReaderWriterTest.java +++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/xml/UserReaderWriterTest.java @@ -101,7 +101,8 @@ public class UserReaderWriterTest try { String s = null; - User<? extends Principal> u = UserReader.read(s); + UserReader userReader = new UserReader(); + User<? extends Principal> u = userReader.read(s); fail("null String should throw IllegalArgumentException"); } catch (IllegalArgumentException e) {} @@ -109,7 +110,8 @@ public class UserReaderWriterTest try { InputStream in = null; - User<? extends Principal> u = UserReader.read(in); + UserReader userReader = new UserReader(); + User<? extends Principal> u = userReader.read(in); fail("null InputStream should throw IOException"); } catch (IOException e) {} @@ -117,7 +119,8 @@ public class UserReaderWriterTest try { Reader r = null; - User<? extends Principal> u = UserReader.read(r); + UserReader userReader = new UserReader(); + User<? extends Principal> u = userReader.read(r); fail("null Reader should throw IllegalArgumentException"); } catch (IllegalArgumentException e) {} @@ -129,7 +132,8 @@ public class UserReaderWriterTest { try { - ca.nrc.cadc.ac.xml.UserWriter.write(null, new StringBuilder()); + UserWriter userWriter = new UserWriter(); + userWriter.write(null, new StringBuilder()); fail("null User should throw WriterException"); } catch (WriterException e) {} @@ -144,10 +148,12 @@ public class UserReaderWriterTest expected.details.add(new PersonalDetails("firstname", "lastname")); StringBuilder xml = new StringBuilder(); - UserWriter.write(expected, xml); + UserWriter userWriter = new UserWriter(); + userWriter.write(expected, xml); assertFalse(xml.toString().isEmpty()); - - User<? extends Principal> actual = UserReader.read(xml.toString()); + + UserReader userReader = new UserReader(); + User<? extends Principal> actual = userReader.read(xml.toString()); assertNotNull(actual); assertEquals(expected, actual); } diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/xml/UserRequestReaderWriterTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/xml/UserRequestReaderWriterTest.java index 191fb9b603131b691659c843aa11b25303309d14..30dec9315f46556d62e8193380f68452e29b4a88 100644 --- a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/xml/UserRequestReaderWriterTest.java +++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/xml/UserRequestReaderWriterTest.java @@ -99,7 +99,8 @@ public class UserRequestReaderWriterTest try { String s = null; - UserRequest u = UserRequestReader.read(s); + UserRequestReader userRequestReader = new UserRequestReader(); + UserRequest u = userRequestReader.read(s); fail("null String should throw IllegalArgumentException"); } catch (IllegalArgumentException e) {} @@ -107,7 +108,8 @@ public class UserRequestReaderWriterTest try { InputStream in = null; - UserRequest u = UserRequestReader.read(in); + UserRequestReader userRequestReader = new UserRequestReader(); + UserRequest u = userRequestReader.read(in); fail("null InputStream should throw IOException"); } catch (IOException e) {} @@ -115,7 +117,8 @@ public class UserRequestReaderWriterTest try { Reader r = null; - UserRequest u = UserRequestReader.read(r); + UserRequestReader userRequestReader = new UserRequestReader(); + UserRequest u = userRequestReader.read(r); fail("null Reader should throw IllegalArgumentException"); } catch (IllegalArgumentException e) {} @@ -127,7 +130,8 @@ public class UserRequestReaderWriterTest { try { - UserRequestWriter.write(null, new StringBuilder()); + UserRequestWriter userRequestWriter = new UserRequestWriter(); + userRequestWriter.write(null, new StringBuilder()); fail("null UserRequest should throw WriterException"); } catch (WriterException e) {} @@ -137,22 +141,26 @@ public class UserRequestReaderWriterTest public void testReadWrite() throws Exception { - User<? extends Principal> expectedUser = new User<Principal>(new HttpPrincipal("foo")); + User<HttpPrincipal> expectedUser = new User<HttpPrincipal>(new HttpPrincipal("foo")); expectedUser.getIdentities().add(new NumericPrincipal(123l)); expectedUser.details.add(new PersonalDetails("firstname", "lastname")); - String expectedPassword = "123456"; + char[] expectedPassword = "123456".toCharArray(); - UserRequest expected = new UserRequest(expectedUser, expectedPassword); + UserRequest<HttpPrincipal> expected = + new UserRequest<HttpPrincipal>(expectedUser, expectedPassword); StringBuilder xml = new StringBuilder(); - UserRequestWriter.write(expected, xml); + UserRequestWriter userRequestWriter = new UserRequestWriter(); + userRequestWriter.write(expected, xml); assertFalse(xml.toString().isEmpty()); - - UserRequest actual = UserRequestReader.read(xml.toString()); + + UserRequestReader userRequestReader = new UserRequestReader(); + UserRequest actual = userRequestReader.read(xml.toString()); assertNotNull(actual); assertEquals(expected.getUser(), actual.getUser()); - assertEquals(expected.getPassword(), actual.getPassword()); + assertEquals(String.valueOf(expected.getPassword()), + String.valueOf(actual.getPassword())); } }