diff --git a/projects/cadcAccessControl-Server/Dependencies.txt b/projects/cadcAccessControl-Server/Dependencies.txt new file mode 100644 index 0000000000000000000000000000000000000000..7ef8710a2be2a815c1c2b2bfe670a2f8603a2e57 --- /dev/null +++ b/projects/cadcAccessControl-Server/Dependencies.txt @@ -0,0 +1,15 @@ +JAR files required for the OpenCADC cadcAccessControl-Server project +==================================================================== + +Name in build.xml Versioned Name Project URL +----------------- -------------- ----------- +jdom.jar jdom-1.1 http://www.jdom.org +log4j.jar log4j-1.2.15 http://logging.apache.org +xerces.jar xerces-2_9_1 http://xerces.apache.org +servlet-api.jar apache-tomcat-5.5.20 http://tomcat.apache.org +jdom2jar jdom-2.0.5 http://www.jdom.org +cadcRegistryClient.jar http://code.google.com/p/opencadc +cadcUtil.jar http://code.google.com/p/opencadc +cadcAccessControl.jar http://code.google.com/p/opencadc +cadcUWS.jar http://code.google.com/p/opencadc +cadcLog.jar http://code.google.com/p/opencadc \ No newline at end of file diff --git a/projects/cadcAccessControl-Server/PluginFactory.properties b/projects/cadcAccessControl-Server/PluginFactory.properties new file mode 100644 index 0000000000000000000000000000000000000000..3c47cbb416c913936ebe91192c0c91a34e535e44 --- /dev/null +++ b/projects/cadcAccessControl-Server/PluginFactory.properties @@ -0,0 +1,9 @@ +## commented out values are the defaults, shown as examples +## to customise behaviour, subclass the specified class and +## change the configuration here + +## UserPersistence implementation +ca.nrc.cadc.ac.server.UserPersistence = ca.nrc.cadc.ac.server.ldap.LdapUserPersistence + +## GroupPersistence implementation +ca.nrc.cadc.ac.server.GroupPersistence = ca.nrc.cadc.ac.server.ldap.LdapGroupPersistence \ No newline at end of file diff --git a/projects/cadcAccessControl-Server/build.xml b/projects/cadcAccessControl-Server/build.xml new file mode 100644 index 0000000000000000000000000000000000000000..f30a6185a9e20cee5cc39941fc1f563c830e3410 --- /dev/null +++ b/projects/cadcAccessControl-Server/build.xml @@ -0,0 +1,148 @@ +<!-- +************************************************************************ +******************* CANADIAN ASTRONOMY DATA CENTRE ******************* +************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +* +* (c) 2009. (c) 2009. +* 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 $ +* +************************************************************************ +--> + + +<!DOCTYPE project> +<project name="cadcAccessControl-Server" default="build" basedir="."> + <property environment="env"/> + <property file="local.build.properties" /> + + <!-- site-specific build properties or overrides of values in opencadc.properties --> + <property file="${env.CADC_PREFIX}/etc/local.properties" /> + + <!-- site-specific targets, e.g. install, cannot duplicate those in opencadc.targets.xml --> + <import file="${env.CADC_PREFIX}/etc/local.targets.xml" optional="true" /> + + <!-- default properties and targets --> + <property file="${env.CADC_PREFIX}/etc/opencadc.properties" /> + <import file="${env.CADC_PREFIX}/etc/opencadc.targets.xml"/> + + <!-- developer convenience: place for extra targets and properties --> + <import file="extras.xml" optional="true" /> + + <property name="project" value="cadcAccessControl-Server" /> + + <property name="cadcAccessControl" value="${lib}/cadcAccessControl.jar" /> + <property name="cadcLog" value="${lib}/cadcLog.jar" /> + <property name="cadcRegistry" value="${lib}/cadcRegistryClient.jar" /> + <property name="cadcUtil" value="${lib}/cadcUtil.jar" /> + <property name="cadcUWS" value="${lib}/cadcUWS.jar" /> + <property name="wsUtil" value="${lib}/wsUtil.jar" /> + + <property name="javacsv" value="${ext.lib}/javacsv.jar" /> + <property name="jdom2" value="${ext.lib}/jdom2.jar" /> + <property name="log4j" value="${ext.lib}/log4j.jar" /> + <property name="servlet" value="${ext.lib}/servlet-api.jar" /> + <property name="unboundid" value="${ext.lib}/unboundid-ldapsdk-se.jar" /> + <property name="xerces" value="${ext.lib}/xerces.jar" /> + + <property name="jars" value="${javacsv}:${jdom2}:${log4j}:${servlet}:${unboundid}:${xerces}:${cadcAccessControl}:${cadcLog}:${cadcRegistry}:${cadcUtil}:${cadcUWS}:${wsUtil}" /> + + <target name="build" depends="compile"> + <jar jarfile="${build}/lib/${project}.jar" + basedir="${build}/class" + update="no"> + <include name="ca/nrc/cadc/**" /> + </jar> + </target> + + <!-- JAR files needed to run the test suite --> + <property name="gson" value="${ext.lib}/gson.jar" /> + <property name="easyMock" value="${ext.dev}/easymock.jar" /> + <property name="junit" value="${ext.dev}/junit.jar" /> + <property name="xmlunit" value="${ext.dev}/xmlunit.jar" /> + <property name="xerces" value="${ext.lib}/xerces.jar" /> + <property name="cglib" value="${ext.dev}/cglib.jar" /> + <property name="objenesis" value="${ext.dev}/objenesis.jar" /> + <property name="asm" value="${ext.dev}/asm.jar" /> + + <property name="testingJars" value="${jars}:${gson}:${easyMock}:${junit}:${xmlunit}:${xerces}:${cglib}:${asm}:${objenesis}" /> + + <target name="resources"> + <copy todir="${build}/class"> + <fileset dir="config"> + <include name="**.properties" /> + </fileset> + </copy> + </target> + + <!--<target name="test" depends="compile,compile-test,resources">--> + <!--<echo message="Running test suite..." />--> + <!--<junit printsummary="yes" haltonfailure="yes" fork="yes">--> + <!--<classpath>--> + <!--<pathelement path="${build}/class"/>--> + <!--<pathelement path="${build}/test/class"/>--> + <!--<pathelement path="${testingJars}"/>--> + <!--</classpath>--> + <!--<test name="ca.nrc.cadc.ac.server.ldap.LdapGroupDAOTest" />--> + <!--<formatter type="plain" usefile="false" />--> + <!--</junit>--> + <!--</target>--> + +</project> diff --git a/projects/cadcAccessControl-Server/config/.dbrc_example b/projects/cadcAccessControl-Server/config/.dbrc_example new file mode 100644 index 0000000000000000000000000000000000000000..ced094848f172ce8628940a22568afa4efb3d6be --- /dev/null +++ b/projects/cadcAccessControl-Server/config/.dbrc_example @@ -0,0 +1,2 @@ +#server proxyuser proxyUserDN password driver serverURL +<server hostname> <proxyUser in LdapConfig.properties> <proxyUserLdapDN> <password> N/A N/A diff --git a/projects/cadcAccessControl-Server/config/LdapConfig.properties b/projects/cadcAccessControl-Server/config/LdapConfig.properties new file mode 100644 index 0000000000000000000000000000000000000000..5eb874d802b890852e308e6880946751513437dc --- /dev/null +++ b/projects/cadcAccessControl-Server/config/LdapConfig.properties @@ -0,0 +1,7 @@ +# This are the configuration fields required by the Ldap +server = <name of server> +port = <389 or 636> +proxyUser = <name of proxy user> +usersDn = <DN of users branch> +groupsDn = <DN of groups branch> +adminGroupsDn = <DN of admin groups> 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 new file mode 100755 index 0000000000000000000000000000000000000000..bdfa4e05c79516396085e5ffb90d031dc2d7c3e2 --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/GroupPersistence.java @@ -0,0 +1,178 @@ +/* + ************************************************************************ + ******************* 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; + +import java.security.AccessControlException; +import java.security.Principal; +import java.util.Collection; + +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.UserNotFoundException; +import ca.nrc.cadc.net.TransientException; + +public abstract interface GroupPersistence<T extends Principal> +{ + /** + * Get all group names. + * + * @return A collection of strings. + * @throws TransientException If an temporary, unexpected problem occurred. + * @throws AccessControlException If the operation is not permitted. + */ + public Collection<String> getGroupNames() + throws TransientException, AccessControlException; + + /** + * Get the group with the given Group ID. + * + * @param groupID The Group ID. + * + * @return A Group instance + * + * @throws GroupNotFoundException If the group was not found. + * @throws TransientException If an temporary, unexpected problem occurred. + * @throws AccessControlException If the operation is not permitted. + */ + public abstract Group getGroup(String groupID) + throws GroupNotFoundException, TransientException, + AccessControlException; + + /** + * Creates the group. + * + * @param group The group to create + * + * @return created group + * + * @throws GroupAlreadyExistsException If a group with the same ID already + * exists. + * @throws TransientException If an temporary, unexpected problem occurred. + * @throws AccessControlException If the operation is not permitted. + * @throws UserNotFoundException If owner or a member not valid user. + * @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) + throws GroupAlreadyExistsException, TransientException, + AccessControlException, UserNotFoundException, + GroupNotFoundException; + + /** + * Deletes the group. + * + * @param groupID The Group ID. + * + * @throws GroupNotFoundException If the group was not found. + * @throws TransientException If an temporary, unexpected problem occurred. + * @throws AccessControlException If the operation is not permitted. + */ + public abstract void deleteGroup(String groupID) + throws GroupNotFoundException, TransientException, + AccessControlException; + + /** + * Modify the given group. + * + * @param group The group to update. + * + * @return The newly updated group. + * + * @throws GroupNotFoundException If the group was not found. + * @throws TransientException If an temporary, unexpected problem occurred. + * @throws AccessControlException If the operation is not permitted. + * @throws UserNotFoundException If owner or group members not valid users. + */ + public abstract Group modifyGroup(Group group) + throws GroupNotFoundException, TransientException, + AccessControlException, UserNotFoundException; + + /** + * Obtain a Collection of Groups that fit the given query. + * + * @param userID The userID. + * @param role Role of the user, either owner, member, or read/write. + * @param groupID The Group ID. + * + * @return Collection of Groups matching the query, or empty Collection. + * Never null. + * + * @throws UserNotFoundException If owner or group members not valid users. + * @throws ca.nrc.cadc.ac.GroupNotFoundException + * @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) + throws UserNotFoundException, GroupNotFoundException, + TransientException, AccessControlException; + +} diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/PluginFactory.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/PluginFactory.java new file mode 100755 index 0000000000000000000000000000000000000000..caa18b20c505d98444c4b428ca8a8a9dad7b0aba --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/PluginFactory.java @@ -0,0 +1,165 @@ +/* + ************************************************************************ + ******************* 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; + +import ca.nrc.cadc.ac.server.ldap.LdapGroupPersistence; +import ca.nrc.cadc.ac.server.ldap.LdapUserPersistence; +import java.net.URL; +import java.security.Principal; +import java.util.Properties; +import java.util.Set; +import org.apache.log4j.Logger; + +public class PluginFactory +{ + private static final Logger log = Logger.getLogger(PluginFactory.class); + + private static final String CONFIG = PluginFactory.class.getSimpleName() + ".properties"; + private Properties config; + + public PluginFactory() + { + init(); + } + + @Override + public String toString() + { + return getClass().getName() + "[" + config.entrySet().size() + "]"; + } + + private void init() + { + config = new Properties(); + URL url = null; + try + { + url = PluginFactory.class.getClassLoader().getResource(CONFIG); + if (url != null) + { + config.load(url.openStream()); + } + } + catch (Exception ex) + { + throw new RuntimeException("failed to read " + CONFIG + " from " + url, ex); + } + } + + @SuppressWarnings("unchecked") + public <T extends Principal> GroupPersistence<T> getGroupPersistence() + { + GroupPersistence<T> ret = null; + String name = GroupPersistence.class.getName(); + String cname = config.getProperty(name); + if (cname == null) + { + ret = new LdapGroupPersistence<T>(); + } + else + { + try + { + Class<?> c = Class.forName(cname); + ret = (GroupPersistence<T>) c.newInstance(); + } + catch (Exception ex) + { + throw new RuntimeException("config error: failed to create GroupPersistence " + cname, ex); + } + } + return ret; + } + + @SuppressWarnings("unchecked") + public <T extends Principal> UserPersistence<T> getUserPersistence() + { + UserPersistence<T> ret = null; + String name = UserPersistence.class.getName(); + String cname = config.getProperty(name); + if (cname == null) + { + ret = new LdapUserPersistence<T>(); + } + else + { + try + { + Class<?> c = Class.forName(cname); + ret = (UserPersistence<T>) c.newInstance(); + } + catch (Exception ex) + { + throw new RuntimeException("config error: failed to create UserPersistence " + cname, ex); + } + } + return ret; + } + +} diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/RequestValidator.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/RequestValidator.java new file mode 100644 index 0000000000000000000000000000000000000000..f35fef417dbc5f90ca550c1013783e649c52f043 --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/RequestValidator.java @@ -0,0 +1,172 @@ +/* + ************************************************************************ + ******************* 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; + +import java.security.Principal; +import java.util.List; + +import org.apache.log4j.Logger; + +import ca.nrc.cadc.ac.Role; +import ca.nrc.cadc.auth.AuthenticationUtil; +import ca.nrc.cadc.uws.Parameter; +import ca.nrc.cadc.uws.ParameterUtil; + +/** + * Request Validator. This class extracts and validates the ID, TYPE, ROLE + * and GURI parameters. + * + */ +public class RequestValidator +{ + private static final Logger log = Logger.getLogger(RequestValidator.class); + + private Principal principal; + private Role role; + private String groupID; + + public RequestValidator() { } + + private void clear() + { + this.principal = null; + this.role = null; + this.groupID = null; + } + + public void validate(List<Parameter> paramList) + { + clear(); + if (paramList == null || paramList.isEmpty()) + { + throw new IllegalArgumentException( + "Missing required parameters: ID, IDTYPE, ROLE"); + } + + // ID + String param = ParameterUtil.findParameterValue("ID", paramList); + if (param == null || param.trim().isEmpty()) + { + throw new IllegalArgumentException( + "ID parameter required but not found"); + } + String userID = param.trim(); + log.debug("ID: " + userID); + + // TYPE + param = ParameterUtil.findParameterValue("IDTYPE", paramList); + if (param == null || param.trim().isEmpty()) + { + throw new IllegalArgumentException( + "IDTYPE parameter required but not found"); + } + + principal = + AuthenticationUtil.createPrincipal(userID, + param.trim()); + log.debug("TYPE: " + param.trim()); + + // ROLE + param = ParameterUtil.findParameterValue("ROLE", paramList); + if (param == null || param.trim().isEmpty()) + { + throw new IllegalArgumentException( + "ROLE parameter required but not found"); + } + this.role = Role.toValue(param); + log.debug("ROLE: " + role); + + // GROUPID + param = ParameterUtil.findParameterValue("GROUPID", paramList); + if (param != null) + { + if (param.isEmpty()) + throw new IllegalArgumentException( + "GROUPID parameter specified without a value"); + this.groupID = param.trim(); + } + log.debug("GROUPID: " + groupID); + } + + public Principal getPrincipal() + { + return principal; + } + + public Role getRole() + { + return role; + } + + public String getGroupID() + { + return groupID; + } + +} 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 new file mode 100755 index 0000000000000000000000000000000000000000..703a3d62a170221b4a4ef875e4596c4ffc8880f9 --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/UserPersistence.java @@ -0,0 +1,128 @@ +/* + ************************************************************************ + ******************* 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; + +import ca.nrc.cadc.ac.User; +import ca.nrc.cadc.ac.UserNotFoundException; +import ca.nrc.cadc.net.TransientException; +import com.unboundid.ldap.sdk.DN; +import java.security.AccessControlException; +import java.security.Principal; +import java.util.Collection; + +public abstract interface UserPersistence<T extends Principal> +{ + /** + * Get the user specified by userID. + * + * @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. + */ + public abstract User<T> getUser(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. + */ + public abstract 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. + */ + public abstract boolean isMember(T userID, String groupID) + throws UserNotFoundException, TransientException, + AccessControlException; +} diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapConfig.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapConfig.java new file mode 100755 index 0000000000000000000000000000000000000000..42995612395ededc619d730d5a1441c31aea0900 --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapConfig.java @@ -0,0 +1,307 @@ +/* + ************************************************************************ + ******************* 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.ldap; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.List; + +import org.apache.log4j.Logger; + +import ca.nrc.cadc.db.ConnectionConfig; +import ca.nrc.cadc.db.DBConfig; +import ca.nrc.cadc.util.MultiValuedProperties; +import ca.nrc.cadc.util.PropertiesReader; +import ca.nrc.cadc.util.StringUtil; + +/** + * Reads and stores the LDAP configuration information. The information + * + * @author adriand + * + */ +public class LdapConfig +{ + private static final Logger logger = Logger.getLogger(LdapConfig.class); + + public static final String CONFIG = LdapConfig.class.getSimpleName() + + ".properties"; + public static final String LDAP_SERVER = "server"; + public static final String LDAP_PORT = "port"; + public static final String LDAP_SERVER_PROXY_USER = "proxyUser"; + public static final String LDAP_USERS_DN = "usersDn"; + public static final String LDAP_GROUPS_DN = "groupsDn"; + public static final String LDAP_ADMIN_GROUPS_DN = "adminGroupsDn"; + + private final static int SECURE_PORT = 636; + + private String usersDN; + private String groupsDN; + private String adminGroupsDN; + private String server; + private int port; + private String proxyUserDN; + private String proxyPasswd; + + public String getProxyUserDN() + { + return proxyUserDN; + } + + public String getProxyPasswd() + { + return proxyPasswd; + } + + public static LdapConfig getLdapConfig() + { + return getLdapConfig(CONFIG); + } + + public static LdapConfig getLdapConfig(final String ldapProperties) + { + PropertiesReader pr = new PropertiesReader(ldapProperties); + + MultiValuedProperties config = pr.getAllProperties(); + + if (config.keySet() == null) + { + throw new RuntimeException("failed to read any LDAP property "); + } + + List<String> prop = config.getProperty(LDAP_SERVER); + if ((prop == null) || (prop.size() != 1)) + { + throw new RuntimeException("failed to read property " + + LDAP_SERVER); + } + String server = prop.get(0); + + prop = config.getProperty(LDAP_PORT); + if ((prop == null) || (prop.size() != 1)) + { + throw new RuntimeException("failed to read property " + LDAP_PORT); + } + int port = Integer.valueOf(prop.get(0)); + + prop = config.getProperty(LDAP_SERVER_PROXY_USER); + if ((prop == null) || (prop.size() != 1)) + { + throw new RuntimeException("failed to read property " + + LDAP_SERVER_PROXY_USER); + } + String ldapProxy = prop.get(0); + + prop = config.getProperty(LDAP_USERS_DN); + if ((prop == null) || (prop.size() != 1)) + { + throw new RuntimeException("failed to read property " + + LDAP_USERS_DN); + } + String ldapUsersDn = prop.get(0); + + prop = config.getProperty(LDAP_GROUPS_DN); + if ((prop == null) || (prop.size() != 1)) + { + throw new RuntimeException("failed to read property " + + LDAP_GROUPS_DN); + } + String ldapGroupsDn = prop.get(0); + + prop = config.getProperty(LDAP_ADMIN_GROUPS_DN); + if ((prop == null) || (prop.size() != 1)) + { + throw new RuntimeException("failed to read property " + + LDAP_ADMIN_GROUPS_DN); + } + String ldapAdminGroupsDn = prop.get(0); + + DBConfig dbConfig; + try + { + dbConfig = new DBConfig(); + } + catch (FileNotFoundException e) + { + throw new RuntimeException("failed to find .dbrc file "); + } + catch (IOException e) + { + throw new RuntimeException("failed to read .dbrc file "); + } + ConnectionConfig cc = dbConfig.getConnectionConfig(server, ldapProxy); + if ( (cc == null) || (cc.getUsername() == null) || (cc.getPassword() == null)) + { + throw new RuntimeException("failed to find connection info in ~/.dbrc"); + } + + return new LdapConfig(server, Integer.valueOf(port), cc.getUsername(), + cc.getPassword(), ldapUsersDn, ldapGroupsDn, + ldapAdminGroupsDn); + } + + + public LdapConfig(String server, int port, String proxyUserDN, + String proxyPasswd, String usersDN, String groupsDN, + String adminGroupsDN) + { + if (!StringUtil.hasText(server)) + { + throw new IllegalArgumentException("Illegal LDAP server name"); + } + if (port < 0) + { + throw new IllegalArgumentException("Illegal LDAP server port: " + + port); + } + if (!StringUtil.hasText(proxyUserDN)) + { + throw new IllegalArgumentException("Illegal Admin DN"); + } + if (!StringUtil.hasText(proxyPasswd)) + { + throw new IllegalArgumentException("Illegal Admin password"); + } + if (!StringUtil.hasText(usersDN)) + { + throw new IllegalArgumentException("Illegal users LDAP DN"); + } + if (!StringUtil.hasText(groupsDN)) + { + throw new IllegalArgumentException("Illegal groups LDAP DN"); + } + if (!StringUtil.hasText(adminGroupsDN)) + { + throw new IllegalArgumentException("Illegal admin groups LDAP DN"); + } + + this.server = server; + this.port = port; + this.proxyUserDN = proxyUserDN; + this.proxyPasswd = proxyPasswd; + this.usersDN = usersDN; + this.groupsDN = groupsDN; + this.adminGroupsDN = adminGroupsDN; + logger.debug(toString()); + } + + public String getUsersDN() + { + return this.usersDN; + } + + public String getGroupsDN() + { + return this.groupsDN; + } + + public String getAdminGroupsDN() + { + return this.adminGroupsDN; + } + + public String getServer() + { + return this.server; + } + + public int getPort() + { + return this.port; + } + + public boolean isSecure() + { + return getPort() == SECURE_PORT; + } + + public String getAdminUserDN() + { + return this.proxyUserDN; + } + + public String getAdminPasswd() + { + return this.proxyPasswd; + } + + public String toString() + { + StringBuilder sb = new StringBuilder(); + sb.append("server = "); + sb.append(server); + sb.append(" port = "); + sb.append(port); + sb.append(" proxyUserDN = "); + sb.append(proxyUserDN); + sb.append(" proxyPasswd = "); + sb.append(proxyPasswd); + return sb.toString(); + } +} diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapDAO.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapDAO.java new file mode 100755 index 0000000000000000000000000000000000000000..abd19b24bde0eda15142be362587d4b22241b26a --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapDAO.java @@ -0,0 +1,257 @@ +/* + ************************************************************************ + ******************* 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.ldap; + +import javax.net.SocketFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.security.auth.Subject; +import javax.security.auth.x500.X500Principal; +import java.io.File; +import java.net.MalformedURLException; +import java.security.*; +import java.security.cert.CertificateException; +import java.util.Set; + +import com.unboundid.ldap.sdk.*; +import com.unboundid.util.ssl.*; + +import ca.nrc.cadc.auth.*; +import ca.nrc.cadc.net.TransientException; + + +public abstract class LdapDAO +{ + private LDAPConnection conn; + + LdapConfig config; + DN subjDN = null; + + public LdapDAO(LdapConfig config) + { + if (config == null) + { + throw new IllegalArgumentException("LDAP config required"); + } + this.config = config; + } + + public void close() + { + if (conn != null) + { + conn.close(); + } + } + + protected LDAPConnection getConnection() + throws LDAPException, AccessControlException + { + if (conn == null) + { + conn = new LDAPConnection(getSocketFactory(), config.getServer(), + config.getPort()); + conn.bind(config.getAdminUserDN(), config.getAdminPasswd()); + } + + return conn; + } + + private SocketFactory getSocketFactory() + { + final SocketFactory socketFactory; + + if (config.isSecure()) + { + socketFactory = createSSLSocketFactory(); + } + else + { + socketFactory = SocketFactory.getDefault(); + } + + return socketFactory; + } + + private SSLSocketFactory createSSLSocketFactory() + { + try + { + return new com.unboundid.util.ssl.SSLUtil(). + createSSLSocketFactory(); + } + catch (GeneralSecurityException e) + { + throw new RuntimeException("Unexpected error.", e); + } + } + + protected DN getSubjectDN() throws LDAPException + { + if (subjDN == null) + { + Subject callerSubject = + Subject.getSubject(AccessController.getContext()); + if (callerSubject == null) + { + throw new AccessControlException("Caller not authenticated."); + } + + Set<Principal> principals = callerSubject.getPrincipals(); + if (principals.isEmpty()) + { + throw new AccessControlException("Caller not authenticated."); + } + + String ldapField = null; + for (Principal p : principals) + { + if (p instanceof HttpPrincipal) + { + ldapField = "(uid=" + p.getName() + ")"; + break; + } + if (p instanceof NumericPrincipal) + { + ldapField = "(entryid=" + p.getName() + ")"; + break; + } + if (p instanceof X500Principal) + { + ldapField = "(distinguishedname=" + p.getName() + ")"; + break; + } + if (p instanceof OpenIdPrincipal) + { + ldapField = "(openid=" + p.getName() + ")"; + break; + } + } + + if (ldapField == null) + { + throw new AccessControlException("Identity of caller unknown."); + } + + SearchResult searchResult = + getConnection().search(config.getUsersDN(), SearchScope.ONE, + ldapField, "entrydn"); + + if (searchResult.getEntryCount() < 1) + { + throw new AccessControlException( + "No LDAP account when search with rule " + ldapField); + } + + subjDN = (searchResult.getSearchEntries().get(0)) + .getAttributeValueAsDN("entrydn"); + } + return subjDN; + } + + /** + * Checks the Ldap result code, and if the result is not SUCCESS, + * throws an appropriate exception. This is the place to decide on + * mapping between ldap errors and exception types + * + * @param code The code returned from an LDAP request. + * @throws TransientException + */ + protected static void checkLdapResult(ResultCode code) + throws TransientException + { + if (code == ResultCode.INSUFFICIENT_ACCESS_RIGHTS) + { + throw new AccessControlException("Not authorized "); + } + else if (code == ResultCode.INVALID_CREDENTIALS) + { + throw new AccessControlException("Invalid credentials "); + } + else if ((code == ResultCode.SUCCESS) || (code + == ResultCode.NO_SUCH_OBJECT)) + { + // all good. nothing to do + } + else if (code == ResultCode.PARAM_ERROR) + { + throw new IllegalArgumentException("Error in Ldap parameters "); + } + else if (code == ResultCode.BUSY || + code == ResultCode.CONNECT_ERROR) + { + throw new TransientException("Connection problems "); + } + else + { + throw new RuntimeException("Ldap error (" + code.getName() + ")"); + } + } + +} 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 new file mode 100755 index 0000000000000000000000000000000000000000..70ee0595f868c4805fda36310ff6cbd9b9278a5b --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAO.java @@ -0,0 +1,1033 @@ +/* + ************************************************************************ + ******************* 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.ldap; + +import java.security.AccessControlException; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.security.auth.x500.X500Principal; + +import org.apache.log4j.Logger; + +import ca.nrc.cadc.ac.ActivatedGroup; +import ca.nrc.cadc.ac.Group; +import ca.nrc.cadc.ac.GroupAlreadyExistsException; +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.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.controls.ProxiedAuthorizationV2RequestControl; + +public class LdapGroupDAO<T extends Principal> extends LdapDAO +{ + private static final Logger logger = Logger.getLogger(LdapGroupDAO.class); + + private LdapUserDAO<T> userPersist; + + public LdapGroupDAO(LdapConfig config, LdapUserDAO<T> userPersist) + { + super(config); + if (userPersist == null) + { + throw new IllegalArgumentException( + "User persistence instance required"); + } + this.userPersist = userPersist; + } + + /** + * Persists a group. + * + * @param group The group to create + * + * @return created group + * + * @throws GroupAlreadyExistsException If a group with the same ID already + * exists. + * @throws TransientException If an temporary, unexpected problem occurred. + * @throws UserNotFoundException If owner or a member not valid user. + * @throws GroupNotFoundException + */ + public Group addGroup(final Group group) + throws GroupAlreadyExistsException, TransientException, + UserNotFoundException, AccessControlException, + GroupNotFoundException + { + if (group.getOwner() == null) + { + throw new IllegalArgumentException("Group owner must be specified"); + } + + if (!group.getProperties().isEmpty()) + { + throw new UnsupportedOperationException( + "Support for groups properties not available"); + } + + if (!isCreatorOwner(group.getOwner())) + { + throw new AccessControlException("Group owner must be creator"); + } + + try + { + Group newGroup = reactivateGroup(group); + if ( newGroup != null) + { + return newGroup; + } + else + { + + DN ownerDN = userPersist.getUserDN(group.getOwner()); + + // add group to groups tree + LDAPResult result = addGroup(getGroupDN(group.getID()), + group.getID(), ownerDN, + group.description, + group.getUserMembers(), + group.getGroupMembers()); + LdapDAO.checkLdapResult(result.getResultCode()); + + // add group to admin groups tree + result = addGroup(getAdminGroupDN(group.getID()), + group.getID(), ownerDN, + group.description, + group.getUserAdmins(), + group.getGroupAdmins()); + LdapDAO.checkLdapResult(result.getResultCode()); + + try + { + return getGroup(group.getID()); + } + catch (GroupNotFoundException e) + { + throw new RuntimeException("BUG: new group not found"); + } + } + } + catch (LDAPException e) + { + LdapDAO.checkLdapResult(e.getResultCode()); + throw new RuntimeException("Unexpected LDAP exception", e); + } + } + + private LDAPResult addGroup(final DN groupDN, final String groupID, + final DN ownerDN, final String description, + final Set<User<? extends Principal>> users, + final Set<Group> groups) + throws UserNotFoundException, LDAPException, TransientException, + AccessControlException, GroupNotFoundException + { + // add new group + List<Attribute> attributes = new ArrayList<Attribute>(); + Attribute ownerAttribute = + new Attribute("owner", ownerDN.toNormalizedString()); + attributes.add(ownerAttribute); + attributes.add(new Attribute("objectClass", "groupofuniquenames")); + attributes.add(new Attribute("cn", groupID)); + + if (StringUtil.hasText(description)) + { + attributes.add(new Attribute("description", description)); + } + + List<String> members = new ArrayList<String>(); + for (User<? extends Principal> userMember : users) + { + DN memberDN = this.userPersist.getUserDN(userMember); + members.add(memberDN.toNormalizedString()); + } + for (Group groupMember : groups) + { + final String groupMemberID = groupMember.getID(); + if (!checkGroupExists(groupMemberID)) + { + throw new GroupNotFoundException(groupMemberID); + } + DN memberDN = getGroupDN(groupMemberID); + members.add(memberDN.toNormalizedString()); + } + if (!members.isEmpty()) + { + attributes.add(new Attribute("uniquemember", + (String[]) members.toArray(new String[members.size()]))); + } + + AddRequest addRequest = new AddRequest(groupDN, attributes); + addRequest.addControl( + new ProxiedAuthorizationV2RequestControl( + "dn:" + getSubjectDN().toNormalizedString())); + + return getConnection().add(addRequest); + } + + + /** + * Checks whether group name available for the user or already in use. + * @param group + * @return activated group or null if group does not exists + * @throws AccessControlException + * @throws UserNotFoundException + * @throws GroupNotFoundException + * @throws TransientException + * @throws GroupAlreadyExistsException + */ + private Group reactivateGroup(final Group group) + throws AccessControlException, UserNotFoundException, + TransientException, GroupAlreadyExistsException + { + try + { + // check group name exists + Filter filter = Filter.createEqualityFilter("cn", group.getID()); + + SearchRequest searchRequest = + new SearchRequest( + getGroupDN(group.getID()) + .toNormalizedString(), SearchScope.SUB, filter, + new String[] {"nsaccountlock"}); + + searchRequest.addControl( + new ProxiedAuthorizationV2RequestControl("dn:" + + getSubjectDN().toNormalizedString())); + + SearchResultEntry searchResult = + getConnection().searchForEntry(searchRequest); + + if (searchResult == null) + { + return null; + } + + if (searchResult.getAttributeValue("nsaccountlock") == null) + { + throw new + GroupAlreadyExistsException("Group already exists " + group.getID()); + } + + // activate group + try + { + return modifyGroup(group, true); + } + catch (GroupNotFoundException e) + { + throw new RuntimeException( + "BUG: group to modify does not exist" + group.getID()); + } + } + catch (LDAPException e) + { + LdapDAO.checkLdapResult(e.getResultCode()); + throw new RuntimeException("Unexpected LDAP exception", e); + } + } + + + /** + * Get all group names. + * + * @return A collection of strings + * + * @throws TransientException If an temporary, unexpected problem occurred. + */ + 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) + { + if (e.getResultCode() == ResultCode.NO_SUCH_OBJECT) + { + logger.debug("Could not find groups root", e); + throw new IllegalStateException("Could not find groups root"); + } + } + + LdapDAO.checkLdapResult(searchResult.getResultCode()); + List<String> groupNames = new ArrayList<String>(); + for (SearchResultEntry next : searchResult.getSearchEntries()) + { + if (!next.hasAttribute("nsaccountlock")) + { + groupNames.add(next.getAttributeValue("cn")); + } + } + + return groupNames; + } + catch (LDAPException e1) + { + LdapDAO.checkLdapResult(e1.getResultCode()); + throw new IllegalStateException("Unexpected exception: " + e1.getMatchedDN(), e1); + } + + } + + /** + * Get the group with the given Group ID. + * + * @param groupID The Group unique ID. + * + * @return A Group instance + * + * @throws GroupNotFoundException If the group was not found. + * @throws TransientException If an temporary, unexpected problem occurred. + */ + public Group getGroup(final String groupID) + throws GroupNotFoundException, TransientException, + AccessControlException + { + return getGroup(groupID, true); + } + + public Group getGroup(final String groupID, final boolean withMembers) + throws GroupNotFoundException, TransientException, + AccessControlException + { + Group group = getGroup(getGroupDN(groupID), groupID, true); + + Group adminGroup = getAdminGroup(getAdminGroupDN(groupID), groupID, + true); + + group.getGroupAdmins().addAll(adminGroup.getGroupMembers()); + group.getUserAdmins().addAll(adminGroup.getUserMembers()); + return group; + } + + private Group getGroup(final DN groupDN, final String groupID, + final boolean withMembers) + throws GroupNotFoundException, TransientException, + AccessControlException + { + String [] attributes = new String[] {"entrydn", "cn", "description", + "owner", "uniquemember", + "modifytimestamp", "nsaccountlock"}; + return getGroup(groupDN, groupID, withMembers, attributes); + } + + private Group getAdminGroup(final DN groupDN, final String groupID, + final boolean withMembers) + throws GroupNotFoundException, TransientException, + AccessControlException + { + String [] attributes = new String[] {"entrydn", "cn", "owner", + "uniquemember"}; + return getGroup(groupDN, groupID, withMembers, attributes); + } + + private Group getGroup(final DN groupDN, final String groupID, + final boolean withMembers, final String[] attributes) + throws GroupNotFoundException, TransientException, + AccessControlException + { + try + { + Filter filter = Filter.createEqualityFilter("cn", groupID); + + SearchRequest searchRequest = + new SearchRequest(groupDN.toNormalizedString(), + SearchScope.SUB, filter, attributes); + + searchRequest.addControl( + new ProxiedAuthorizationV2RequestControl("dn:" + + getSubjectDN().toNormalizedString())); + + SearchResult searchResult = null; + try + { + searchResult = getConnection().search(searchRequest); + } + catch (LDAPSearchException e) + { + if (e.getResultCode() == ResultCode.NO_SUCH_OBJECT) + { + String msg = "Group not found " + groupID; + logger.debug(msg); + throw new GroupNotFoundException(groupID); + } + else + { + LdapDAO.checkLdapResult(e.getResultCode()); + } + } + + if (searchResult.getEntryCount() == 0) + { + LdapDAO.checkLdapResult(searchResult.getResultCode()); + //access denied + String msg = "Not authorized to access " + groupID; + logger.debug(msg); + throw new AccessControlException(groupID); + } + + if (searchResult.getEntryCount() >1) + { + throw new RuntimeException("BUG: multiple results when retrieving group " + groupID); + } + + SearchResultEntry searchEntry = searchResult.getSearchEntries().get(0); + + if (searchEntry.getAttribute("nsaccountlock") != null) + { + // deleted group + String msg = "Group not found " + groupID; + logger.debug(msg); + throw new GroupNotFoundException(groupID); + } + + DN groupOwner = searchEntry.getAttributeValueAsDN("owner"); + if (groupOwner == null) + { + //TODO assume user not allowed to read group + throw new AccessControlException(groupID); + } + + User<X500Principal> owner; + try + { + owner = userPersist.getMember(groupOwner); + } + catch (UserNotFoundException e) + { + throw new RuntimeException("BUG: group owner not found"); + } + + Group ldapGroup = new Group(groupID, owner); + if (searchEntry.hasAttribute("description")) + { + ldapGroup.description = + searchEntry.getAttributeValue("description"); + } + if (searchEntry.hasAttribute("modifytimestamp")) + { + ldapGroup.lastModified = + searchEntry.getAttributeValueAsDate("modifytimestamp"); + } + + if (withMembers) + { + if (searchEntry.getAttributeValues("uniquemember") != null) + { + for (String member : searchEntry + .getAttributeValues("uniquemember")) + { + DN memberDN = new DN(member); + if (memberDN.isDescendantOf(config.getUsersDN(), false)) + { + User<X500Principal> user; + try + { + user = userPersist.getMember(memberDN); + } + catch (UserNotFoundException e) + { + throw new RuntimeException( + "BUG: group member not found"); + } + ldapGroup.getUserMembers().add(user); + } + else if (memberDN.isDescendantOf(config.getGroupsDN(), + false)) + { + ldapGroup.getGroupMembers().add(new Group( + memberDN.getRDNString().replace("cn=", ""))); + } + else + { + throw new RuntimeException( + "BUG: unknown member DN type: " + memberDN); + } + } + } + } + + return ldapGroup; + } + catch (LDAPException e1) + { + LdapDAO.checkLdapResult(e1.getResultCode()); + throw new GroupNotFoundException("Not found " + groupID); + } + } + + /** + * Modify the given group. + * + * @param group The group to update. It must be an existing group + * + * @return The newly updated group. + * + * @throws GroupNotFoundException If the group was not found. + * @throws TransientException If an temporary, unexpected problem occurred. + * @throws AccessControlException If the operation is not permitted. + * @throws UserNotFoundException If owner or group members not valid users. + */ + public Group modifyGroup(final Group group) + throws GroupNotFoundException, TransientException, + AccessControlException, UserNotFoundException + { + getGroup(group.getID()); //group must exists first + return modifyGroup(group, false); + } + + private Group modifyGroup(final Group group, boolean withActivate) + throws UserNotFoundException, TransientException, + AccessControlException, GroupNotFoundException + { + if (!group.getProperties().isEmpty()) + { + throw new UnsupportedOperationException( + "Support for groups properties not available"); + } + + List<Modification> mods = new ArrayList<Modification>(); + List<Modification> adminMods = new ArrayList<Modification>(); + if (withActivate) + { + mods.add(new Modification(ModificationType.DELETE, "nsaccountlock")); + adminMods.add(new Modification(ModificationType.DELETE, "nsaccountlock")); + } + + if (group.description == null) + { + mods.add(new Modification(ModificationType.REPLACE, "description")); + } + else + { + mods.add(new Modification(ModificationType.REPLACE, "description", group.description)); + } + + List<String> newMembers = new ArrayList<String>(); + for (User<?> member : group.getUserMembers()) + { + DN memberDN = userPersist.getUserDN(member); + newMembers.add(memberDN.toNormalizedString()); + } + for (Group gr : group.getGroupMembers()) + { + if (!checkGroupExists(gr.getID())) + { + throw new GroupNotFoundException(gr.getID()); + } + DN grDN = getGroupDN(gr.getID()); + newMembers.add(grDN.toNormalizedString()); + } + List<String> newAdmins = new ArrayList<String>(); + for (User<?> member : group.getUserAdmins()) + { + DN memberDN = userPersist.getUserDN(member); + newAdmins.add(memberDN.toNormalizedString()); + } + for (Group gr : group.getGroupAdmins()) + { + if (!checkGroupExists(gr.getID())) + { + throw new GroupNotFoundException(gr.getID()); + } + DN grDN = getGroupDN(gr.getID()); + newAdmins.add(grDN.toNormalizedString()); + } + + mods.add(new Modification(ModificationType.REPLACE, "uniquemember", + (String[]) newMembers.toArray(new String[newMembers.size()]))); + adminMods.add(new Modification(ModificationType.REPLACE, "uniquemember", + (String[]) newAdmins.toArray(new String[newAdmins.size()]))); + + // modify admin group first + ModifyRequest modifyRequest = new ModifyRequest(getAdminGroupDN(group.getID()), adminMods); + try + { + modifyRequest.addControl( + new ProxiedAuthorizationV2RequestControl( + "dn:" + getSubjectDN().toNormalizedString())); + LdapDAO.checkLdapResult(getConnection(). + modify(modifyRequest).getResultCode()); + + // modify the group itself now + modifyRequest = new ModifyRequest(getGroupDN(group.getID()), mods); + + modifyRequest.addControl( + new ProxiedAuthorizationV2RequestControl( + "dn:" + getSubjectDN().toNormalizedString())); + LdapDAO.checkLdapResult(getConnection(). + modify(modifyRequest).getResultCode()); + } + catch (LDAPException e1) + { + LdapDAO.checkLdapResult(e1.getResultCode()); + } + try + { + if (withActivate) + { + return new ActivatedGroup(getGroup(group.getID())); + } + else + { + return getGroup(group.getID()); + } + } + catch (GroupNotFoundException e) + { + throw new RuntimeException( + "BUG: modified group not found (" + group.getID() + ")"); + } + } + + /** + * Deletes the group. + * + * @param groupID The group to delete + * + * @throws GroupNotFoundException If the group was not found. + * @throws TransientException If an temporary, unexpected problem occurred. + */ + public void deleteGroup(final String groupID) + throws GroupNotFoundException, TransientException, + AccessControlException + { + deleteGroup(getGroupDN(groupID), groupID, false); + deleteGroup(getAdminGroupDN(groupID), groupID, true); + } + + private void deleteGroup(final DN groupDN, final String groupID, + final boolean isAdmin) + throws GroupNotFoundException, TransientException, + AccessControlException + { + Group group = getGroup(groupDN, groupID, true); + List<Modification> modifs = new ArrayList<Modification>(); + modifs.add(new Modification(ModificationType.ADD, "nsaccountlock", "true")); + + if (isAdmin) + { + if (!group.getGroupAdmins().isEmpty() || + !group.getUserAdmins().isEmpty()) + { + modifs.add(new Modification(ModificationType.DELETE, "uniquemember")); + } + } + else + { + if (!group.getGroupMembers().isEmpty() || + !group.getUserMembers().isEmpty()) + { + modifs.add(new Modification(ModificationType.DELETE, "uniquemember")); + } + } + + ModifyRequest modifyRequest = new ModifyRequest(groupDN, modifs); + try + { + modifyRequest.addControl( + new ProxiedAuthorizationV2RequestControl( + "dn:" + getSubjectDN().toNormalizedString())); + LDAPResult result = getConnection().modify(modifyRequest); + LdapDAO.checkLdapResult(result.getResultCode()); + } + catch (LDAPException e1) + { + LdapDAO.checkLdapResult(e1.getResultCode()); + } + + try + { + getGroup(group.getID()); + throw new RuntimeException("BUG: group not deleted " + + group.getID()); + } + catch (GroupNotFoundException ignore) {} + } + + /** + * Obtain a Collection of Groups that fit the given query. + * + * @param userID The userID. + * @param role Role of the user, either owner, member, or read/write. + * @param groupID The Group ID. + * + * @return Collection of Groups + * matching GROUP_READ_ACI.replace(ACTUAL_GROUP_TOKEN, + * readGrDN.toNormalizedString()) the query, or empty + * Collection. Never null. + * @throws TransientException If an temporary, unexpected problem occurred. + * @throws UserNotFoundException + * @throws GroupNotFoundException + */ + public Collection<Group> getGroups(final T userID, final Role role, + final String groupID) + throws TransientException, AccessControlException, + GroupNotFoundException, UserNotFoundException + { + User<T> user = new User<T>(userID); + DN userDN = null; + try + { + userDN = userPersist.getUserDN(user); + } + catch (UserNotFoundException e) + { + // no anonymous searches + throw new AccessControlException("Not authorized to search"); + } + + Collection<DN> groupDNs = new HashSet<DN>(); + if (role == Role.OWNER) + { + groupDNs.addAll(getOwnerGroups(user, userDN, groupID)); + } + else if (role == Role.MEMBER) + { + groupDNs.addAll(getMemberGroups(user, userDN, groupID, false)); + } + else if (role == Role.ADMIN) + { + groupDNs.addAll(getMemberGroups(user, userDN, groupID, true)); + } + + if (logger.isDebugEnabled()) + { + for (DN dn : groupDNs) + { + logger.debug("Search adding DN: " + dn); + } + } + + Collection<Group> groups = new HashSet<Group>(); + try + { + for (DN groupDN : groupDNs) + { + if (role == Role.ADMIN) + { + groupDN = new DN(groupDN.getRDNString() + "," + config.getGroupsDN()); + } + try + { + groups.add(getGroup(groupDN)); + logger.debug("Search adding group: " + groupDN); + } + catch (GroupNotFoundException e) + { + final String message = "BUG: group " + groupDN + " not found but " + + "membership exists (" + userID + ")"; + logger.error(message); + //throw new IllegalStateException(message); + } + } + } + catch (LDAPException e) + { + throw new TransientException("Error getting group", e); + } + return groups; + } + + protected Collection<DN> getOwnerGroups(final User<T> user, + final DN userDN, + final String groupID) + throws TransientException, AccessControlException, + GroupNotFoundException, UserNotFoundException + { + Collection<DN> groupDNs = new HashSet<DN>(); + try + { + Filter filter = Filter.createEqualityFilter("owner", + userDN.toString()); + if (groupID != null) + { + getGroup(groupID); + filter = Filter.createANDFilter(filter, + Filter.createEqualityFilter("cn", groupID)); + } + + SearchRequest searchRequest = new SearchRequest( + config.getGroupsDN(), SearchScope.SUB, filter, "entrydn", "nsaccountlock"); + + searchRequest.addControl( + new ProxiedAuthorizationV2RequestControl("dn:" + + getSubjectDN().toNormalizedString())); + + SearchResult results = getConnection().search(searchRequest); + for (SearchResultEntry result : results.getSearchEntries()) + { + String entryDN = result.getAttributeValue("entrydn"); + // make sure the group isn't deleted + if (result.getAttribute("nsaccountlock") == null) + { + groupDNs.add(new DN(entryDN)); + } + + } + } + catch (LDAPException e1) + { + LdapDAO.checkLdapResult(e1.getResultCode()); + } + return groupDNs; + } + + protected Collection<DN> getMemberGroups(final User<T> user, + final DN userDN, + final String groupID, + final boolean isAdmin) + throws TransientException, AccessControlException, + GroupNotFoundException, UserNotFoundException + { + Collection<DN> groupDNs = new HashSet<DN>(); + if (groupID != null) + { + DN groupDN; + if (isAdmin) + { + groupDN = getAdminGroupDN(groupID); + } + else + { + groupDN = getGroupDN(groupID); + } + if (userPersist.isMember(user.getUserID(), + groupDN.toNormalizedString())) + { + groupDNs.add(groupDN); + } + } + else + { + Collection<DN> memberGroupDNs = + userPersist.getUserGroups(user.getUserID(), isAdmin); + groupDNs.addAll(memberGroupDNs); + } + return groupDNs; + } + + /** + * Returns a group based on its LDAP DN. The returned group is bare + * (contains only group ID, description, modifytimestamp). + * + * @param groupDN + * @return + * @throws com.unboundid.ldap.sdk.LDAPException + * @throws ca.nrc.cadc.ac.GroupNotFoundException + */ + protected Group getGroup(final DN groupDN) + throws LDAPException, GroupNotFoundException, UserNotFoundException + { + Filter filter = Filter.createEqualityFilter("entrydn", + groupDN.toNormalizedString()); + + SearchRequest searchRequest = new SearchRequest( + config.getGroupsDN(), SearchScope.SUB, filter, + "cn", "description", "owner", "nsaccountlock"); + + searchRequest.addControl( + new ProxiedAuthorizationV2RequestControl("dn:" + + getSubjectDN().toNormalizedString())); + + SearchResultEntry searchResult = + getConnection().searchForEntry(searchRequest); + + if (searchResult == null) + { + String msg = "Group not found " + groupDN; + logger.debug(msg); + throw new GroupNotFoundException(groupDN.toNormalizedString()); + } + + if (searchResult.getAttribute("nsaccountlock") != null) + { + // deleted group + String msg = "Group not found " + groupDN; + logger.debug(msg); + throw new GroupNotFoundException(groupDN.toNormalizedString()); + } + + Group group = new Group(searchResult.getAttributeValue("cn"), + userPersist.getMember( + new DN(searchResult.getAttributeValue( + "owner")))); + group.description = searchResult.getAttributeValue("description"); + return group; + } + + /** + * + * @param groupID + * @return + */ + protected DN getGroupDN(final String groupID) throws TransientException + { + try + { + return new DN("cn=" + groupID + "," + config.getGroupsDN()); + } + catch (LDAPException e) + { + LdapDAO.checkLdapResult(e.getResultCode()); + } + throw new IllegalArgumentException(groupID + " not a valid group ID"); + } + + /** + * + * @param groupID + * @return + */ + protected DN getAdminGroupDN(final String groupID) throws TransientException + { + try + { + return new DN("cn=" + groupID + "," + config.getAdminGroupsDN()); + } + catch (LDAPException e) + { + LdapDAO.checkLdapResult(e.getResultCode()); + } + throw new IllegalArgumentException(groupID + " not a valid group ID"); + } + + /** + * + * @param owner + * @return + * @throws UserNotFoundException + */ + protected boolean isCreatorOwner(final User<? extends Principal> owner) + throws UserNotFoundException + { + try + { + User<X500Principal> subjectUser = + userPersist.getMember(getSubjectDN()); + if (subjectUser.equals(owner)) + { + return true; + } + return false; + } + catch (LDAPException e) + { + throw new RuntimeException(e); + } + } + + private boolean checkGroupExists(String groupID) + throws TransientException + { + for (String groupName : getGroupNames()) + { + if (groupName.equalsIgnoreCase(groupID)) + { + return true; + } + } + return false; + } + +} 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 new file mode 100755 index 0000000000000000000000000000000000000000..f59bc1518d82c3522bf0cd104bc3ca8fecfc7ebf --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapGroupPersistence.java @@ -0,0 +1,252 @@ +/* + ************************************************************************ + ******************* 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.ldap; + +import java.security.AccessControlException; +import java.security.Principal; +import java.util.Collection; + +import org.apache.log4j.Logger; + +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.UserNotFoundException; +import ca.nrc.cadc.ac.server.GroupPersistence; +import ca.nrc.cadc.net.TransientException; + +public class LdapGroupPersistence<T extends Principal> + implements GroupPersistence<T> +{ + private static final Logger log = + Logger.getLogger(LdapGroupPersistence.class); + private final LdapConfig config; + + public LdapGroupPersistence() + { + config = LdapConfig.getLdapConfig(); + } + + public Collection<String> getGroupNames() + throws TransientException, AccessControlException + { + LdapGroupDAO<T> groupDAO = null; + LdapUserDAO<T> userDAO = null; + try + { + userDAO = new LdapUserDAO<T>(config); + groupDAO = new LdapGroupDAO<T>(config, userDAO); + Collection<String> ret = groupDAO.getGroupNames(); + return ret; + } + finally + { + if (groupDAO != null) + { + groupDAO.close(); + } + if (userDAO != null) + { + userDAO.close(); + } + } + } + + public Group getGroup(String groupName) + throws GroupNotFoundException, TransientException, + AccessControlException + { + LdapGroupDAO<T> groupDAO = null; + LdapUserDAO<T> userDAO = null; + try + { + userDAO = new LdapUserDAO<T>(config); + groupDAO = new LdapGroupDAO<T>(config, userDAO); + Group ret = groupDAO.getGroup(groupName); + return ret; + } + finally + { + if (groupDAO != null) + { + groupDAO.close(); + } + if (userDAO != null) + { + userDAO.close(); + } + } + } + + public Group addGroup(Group group) + throws GroupAlreadyExistsException, TransientException, + AccessControlException, UserNotFoundException, + GroupNotFoundException + { + LdapGroupDAO<T> groupDAO = null; + LdapUserDAO<T> userDAO = null; + try + { + userDAO = new LdapUserDAO<T>(config); + groupDAO = new LdapGroupDAO<T>(config, userDAO); + Group ret = groupDAO.addGroup(group); + return ret; + } + finally + { + if (groupDAO != null) + { + groupDAO.close(); + } + if (userDAO != null) + { + userDAO.close(); + } + } + } + + public void deleteGroup(String groupName) + throws GroupNotFoundException, TransientException, + AccessControlException + { + LdapGroupDAO<T> groupDAO = null; + LdapUserDAO<T> userDAO = null; + try + { + userDAO = new LdapUserDAO<T>(config); + groupDAO = new LdapGroupDAO<T>(config, userDAO); + groupDAO.deleteGroup(groupName); + } + finally + { + if (groupDAO != null) + { + groupDAO.close(); + } + if (userDAO != null) + { + userDAO.close(); + } + } + } + + public Group modifyGroup(Group group) + throws GroupNotFoundException, TransientException, + AccessControlException, UserNotFoundException + { + LdapGroupDAO<T> groupDAO = null; + LdapUserDAO<T> userDAO = null; + try + { + userDAO = new LdapUserDAO<T>(config); + groupDAO = new LdapGroupDAO<T>(config, userDAO); + Group ret = groupDAO.modifyGroup(group); + return ret; + } + finally + { + if (groupDAO != null) + { + groupDAO.close(); + } + if (userDAO != null) + { + userDAO.close(); + } + } + } + + public Collection<Group> getGroups(T userID, Role role, String groupID) + throws UserNotFoundException, GroupNotFoundException, + TransientException, AccessControlException + { + LdapGroupDAO<T> groupDAO = null; + LdapUserDAO<T> userDAO = null; + try + { + userDAO = new LdapUserDAO<T>(config); + groupDAO = new LdapGroupDAO<T>(config, userDAO); + Collection<Group> ret = groupDAO.getGroups(userID, role, groupID); + return ret; + } + finally + { + if (groupDAO != null) + { + groupDAO.close(); + } + if (userDAO != null) + { + userDAO.close(); + } + } + } + +} 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 new file mode 100755 index 0000000000000000000000000000000000000000..f929385511697284380d6e5f6f4abef2d6457ce9 --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java @@ -0,0 +1,438 @@ +/* + ************************************************************************ + ******************* 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.ldap; + +import javax.security.auth.x500.X500Principal; +import java.security.AccessControlException; +import java.security.Principal; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import com.unboundid.ldap.sdk.*; +import com.unboundid.ldap.sdk.controls.ProxiedAuthorizationV2RequestControl; +import org.apache.log4j.Logger; + +import ca.nrc.cadc.ac.PersonalDetails; +import ca.nrc.cadc.ac.User; +import ca.nrc.cadc.ac.UserNotFoundException; +import ca.nrc.cadc.auth.HttpPrincipal; +import ca.nrc.cadc.net.TransientException; + + +public class LdapUserDAO<T extends Principal> extends LdapDAO +{ + private static final Logger logger = Logger.getLogger(LdapUserDAO.class); + + // Map of identity type to LDAP attribute + private Map<Class<?>, String> userLdapAttrib = + new HashMap<Class<?>, String>(); + + // User attributes returned to the GMS + private static final String LDAP_FNAME = "givenname"; + private static final String LDAP_LNAME = "sn"; + //TODO to add the rest + private String[] userAttribs = new String[]{LDAP_FNAME, LDAP_LNAME}; + private String[] memberAttribs = new String[]{LDAP_FNAME, LDAP_LNAME}; + + public LdapUserDAO(LdapConfig config) + { + super(config); + this.userLdapAttrib.put(HttpPrincipal.class, "uid"); + this.userLdapAttrib.put(X500Principal.class, "distinguishedname"); + + // add the id attributes to user and member attributes + String[] princs = userLdapAttrib.values() + .toArray(new String[userLdapAttrib.values().size()]); + String[] tmp = new String[userAttribs.length + princs.length]; + System.arraycopy(princs, 0, tmp, 0, princs.length); + System.arraycopy(userAttribs, 0, tmp, princs.length, + userAttribs.length); + userAttribs = tmp; + + tmp = new String[memberAttribs.length + princs.length]; + System.arraycopy(princs, 0, tmp, 0, princs.length); + System.arraycopy(memberAttribs, 0, tmp, princs.length, + memberAttribs.length); + memberAttribs = tmp; + } + + + /** + * Get the user specified by userID. + * + * @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. + */ + public User<T> getUser(T userID) + throws UserNotFoundException, TransientException, + AccessControlException + { + String searchField = userLdapAttrib.get(userID.getClass()); + if (searchField == null) + { + throw new IllegalArgumentException( + "Unsupported principal type " + userID.getClass()); + } + + searchField = + "(&(objectclass=cadcaccount)(" + searchField + "=" + userID + .getName() + "))"; + + SearchResultEntry searchResult = null; + try + { + SearchRequest searchRequest = new SearchRequest(config.getUsersDN(), + SearchScope.SUB, + searchField, + userAttribs); + + searchRequest.addControl( + new ProxiedAuthorizationV2RequestControl("dn:" + + getSubjectDN() + .toNormalizedString())); + + searchResult = getConnection().searchForEntry(searchRequest); + } + catch (LDAPException e) + { + LdapDAO.checkLdapResult(e.getResultCode()); + } + + if (searchResult == null) + { + String msg = "User not found " + userID.toString(); + logger.debug(msg); + throw new UserNotFoundException(msg); + } + User<T> user = new User<T>(userID); + user.getIdentities().add( + new HttpPrincipal(searchResult.getAttributeValue(userLdapAttrib + .get(HttpPrincipal.class)))); + + String fname = searchResult.getAttributeValue(LDAP_FNAME); + String lname = searchResult.getAttributeValue(LDAP_LNAME); + user.details.add(new PersonalDetails(fname, lname)); + //TODO populate user with the other returned personal or posix attributes + return user; + } + + /** + * Get all groups the user specified by userID belongs to. + * + * @param userID The userID. + * @param isAdmin + * @return Collection of Group instances. + * @throws UserNotFoundException when the user is not found. + * @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) + throws UserNotFoundException, TransientException, + AccessControlException + { + Collection<DN> groupDNs = new HashSet<DN>(); + try + { + String searchField = userLdapAttrib.get(userID.getClass()); + if (searchField == null) + { + throw new IllegalArgumentException( + "Unsupported principal type " + userID.getClass()); + } + + User<T> user = getUser(userID); + Filter filter = Filter.createANDFilter( + Filter.createEqualityFilter(searchField, + user.getUserID().getName()), + Filter.createPresenceFilter("memberOf")); + + SearchRequest searchRequest = + new SearchRequest(config.getUsersDN(), SearchScope.SUB, + filter, "memberOf"); + + searchRequest.addControl( + new ProxiedAuthorizationV2RequestControl("dn:" + + getSubjectDN() + .toNormalizedString())); + + SearchResultEntry searchResult = + getConnection().searchForEntry(searchRequest); + + DN parentDN; + if (isAdmin) + { + parentDN = new DN(config.getAdminGroupsDN()); + } + else + { + parentDN = new DN(config.getGroupsDN()); + } + + if (searchResult != null) + { + String[] members = searchResult.getAttributeValues("memberOf"); + if (members != null) + { + for (String member : members) + { + DN groupDN = new DN(member); + if (groupDN.isDescendantOf(parentDN, false)) + { + groupDNs.add(groupDN); + } + } + } + } + } + catch (LDAPException e) + { + LdapDAO.checkLdapResult(e.getResultCode()); + } + return groupDNs; + } + + /** + * 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. + */ + public boolean isMember(T userID, String groupID) + throws UserNotFoundException, TransientException, + AccessControlException + { + try + { + String searchField = userLdapAttrib.get(userID.getClass()); + if (searchField == null) + { + throw new IllegalArgumentException( + "Unsupported principal type " + userID.getClass()); + } + + User<T> user = getUser(userID); + Filter filter = Filter.createANDFilter( + Filter.createEqualityFilter(searchField, + user.getUserID().getName()), + Filter.createEqualityFilter("memberOf", groupID)); + + SearchRequest searchRequest = + new SearchRequest(config.getUsersDN(), SearchScope.SUB, + filter, "cn"); + + searchRequest.addControl( + new ProxiedAuthorizationV2RequestControl("dn:" + + getSubjectDN() + .toNormalizedString())); + + SearchResultEntry searchResults = + getConnection().searchForEntry(searchRequest); + + return (searchResults != null); + } + catch (LDAPException e) + { + LdapDAO.checkLdapResult(e.getResultCode()); + } + return false; + } + +// public boolean isMember(T userID, String groupID) +// throws UserNotFoundException, TransientException, +// AccessControlException +// { +// try +// { +// String searchField = (String) userLdapAttrib.get(userID.getClass()); +// if (searchField == null) +// { +// throw new IllegalArgumentException( +// "Unsupported principal type " + userID.getClass()); +// } +// +// User<T> user = getUser(userID); +// DN userDN = getUserDN(user); +// +// CompareRequest compareRequest = +// new CompareRequest(userDN.toNormalizedString(), +// "memberOf", groupID); +// +// compareRequest.addControl( +// new ProxiedAuthorizationV2RequestControl("dn:" + +// getSubjectDN().toNormalizedString())); +// +// CompareResult compareResult = +// getConnection().compare(compareRequest); +// return compareResult.compareMatched(); +// } +// catch (LDAPException e) +// { +// LdapDAO.checkLdapResult(e.getResultCode()); +// throw new RuntimeException("Unexpected LDAP exception", e); +// } +// } + + /** + * Returns a member user identified by the X500Principal only. The + * returned object has the fields required by the GMS. + * Note that this method binds as a proxy user and not as the + * subject. + * + * @param userDN + * @return + * @throws UserNotFoundException + * @throws LDAPException + */ + User<X500Principal> getMember(DN userDN) + throws UserNotFoundException, LDAPException + { + Filter filter = + Filter.createEqualityFilter("entrydn", + userDN.toNormalizedString()); + + SearchRequest searchRequest = + new SearchRequest(this.config.getUsersDN(), SearchScope.SUB, + filter, memberAttribs); + + SearchResultEntry searchResult = + getConnection().searchForEntry(searchRequest); + + if (searchResult == null) + { + String msg = "Member not found " + userDN; + logger.debug(msg); + throw new UserNotFoundException(msg); + } + User<X500Principal> user = new User<X500Principal>( + new X500Principal(searchResult.getAttributeValue( + userLdapAttrib.get(X500Principal.class)))); + String princ = searchResult.getAttributeValue( + userLdapAttrib.get(HttpPrincipal.class)); + if (princ != null) + { + user.getIdentities().add(new HttpPrincipal(princ)); + } + String fname = searchResult.getAttributeValue(LDAP_FNAME); + String lname = searchResult.getAttributeValue(LDAP_LNAME); + user.details.add(new PersonalDetails(fname, lname)); + return user; + } + + + DN getUserDN(User<? extends Principal> user) + throws UserNotFoundException, TransientException + { + String searchField = + userLdapAttrib.get(user.getUserID().getClass()); + if (searchField == null) + { + throw new IllegalArgumentException( + "Unsupported principal type " + user.getUserID() + .getClass()); + } + + searchField = "(" + searchField + "=" + + user.getUserID().getName() + ")"; + + SearchResultEntry searchResult = null; + try + { + SearchRequest searchRequest = + new SearchRequest(this.config.getUsersDN(), SearchScope.SUB, + searchField, "entrydn"); + + + searchResult = + getConnection().searchForEntry(searchRequest); + + } + catch (LDAPException e) + { + LdapDAO.checkLdapResult(e.getResultCode()); + } + + if (searchResult == null) + { + String msg = "User not found " + user.getUserID().getName(); + logger.debug(msg); + throw new UserNotFoundException(msg); + } + return searchResult.getAttributeValueAsDN("entrydn"); + } + +} 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 new file mode 100755 index 0000000000000000000000000000000000000000..8511d254f2ab164ad4428e9ab929f9e782bf852b --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserPersistence.java @@ -0,0 +1,193 @@ +/* + ************************************************************************ + ******************* 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.ldap; + +import ca.nrc.cadc.ac.User; +import ca.nrc.cadc.ac.UserNotFoundException; +import ca.nrc.cadc.ac.server.UserPersistence; +import ca.nrc.cadc.net.TransientException; +import com.unboundid.ldap.sdk.DN; +import java.security.AccessControlException; +import java.security.Principal; +import java.util.Collection; +import org.apache.log4j.Logger; + +public class LdapUserPersistence<T extends Principal> + implements UserPersistence<T> +{ + private static final Logger logger = Logger.getLogger(LdapUserPersistence.class); + private LdapConfig config; + + public LdapUserPersistence() + { + try + { + this.config = LdapConfig.getLdapConfig(); + } + catch (RuntimeException e) + { + logger.error("test/config/LdapConfig.properties file required.", e); + } + } + + /** + * Get the user specified by userID. + * + * @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. + */ + public User<T> getUser(T userID) + throws UserNotFoundException, TransientException, AccessControlException + { + LdapUserDAO<T> userDAO = null; + try + { + userDAO = new LdapUserDAO<T>(this.config); + User<T> ret = userDAO.getUser(userID); + return ret; + } + finally + { + if (userDAO != null) + { + userDAO.close(); + } + } + } + + /** + * 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. + */ + public 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; + } + finally + { + if (userDAO != null) + { + userDAO.close(); + } + } + } + + /** + * 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. + */ + public boolean isMember(T userID, String groupID) + throws UserNotFoundException, TransientException, + AccessControlException + { + LdapUserDAO<T> userDAO = null; + try + { + userDAO = new LdapUserDAO<T>(this.config); + boolean ret = userDAO.isMember(userID, groupID); + return ret; + } + finally + { + if (userDAO != null) + { + userDAO.close(); + } + } + } + +} diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/ACSearchRunner.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/ACSearchRunner.java new file mode 100755 index 0000000000000000000000000000000000000000..d608fb82b1c65fbd214996b05eef78fc878b1fbd --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/ACSearchRunner.java @@ -0,0 +1,389 @@ +/* + ************************************************************************ + ******************* 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 java.io.IOException; +import java.security.AccessControlContext; +import java.security.AccessControlException; +import java.security.AccessController; +import java.security.Principal; +import java.util.Collection; +import java.util.Date; +import java.util.Iterator; +import java.util.Set; + +import javax.security.auth.Subject; +import javax.security.auth.x500.X500Principal; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; + +import ca.nrc.cadc.ac.Group; +import ca.nrc.cadc.ac.GroupNotFoundException; +import ca.nrc.cadc.ac.GroupsWriter; +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.auth.AuthenticationUtil; +import ca.nrc.cadc.auth.HttpPrincipal; +import ca.nrc.cadc.net.TransientException; +import ca.nrc.cadc.uws.ExecutionPhase; +import ca.nrc.cadc.uws.Job; +import ca.nrc.cadc.uws.server.JobRunner; +import ca.nrc.cadc.uws.server.JobUpdater; +import ca.nrc.cadc.uws.server.SyncOutput; +import ca.nrc.cadc.uws.util.JobLogInfo; + +public class ACSearchRunner implements JobRunner +{ + private static Logger log = Logger.getLogger(ACSearchRunner.class); + + private JobUpdater jobUpdater; + private SyncOutput syncOut; + private Job job; + private JobLogInfo logInfo; + + @Override + public void setJobUpdater(JobUpdater jobUpdater) + { + this.jobUpdater = jobUpdater; + } + + @Override + public void setJob(Job job) + { + this.job = job; + } + + @Override + public void setSyncOutput(SyncOutput syncOut) + { + this.syncOut = syncOut; + } + + @Override + public void run() + { + AccessControlContext acContext = AccessController.getContext(); + Subject subject = Subject.getSubject(acContext); + + log.debug("RUN ACSearchRunner: " + subject); + if (log.isDebugEnabled()) + { + Set<Principal> principals = subject.getPrincipals(); + Iterator<Principal> i = principals.iterator(); + while (i.hasNext()) + { + Principal next = i.next(); + log.debug("Principal " + + next.getClass().getSimpleName() + + ": " + next.getName()); + } + } + + logInfo = new JobLogInfo(job); + logInfo.setSubject(subject); + + String startMessage = logInfo.start(); + log.info(startMessage); + + long t1 = System.currentTimeMillis(); + search(subject); + long t2 = System.currentTimeMillis(); + + logInfo.setElapsedTime(t2 - t1); + + String endMessage = logInfo.end(); + log.info(endMessage); + } + + @SuppressWarnings("unchecked") + private void search(Subject subject) + { + + // Note: This search runner is customized to run with + // InMemoryJobPersistence, and synchronous POST requests are + // dealt with immediately, rather than returning results via + // a redirect. + // Jobs in this runner are never updated after execution begins + // in case the in-memory job has gone away. Error reporting + // is done directly through the response on both POST and GET + + try + { + ExecutionPhase ep = + jobUpdater.setPhase(job.getID(), ExecutionPhase.QUEUED, + ExecutionPhase.EXECUTING, new Date()); + if ( !ExecutionPhase.EXECUTING.equals(ep) ) + { + throw new IllegalStateException("QUEUED -> EXECUTING [FAILED]"); + } + log.debug(job.getID() + ": QUEUED -> EXECUTING [OK]"); + + RequestValidator rv = new RequestValidator(); + rv.validate(job.getParameterList()); + + // only allow users to search themselves... + Principal userBeingSearched = rv.getPrincipal(); + + boolean idMatch = false; + if (userBeingSearched instanceof X500Principal) + { + Set<X500Principal> x500Principals = subject.getPrincipals(X500Principal.class); + Iterator<X500Principal> i = x500Principals.iterator(); + while (i.hasNext()) + { + X500Principal next = i.next(); + log.debug(String.format("Comparing x500: [%s][%s]", + next.getName(), userBeingSearched.getName())); + if (AuthenticationUtil.equals(next, userBeingSearched)) + idMatch = true; + } + } + else if (userBeingSearched instanceof HttpPrincipal) + { + Set<HttpPrincipal> httpPrincipals = subject.getPrincipals(HttpPrincipal.class); + Iterator<HttpPrincipal> i = httpPrincipals.iterator(); + while (i.hasNext()) + { + HttpPrincipal next = i.next(); + log.debug(String.format("Comparing http: [%s][%s]", + next.getName(), userBeingSearched.getName())); + if (next.equals(userBeingSearched)) + idMatch = true; + } + } + if (!idMatch) + throw new AccessControlException("Can only search oneself."); + + PluginFactory factory = new PluginFactory(); + GroupPersistence dao = factory.getGroupPersistence(); + Collection<Group> groups = + dao.getGroups(rv.getPrincipal(), rv.getRole(), rv.getGroupID()); + syncOut.setResponseCode(HttpServletResponse.SC_OK); + GroupsWriter.write(groups, syncOut.getOutputStream()); + + // Mark the Job as completed. +// jobUpdater.setPhase(job.getID(), ExecutionPhase.EXECUTING, +// ExecutionPhase.COMPLETED, new Date()); + } + catch (TransientException t) + { + logInfo.setSuccess(false); + logInfo.setMessage(t.getMessage()); + log.error("FAIL", t); + + syncOut.setResponseCode(503); + syncOut.setHeader("Content-Type", "text/plan"); + try + { + syncOut.getOutputStream().write(t.getMessage().getBytes()); + } + catch (IOException e) + { + log.warn("Could not write response to output stream", e); + } + +// ErrorSummary errorSummary = +// new ErrorSummary(t.getMessage(), ErrorType.FATAL); +// try +// { +// jobUpdater.setPhase(job.getID(), ExecutionPhase.EXECUTING, +// ExecutionPhase.ERROR, errorSummary, +// new Date()); +// } +// catch(Throwable oops) +// { +// log.debug("failed to set final error status after " + t, oops); +// } + } + catch (UserNotFoundException t) + { + logInfo.setSuccess(false); + logInfo.setMessage(t.getMessage()); + log.debug("FAIL", t); + + syncOut.setResponseCode(404); + syncOut.setHeader("Content-Type", "text/plan"); + try + { + syncOut.getOutputStream().write(t.getMessage().getBytes()); + } + catch (IOException e) + { + log.warn("Could not write response to output stream", e); + } + +// ErrorSummary errorSummary = +// new ErrorSummary(t.getMessage(), ErrorType.FATAL); +// try +// { +// jobUpdater.setPhase(job.getID(), ExecutionPhase.EXECUTING, +// ExecutionPhase.ERROR, errorSummary, +// new Date()); +// } +// catch(Throwable oops) +// { +// log.debug("failed to set final error status after " + t, oops); +// } + } + catch (GroupNotFoundException t) + { + logInfo.setSuccess(false); + logInfo.setMessage(t.getMessage()); + log.debug("FAIL", t); + + syncOut.setResponseCode(404); + syncOut.setHeader("Content-Type", "text/plan"); + try + { + syncOut.getOutputStream().write(t.getMessage().getBytes()); + } + catch (IOException e) + { + log.warn("Could not write response to output stream", e); + } + +// ErrorSummary errorSummary = +// new ErrorSummary(t.getMessage(), ErrorType.FATAL); +// try +// { +// jobUpdater.setPhase(job.getID(), ExecutionPhase.EXECUTING, +// ExecutionPhase.ERROR, errorSummary, +// new Date()); +// } +// catch(Throwable oops) +// { +// log.debug("failed to set final error status after " + t, oops); +// } + } + catch (AccessControlException t) + { + logInfo.setSuccess(false); + logInfo.setMessage(t.getMessage()); + log.debug("FAIL", t); + + syncOut.setResponseCode(403); + syncOut.setHeader("Content-Type", "text/plan"); + try + { + syncOut.getOutputStream().write(t.getMessage().getBytes()); + } + catch (IOException e) + { + log.warn("Could not write response to output stream", e); + } + +// ErrorSummary errorSummary = +// new ErrorSummary(t.getMessage(), ErrorType.FATAL); +// try +// { +// jobUpdater.setPhase(job.getID(), ExecutionPhase.EXECUTING, +// ExecutionPhase.ERROR, errorSummary, +// new Date()); +// } +// catch(Throwable oops) +// { +// log.debug("failed to set final error status after " + t, oops); +// } + } + catch (Throwable t) + { + logInfo.setSuccess(false); + logInfo.setMessage(t.getMessage()); + log.error("FAIL", t); + + syncOut.setResponseCode(500); + syncOut.setHeader("Content-Type", "text/plan"); + try + { + syncOut.getOutputStream().write(t.getMessage().getBytes()); + } + catch (IOException e) + { + log.warn("Could not write response to output stream", e); + } + +// ErrorSummary errorSummary = +// new ErrorSummary(t.getMessage(), ErrorType.FATAL); +// try +// { +// jobUpdater.setPhase(job.getID(), ExecutionPhase.EXECUTING, +// ExecutionPhase.ERROR, errorSummary, +// new Date()); +// } +// catch(Throwable oops) +// { +// log.debug("failed to set final error status after " + t, oops); +// } + } + } + +} diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/AddGroupMemberAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/AddGroupMemberAction.java new file mode 100755 index 0000000000000000000000000000000000000000..9577061cca259dcc76f5e4dae527685aafc7164d --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/AddGroupMemberAction.java @@ -0,0 +1,109 @@ +/* + ************************************************************************ + ******************* 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.ac.Group; +import ca.nrc.cadc.ac.GroupAlreadyExistsException; +import ca.nrc.cadc.ac.server.GroupPersistence; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +public class AddGroupMemberAction extends GroupsAction +{ + private final String groupName; + private final String groupMemberName; + + AddGroupMemberAction(GroupLogInfo logInfo, String groupName, + String groupMemberName) + { + super(logInfo); + this.groupName = groupName; + this.groupMemberName = groupMemberName; + } + + public Object run() + throws Exception + { + GroupPersistence groupPersistence = getGroupPersistence(); + Group group = groupPersistence.getGroup(this.groupName); + Group toAdd = groupPersistence.getGroup(this.groupMemberName); + if (!group.getGroupMembers().add(toAdd)) + { + throw new GroupAlreadyExistsException(this.groupMemberName); + } + groupPersistence.modifyGroup(group); + + 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/AddUserMemberAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/AddUserMemberAction.java new file mode 100755 index 0000000000000000000000000000000000000000..d8a84b2650cf2b3d4cd191b5fbf7f4a54014235c --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/AddUserMemberAction.java @@ -0,0 +1,118 @@ +/* + ************************************************************************ + ******************* 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.ac.Group; +import ca.nrc.cadc.ac.MemberAlreadyExistsException; +import ca.nrc.cadc.ac.User; +import ca.nrc.cadc.ac.server.GroupPersistence; +import ca.nrc.cadc.ac.server.UserPersistence; +import ca.nrc.cadc.auth.AuthenticationUtil; +import java.security.Principal; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +public class AddUserMemberAction extends GroupsAction +{ + private final String groupName; + private final String userID; + private final String userIDType; + + AddUserMemberAction(GroupLogInfo logInfo, String groupName, String userID, + String userIDType) + { + super(logInfo); + this.groupName = groupName; + this.userID = userID; + this.userIDType = userIDType; + } + + @SuppressWarnings("unchecked") + public Object run() + throws Exception + { + GroupPersistence groupPersistence = getGroupPersistence(); + UserPersistence userPersistence = getUserPersistence(); + Group group = groupPersistence.getGroup(this.groupName); + Principal userPrincipal = AuthenticationUtil.createPrincipal(this.userID, this.userIDType); + User toAdd = userPersistence.getUser(userPrincipal); + if (!group.getUserMembers().add(toAdd)) + { + 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/CreateGroupAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/CreateGroupAction.java new file mode 100755 index 0000000000000000000000000000000000000000..32661345fc85f1042784a01421c27da98d4b9c48 --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/CreateGroupAction.java @@ -0,0 +1,117 @@ +/* + ************************************************************************ + ******************* 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 java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import ca.nrc.cadc.ac.Group; +import ca.nrc.cadc.ac.GroupReader; +import ca.nrc.cadc.ac.GroupWriter; +import ca.nrc.cadc.ac.User; +import ca.nrc.cadc.ac.server.GroupPersistence; + +public class CreateGroupAction extends GroupsAction +{ + private final InputStream inputStream; + + CreateGroupAction(GroupLogInfo logInfo, InputStream inputStream) + { + super(logInfo); + this.inputStream = inputStream; + } + + public Object run() + throws Exception + { + GroupPersistence groupPersistence = getGroupPersistence(); + Group group = GroupReader.read(this.inputStream); + Group newGroup = groupPersistence.addGroup(group); + this.response.setContentType("application/xml"); + GroupWriter.write(newGroup, this.response.getOutputStream()); + + List<String> addedMembers = null; + if ((newGroup.getUserMembers().size() > 0) || (newGroup.getGroupMembers().size() > 0)) + { + addedMembers = new ArrayList<String>(); + for (Group gr : newGroup.getGroupMembers()) + { + addedMembers.add(gr.getID()); + } + for (User usr : newGroup.getUserMembers()) + { + addedMembers.add(usr.getUserID().getName()); + } + } + logGroupInfo(newGroup.getID(), null, addedMembers); + return null; + } + +} diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/DeleteGroupAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/DeleteGroupAction.java new file mode 100755 index 0000000000000000000000000000000000000000..8f619fa381cc12469cf9ff0b196c280364d22571 --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/DeleteGroupAction.java @@ -0,0 +1,108 @@ +/* + ************************************************************************ + ******************* 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 java.util.ArrayList; + +import ca.nrc.cadc.ac.Group; +import ca.nrc.cadc.ac.User; +import ca.nrc.cadc.ac.server.GroupPersistence; + +public class DeleteGroupAction extends GroupsAction +{ + private final String groupName; + + DeleteGroupAction(GroupLogInfo logInfo, String groupName) + { + super(logInfo); + this.groupName = groupName; + } + + public Object run() + throws Exception + { + GroupPersistence groupPersistence = getGroupPersistence(); + Group deletedGroup = groupPersistence.getGroup(this.groupName); + groupPersistence.deleteGroup(this.groupName); + if ((deletedGroup.getUserMembers().size() > 0) || (deletedGroup.getGroupMembers().size() > 0)) + { + this.logInfo.deletedMembers = new ArrayList<String>(); + for (Group gr : deletedGroup.getGroupMembers()) + { + this.logInfo.deletedMembers.add(gr.getID()); + } + for (User usr : deletedGroup.getUserMembers()) + { + this.logInfo.deletedMembers.add(usr.getUserID().getName()); + } + } + return null; + } + +} diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/GetGroupAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/GetGroupAction.java new file mode 100755 index 0000000000000000000000000000000000000000..e72003567a83a2723ee6ce15376d5a5beee22027 --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/GetGroupAction.java @@ -0,0 +1,94 @@ +/* + ************************************************************************ + ******************* 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.ac.Group; +import ca.nrc.cadc.ac.GroupWriter; +import ca.nrc.cadc.ac.server.GroupPersistence; + +public class GetGroupAction extends GroupsAction +{ + private final String groupName; + + GetGroupAction(GroupLogInfo logInfo, String groupName) + { + super(logInfo); + this.groupName = groupName; + } + + public Object run() + throws Exception + { + GroupPersistence groupPersistence = getGroupPersistence(); + Group group = groupPersistence.getGroup(this.groupName); + this.response.setContentType("application/xml"); + GroupWriter.write(group, this.response.getOutputStream()); + return null; + } + +} diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/GetGroupNamesAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/GetGroupNamesAction.java new file mode 100644 index 0000000000000000000000000000000000000000..a29e5fcf29a37ebf66ded5fd96cff4edbe77f26c --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/GetGroupNamesAction.java @@ -0,0 +1,111 @@ +/* + ************************************************************************ + ******************* 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 java.io.Writer; +import java.util.Collection; + +import org.apache.log4j.Logger; + +import ca.nrc.cadc.ac.server.GroupPersistence; + +public class GetGroupNamesAction extends GroupsAction +{ + + private static final Logger log = Logger.getLogger(GetGroupNamesAction.class); + + GetGroupNamesAction(GroupLogInfo logInfo) + { + super(logInfo); + } + + public Object run() + throws Exception + { + GroupPersistence groupPersistence = getGroupPersistence(); + Collection<String> groups = groupPersistence.getGroupNames(); + log.debug("Found " + groups.size() + " group names"); + response.setContentType("text/plain"); + log.debug("Set content-type to text/plain"); + Writer writer = response.getWriter(); + boolean start = true; + for (final String group : groups) + { + if (!start) + { + writer.write("\r\n"); + } + writer.write(group); + start = false; + } + + return null; + } +} diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/GroupLogInfo.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/GroupLogInfo.java new file mode 100755 index 0000000000000000000000000000000000000000..512610114aa61aa3cc24d30a2fd62c3922f93e7c --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/GroupLogInfo.java @@ -0,0 +1,86 @@ +/* + ************************************************************************ + ******************* 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.log.ServletLogInfo; +import java.util.List; +import javax.servlet.http.HttpServletRequest; + +public class GroupLogInfo extends ServletLogInfo +{ + public String groupID; + public List<String> addedMembers; + public List<String> deletedMembers; + + public GroupLogInfo(HttpServletRequest request) + { + super(request); + } + +} diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/GroupsAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/GroupsAction.java new file mode 100755 index 0000000000000000000000000000000000000000..02f64926a9982e7ae88b89bed6c054087cb473a9 --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/GroupsAction.java @@ -0,0 +1,249 @@ +/* + ************************************************************************ + ******************* 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 java.io.IOException; +import java.security.AccessControlException; +import java.security.Principal; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.List; + +import javax.security.auth.Subject; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; + +import ca.nrc.cadc.ac.GroupAlreadyExistsException; +import ca.nrc.cadc.ac.GroupNotFoundException; +import ca.nrc.cadc.ac.MemberAlreadyExistsException; +import ca.nrc.cadc.ac.MemberNotFoundException; +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.net.TransientException; + +public abstract class GroupsAction + implements PrivilegedExceptionAction<Object> +{ + private static final Logger log = Logger.getLogger(GroupsAction.class); + protected GroupLogInfo logInfo; + protected HttpServletResponse response; + + GroupsAction(GroupLogInfo logInfo) + { + this.logInfo = logInfo; + } + + public void doAction(Subject subject, HttpServletResponse response) + 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; + } + } + catch (AccessControlException e) + { + log.debug(e); + String message = "Permission Denied"; + this.logInfo.setMessage(message); + sendError(403, message); + } + catch (IllegalArgumentException e) + { + log.debug(e); + String message = e.getMessage(); + this.logInfo.setMessage(message); + sendError(400, message); + } + catch (MemberNotFoundException e) + { + log.debug(e); + String message = "Member not found: " + e.getMessage(); + this.logInfo.setMessage(message); + sendError(404, message); + } + catch (GroupNotFoundException e) + { + log.debug(e); + String message = "Group not found: " + e.getMessage(); + this.logInfo.setMessage(message); + sendError(404, message); + } + catch (UserNotFoundException e) + { + log.debug(e); + String message = "User not found: " + e.getMessage(); + this.logInfo.setMessage(message); + sendError(404, message); + } + catch (MemberAlreadyExistsException e) + { + log.debug(e); + String message = "Member already exists: " + e.getMessage(); + this.logInfo.setMessage(message); + sendError(409, message); + } + catch (GroupAlreadyExistsException e) + { + log.debug(e); + String message = "Group already exists: " + e.getMessage(); + this.logInfo.setMessage(message); + sendError(409, message); + } + catch (UnsupportedOperationException e) + { + log.debug(e); + this.logInfo.setMessage("Not yet implemented."); + sendError(501); + } + catch (TransientException e) + { + String message = "Internal Transient Error: " + e.getMessage(); + this.logInfo.setSuccess(false); + this.logInfo.setMessage(message); + log.error(message, e); + sendError(503, message); + } + catch (Throwable t) + { + String message = "Internal Error: " + t.getMessage(); + this.logInfo.setSuccess(false); + this.logInfo.setMessage(message); + log.error(message, t); + sendError(500, message); + } + } + + private void sendError(int responseCode) + throws IOException + { + sendError(responseCode, null); + } + + private void sendError(int responseCode, String message) + throws IOException + { + if (!this.response.isCommitted()) + { + this.response.setContentType("text/plain"); + if (message != null) + { + this.response.getWriter().write(message); + } + this.response.setStatus(responseCode); + } + else + { + log.warn("Could not send error " + responseCode + " (" + message + ") because the response is already committed."); + } + } + + <T extends Principal> GroupPersistence<T> getGroupPersistence() + { + PluginFactory pluginFactory = new PluginFactory(); + return pluginFactory.getGroupPersistence(); + } + + <T extends Principal> UserPersistence<T> getUserPersistence() + { + PluginFactory pluginFactory = new PluginFactory(); + return pluginFactory.getUserPersistence(); + } + + protected void logGroupInfo(String groupID, List<String> deletedMembers, List<String> addedMembers) + { + this.logInfo.groupID = groupID; + this.logInfo.addedMembers = addedMembers; + this.logInfo.deletedMembers = deletedMembers; + } + +} diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/GroupsActionFactory.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/GroupsActionFactory.java new file mode 100755 index 0000000000000000000000000000000000000000..83ecc9d1f7a0caae37d88e1b53d7c7183e1079e5 --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/GroupsActionFactory.java @@ -0,0 +1,194 @@ +/* + ************************************************************************ + ******************* 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 java.io.IOException; +import java.net.URL; +import java.net.URLDecoder; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.log4j.Logger; + +import ca.nrc.cadc.util.StringUtil; + +public 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 = ""; + } + + if (path.startsWith("/")) + { + path = path.substring(1); + } + + if (path.endsWith("/")) + { + path = path.substring(0, path.length() - 1); + } + + String[] segments = new String[0]; + if (StringUtil.hasText(path)) + { + segments = path.split("/"); + } + + if (segments.length == 0) + { + if (method.equals("GET")) + { + action = new GetGroupNamesAction(logInfo); + } + else if (method.equals("PUT")) + { + action = new CreateGroupAction(logInfo, request.getInputStream()); + } + + } + else if (segments.length == 1) + { + String groupName = segments[0]; + if (method.equals("GET")) + { + action = new GetGroupAction(logInfo, groupName); + } + else if (method.equals("DELETE")) + { + action = new DeleteGroupAction(logInfo, groupName); + } + else if (method.equals("POST")) + { + final URL requestURL = + new URL(request.getRequestURL().toString()); + final String redirectURI = requestURL.getProtocol() + "://" + + requestURL.getHost() + ":" + + requestURL.getPort() + + request.getContextPath() + + request.getServletPath() + + "/" + path; + action = new ModifyGroupAction(logInfo, groupName, redirectURI, + request.getInputStream()); + } + } + else if (segments.length == 3) + { + String groupName = segments[0]; + String memberCategory = segments[1]; + if (method.equals("PUT")) + { + if (memberCategory.equals("groupMembers")) + { + String groupMemberName = segments[2]; + action = new AddGroupMemberAction(logInfo, groupName, groupMemberName); + } + else if (memberCategory.equals("userMembers")) + { + String userMemberID = URLDecoder.decode(segments[2], "UTF-8"); + String userMemberIDType = request.getParameter("idType"); + action = new AddUserMemberAction(logInfo, groupName, userMemberID, userMemberIDType); + } + } + else if (method.equals("DELETE")) + { + if (memberCategory.equals("groupMembers")) + { + String groupMemberName = segments[2]; + action = new RemoveGroupMemberAction(logInfo, groupName, groupMemberName); + } + else if (memberCategory.equals("userMembers")) + { + String memberUserID = URLDecoder.decode(segments[2], "UTF-8"); + String memberUserIDType = request.getParameter("idType"); + action = new RemoveUserMemberAction(logInfo, groupName, memberUserID, memberUserIDType); + } + } + } + + if (action != null) + { + log.debug("Returning action: " + action.getClass()); + return action; + } + throw new IllegalArgumentException("Bad groups request: " + method + " on " + path); + } + +} diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/GroupsServlet.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/GroupsServlet.java new file mode 100755 index 0000000000000000000000000000000000000000..dd62ed5cdb871629bb86aa975b1a24e7b583e492 --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/GroupsServlet.java @@ -0,0 +1,161 @@ +/* + ************************************************************************ + ******************* 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 java.io.IOException; + +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.auth.AuthenticationUtil; + +public class GroupsServlet extends HttpServlet +{ + private static final Logger log = Logger.getLogger(GroupsServlet.class); + + /** + * Create a GroupAction and run the action safely. + */ + private void doAction(HttpServletRequest request, HttpServletResponse response) + throws IOException + { + long start = System.currentTimeMillis(); + GroupLogInfo logInfo = new GroupLogInfo(request); + try + { + log.info(logInfo.start()); + Subject subject = AuthenticationUtil.getSubject(request); + logInfo.setSubject(subject); + GroupsAction action = GroupsActionFactory.getGroupsAction(request, logInfo); + action.doAction(subject, response); + } + catch (IllegalArgumentException e) + { + log.debug(e.getMessage(), e); + logInfo.setMessage(e.getMessage()); + logInfo.setSuccess(false); + response.getWriter().write(e.getMessage()); + response.setStatus(400); + } + catch (Throwable t) + { + String message = "Internal Server Error: " + t.getMessage(); + log.error(message, t); + logInfo.setSuccess(false); + logInfo.setMessage(message); + response.getWriter().write(message); + response.setStatus(500); + } + finally + { + logInfo.setElapsedTime(System.currentTimeMillis() - start); + log.info(logInfo.end()); + } + } + + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws IOException + { + doAction(request, response); + } + + @Override + public void doPost(HttpServletRequest request, HttpServletResponse response) + throws IOException + { + doAction(request, response); + } + + @Override + public void doDelete(HttpServletRequest request, HttpServletResponse response) + throws IOException + { + doAction(request, response); + } + + @Override + public void doPut(HttpServletRequest request, HttpServletResponse response) + throws IOException + { + doAction(request, response); + } + + @Override + public void doHead(HttpServletRequest request, HttpServletResponse response) + throws IOException + { + doAction(request, response); + } + +} diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/ModifyGroupAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/ModifyGroupAction.java new file mode 100755 index 0000000000000000000000000000000000000000..c7a03ca5688c0d2c697ff24296428310767edc29 --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/ModifyGroupAction.java @@ -0,0 +1,142 @@ +/* + ************************************************************************ + ******************* 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 java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import ca.nrc.cadc.ac.Group; +import ca.nrc.cadc.ac.GroupReader; +import ca.nrc.cadc.ac.User; +import ca.nrc.cadc.ac.server.GroupPersistence; + +public class ModifyGroupAction extends GroupsAction +{ + private final String groupName; + private final String request; + private final InputStream inputStream; + + ModifyGroupAction(GroupLogInfo logInfo, String groupName, + final String request, InputStream inputStream) + { + super(logInfo); + this.groupName = groupName; + this.request = request; + this.inputStream = inputStream; + } + + public Object run() + throws Exception + { + GroupPersistence groupPersistence = getGroupPersistence(); + Group group = GroupReader.read(this.inputStream); + Group oldGroup = groupPersistence.getGroup(this.groupName); + groupPersistence.modifyGroup(group); + + List<String> addedMembers = new ArrayList<String>(); + for (User member : group.getUserMembers()) + { + if (!oldGroup.getUserMembers().remove(member)) + { + addedMembers.add(member.getUserID().getName()); + } + } + for (Group gr : group.getGroupMembers()) + { + if (!oldGroup.getGroupMembers().remove(gr)) + { + addedMembers.add(gr.getID()); + } + } + if (addedMembers.isEmpty()) + { + addedMembers = null; + } + List<String> deletedMembers = new ArrayList<String>(); + for (User member : oldGroup.getUserMembers()) + { + deletedMembers.add(member.getUserID().getName()); + } + for (Group gr : oldGroup.getGroupMembers()) + { + deletedMembers.add(gr.getID()); + } + if (deletedMembers.isEmpty()) + { + deletedMembers = null; + } + logGroupInfo(group.getID(), deletedMembers, addedMembers); + + this.response.sendRedirect(request); + + return null; + } + +} diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/RemoveGroupMemberAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/RemoveGroupMemberAction.java new file mode 100755 index 0000000000000000000000000000000000000000..39e148916a204e9369340fe50a5b0eabc22c69bf --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/RemoveGroupMemberAction.java @@ -0,0 +1,108 @@ +/* + ************************************************************************ + ******************* 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.ac.Group; +import ca.nrc.cadc.ac.GroupNotFoundException; +import ca.nrc.cadc.ac.server.GroupPersistence; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +public class RemoveGroupMemberAction extends GroupsAction +{ + private final String groupName; + private final String groupMemberName; + + RemoveGroupMemberAction(GroupLogInfo logInfo, String groupName, String groupMemberName) + { + super(logInfo); + this.groupName = groupName; + this.groupMemberName = groupMemberName; + } + + public Object run() + throws Exception + { + GroupPersistence groupPersistence = getGroupPersistence(); + Group group = groupPersistence.getGroup(this.groupName); + Group toRemove = groupPersistence.getGroup(this.groupMemberName); + if (!group.getGroupMembers().remove(toRemove)) + { + throw new GroupNotFoundException(this.groupMemberName); + } + groupPersistence.modifyGroup(group); + + 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/RemoveUserMemberAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/RemoveUserMemberAction.java new file mode 100755 index 0000000000000000000000000000000000000000..c9612f663c5009d88c9d00d17fa82974a266a6bb --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/RemoveUserMemberAction.java @@ -0,0 +1,116 @@ +/* + ************************************************************************ + ******************* 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.ac.Group; +import ca.nrc.cadc.ac.MemberNotFoundException; +import ca.nrc.cadc.ac.User; +import ca.nrc.cadc.ac.server.GroupPersistence; +import ca.nrc.cadc.ac.server.UserPersistence; +import ca.nrc.cadc.auth.AuthenticationUtil; +import java.security.Principal; +import java.util.ArrayList; +import java.util.List; + +public class RemoveUserMemberAction extends GroupsAction +{ + private final String groupName; + private final String userID; + private final String userIDType; + + RemoveUserMemberAction(GroupLogInfo logInfo, String groupName, String userID, String userIDType) + { + super(logInfo); + this.groupName = groupName; + this.userID = userID; + this.userIDType = userIDType; + } + + @SuppressWarnings("unchecked") + public Object run() + throws Exception + { + GroupPersistence groupPersistence = getGroupPersistence(); + UserPersistence userPersistence = getUserPersistence(); + Group group = groupPersistence.getGroup(this.groupName); + Principal userPrincipal = AuthenticationUtil.createPrincipal(this.userID, this.userIDType); + User toRemove = userPersistence.getUser(userPrincipal); + if (!group.getUserMembers().remove(toRemove)) + { + throw new MemberNotFoundException(); + } + groupPersistence.modifyGroup(group); + + List<String> deletedMembers = new ArrayList<String>(); + deletedMembers.add(toRemove.getUserID().getName()); + logGroupInfo(group.getID(), deletedMembers, null); + return null; + } + +} diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/RequestValidatorTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/RequestValidatorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..94760917ca297b709b57a06d0700769e95dd9d05 --- /dev/null +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/RequestValidatorTest.java @@ -0,0 +1,200 @@ +/* + ************************************************************************ + ******************* 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; + +import ca.nrc.cadc.ac.Role; +import ca.nrc.cadc.ac.server.web.AddUserMemberActionTest; +import ca.nrc.cadc.auth.AuthenticationUtil; +import ca.nrc.cadc.util.Log4jInit; +import ca.nrc.cadc.uws.Parameter; +import java.security.Principal; +import java.util.ArrayList; +import java.util.List; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author jburke + */ +public class RequestValidatorTest +{ + private final static Logger log = Logger.getLogger(AddUserMemberActionTest.class); + + @BeforeClass + public static void setUpClass() + { + Log4jInit.setLevel("ca.nrc.cadc.ac", Level.INFO); + } + + /** + * Test of validate method, of class RequestValidator. + */ + @Test + public void testValidate() + { + try + { + RequestValidator rv = new RequestValidator(); + + try + { + rv.validate(null); + fail("null parameter list should throw IllegalArgumentException"); + } + catch (IllegalArgumentException ignore) {} + + List<Parameter> paramList = new ArrayList<Parameter>(); + try + { + rv.validate(paramList); + fail("empty parameter list should throw IllegalArgumentException"); + } + catch (IllegalArgumentException ignore) {} + + paramList.add(new Parameter("IDTYPE", "idtype")); + paramList.add(new Parameter("ROLE", "role")); + try + { + rv.validate(paramList); + fail("missing ID parameter should throw IllegalArgumentException"); + } + catch (IllegalArgumentException ignore) {} + + paramList.clear(); + paramList.add(new Parameter("ID", "foo")); + paramList.add(new Parameter("ROLE", "role")); + try + { + rv.validate(paramList); + fail("missing IDTYPE parameter should throw IllegalArgumentException"); + } + catch (IllegalArgumentException ignore) {} + + paramList.clear(); + paramList.add(new Parameter("ID", "foo")); + paramList.add(new Parameter("IDTYPE", "idtype")); + try + { + rv.validate(paramList); + fail("missing ROLE parameter should throw IllegalArgumentException"); + } + catch (IllegalArgumentException ignore) {} + + paramList.clear(); + paramList.add(new Parameter("ID", "foo")); + paramList.add(new Parameter("IDTYPE", AuthenticationUtil.AUTH_TYPE_HTTP)); + paramList.add(new Parameter("ROLE", "foo")); + try + { + rv.validate(paramList); + fail("invalid ROLE parameter should throw IllegalArgumentException"); + } + catch (IllegalArgumentException ignore) {} + + paramList.clear(); + paramList.add(new Parameter("ID", "foo")); + paramList.add(new Parameter("IDTYPE", AuthenticationUtil.AUTH_TYPE_HTTP)); + paramList.add(new Parameter("ROLE", "foo")); + paramList.add(new Parameter("GROUPID", "")); + try + { + rv.validate(paramList); + fail("empty GROUPID parameter value should throw IllegalArgumentException"); + } + catch (IllegalArgumentException ignore) {} + + paramList.clear(); + paramList.add(new Parameter("ID", "foo")); + paramList.add(new Parameter("IDTYPE", AuthenticationUtil.AUTH_TYPE_HTTP)); + paramList.add(new Parameter("ROLE", Role.MEMBER.getValue())); + rv.validate(paramList); + + assertNotNull(rv.getPrincipal()); + assertNotNull(rv.getRole()); + assertNull(rv.getGroupID()); + + paramList.add(new Parameter("GROUPID", "bar")); + rv.validate(paramList); + + assertNotNull(rv.getPrincipal()); + assertNotNull(rv.getRole()); + assertNotNull(rv.getGroupID()); + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + fail("unexpected error: " + t.getMessage()); + } + } + +} diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/AbstractLdapDAOTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/AbstractLdapDAOTest.java new file mode 100644 index 0000000000000000000000000000000000000000..5801981ac380b8f2314d4b321952cd86d15789ea --- /dev/null +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/AbstractLdapDAOTest.java @@ -0,0 +1,82 @@ +/** + ************************************************************************ + ******************* 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/>. + * + ************************************************************************ + */ + +package ca.nrc.cadc.ac.server.ldap; + +/** + * Created by jburke on 2014-11-03. + */ +public class AbstractLdapDAOTest +{ + static final String CONFIG = LdapConfig.class.getSimpleName() + ".test.properties"; + + static protected LdapConfig getLdapConfig() + { + return LdapConfig.getLdapConfig(CONFIG); + } + +} diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapDAOTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapDAOTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ecd65e9483ab73d8813a600fc6833ca38dbfb673 --- /dev/null +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapDAOTest.java @@ -0,0 +1,177 @@ +/** + ************************************************************************ + ******************* 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/>. + * + ************************************************************************ + */ + + +package ca.nrc.cadc.ac.server.ldap; + +import java.security.PrivilegedExceptionAction; + +import javax.net.ssl.SSLSocketFactory; +import javax.security.auth.Subject; +import javax.security.auth.x500.X500Principal; + +import ca.nrc.cadc.auth.HttpPrincipal; +import ca.nrc.cadc.auth.NumericPrincipal; + +import com.unboundid.ldap.sdk.LDAPConnection; + +import org.junit.Test; +import org.junit.BeforeClass; +import static org.junit.Assert.*; + + +public class LdapDAOTest extends AbstractLdapDAOTest +{ + static LdapConfig config; + + @BeforeClass + public static void setUpBeforeClass() throws Exception + { + // get the configuration of the development server from and config files... + config = getLdapConfig(); + } + @Test + public void testLdapBindConnection() throws Exception + { + //TODO use a test user to test with. To be done when addUser available. + //LdapUserDAO<X500Principal> userDAO = new LdapUserDAO<X500Principal>(); + final X500Principal subjPrincipal = new X500Principal( + "cn=cadcdaotest1,ou=cadc,o=hia,c=ca"); + + // User authenticated with HttpPrincipal + HttpPrincipal httpPrincipal = new HttpPrincipal("CadcDaoTest1"); + Subject subject = new Subject(); + + subject.getPrincipals().add(httpPrincipal); + + final LdapDAOTestImpl ldapDao = new LdapDAOTestImpl(config); + + Subject.doAs(subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + testConnection(ldapDao.getConnection()); + return null; + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + } + }); + + + subject = new Subject(); + subject.getPrincipals().add(subjPrincipal); + + Subject.doAs(subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + testConnection(ldapDao.getConnection()); + return null; + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + } + }); + + + NumericPrincipal numPrincipal = new NumericPrincipal(1866); + subject.getPrincipals().add(numPrincipal); + + Subject.doAs(subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + + testConnection(ldapDao.getConnection()); + return null; + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + } + }); + + } + + private void testConnection(final LDAPConnection ldapCon) + { + assertTrue("Not connected but should be.", ldapCon.isConnected()); + } + +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..7d3be479f44fc01e2eaaab7805e645a1dc9f573a --- /dev/null +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapDAOTestImpl.java @@ -0,0 +1,90 @@ +/** + ************************************************************************ + ******************* 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/>. + * + ************************************************************************ + */ + + +package ca.nrc.cadc.ac.server.ldap; + +import java.security.AccessControlException; + +import com.unboundid.ldap.sdk.LDAPConnection; +import com.unboundid.ldap.sdk.LDAPException; + + +public class LdapDAOTestImpl extends LdapDAO +{ + public LdapDAOTestImpl(LdapConfig config) + { + super(config); + } + + @Override + public LDAPConnection getConnection() throws LDAPException, + AccessControlException + { + return super.getConnection(); + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..7af54bc0ae0a9ec3c1e3621a31038538440a7ae9 --- /dev/null +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAOTest.java @@ -0,0 +1,937 @@ +/** + ************************************************************************ + ******************* 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/>. + * + ************************************************************************ + */ + +package ca.nrc.cadc.ac.server.ldap; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.security.AccessControlException; +import java.security.PrivilegedExceptionAction; +import java.util.Collection; + +import javax.security.auth.Subject; +import javax.security.auth.x500.X500Principal; + +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.junit.BeforeClass; +import org.junit.Test; + +import ca.nrc.cadc.ac.ActivatedGroup; +import ca.nrc.cadc.ac.Group; +import ca.nrc.cadc.ac.GroupAlreadyExistsException; +import ca.nrc.cadc.ac.GroupNotFoundException; +import ca.nrc.cadc.ac.GroupProperty; +import ca.nrc.cadc.ac.Role; +import ca.nrc.cadc.ac.User; +import ca.nrc.cadc.ac.UserNotFoundException; +import ca.nrc.cadc.util.Log4jInit; +import static org.junit.Assert.assertNotNull; + +public class LdapGroupDAOTest extends AbstractLdapDAOTest +{ + private static final Logger log = Logger.getLogger(LdapGroupDAOTest.class); + + static String daoTestDN1 = "cn=cadcdaotest1,ou=cadc,o=hia,c=ca"; + static String daoTestDN2 = "cn=cadcdaotest2,ou=cadc,o=hia,c=ca"; + static String daoTestDN3 = "cn=cadcdaotest3,ou=cadc,o=hia,c=ca"; + static String unknownDN = "cn=foo,ou=cadc,o=hia,c=ca"; + + static X500Principal daoTestPrincipal1; + static X500Principal daoTestPrincipal2; + static X500Principal daoTestPrincipal3; + static X500Principal unknownPrincipal; + + static User<X500Principal> daoTestUser1; + static User<X500Principal> daoTestUser2; + static User<X500Principal> daoTestUser3; + static User<X500Principal> unknownUser; + + static Subject daoTestUser1Subject; + static Subject daoTestUser2Subject; + static Subject anonSubject; + + static LdapConfig config; + + @BeforeClass + public static void setUpBeforeClass() + throws Exception + { + Log4jInit.setLevel("ca.nrc.cadc.ac", Level.INFO); + + // get the configuration of the development server from and config files... + config = getLdapConfig(); + + daoTestPrincipal1 = new X500Principal(daoTestDN1); + daoTestPrincipal2 = new X500Principal(daoTestDN2); + daoTestPrincipal3 = new X500Principal(daoTestDN3); + unknownPrincipal = new X500Principal(unknownDN); + + daoTestUser1 = new User<X500Principal>(daoTestPrincipal1); + daoTestUser2 = new User<X500Principal>(daoTestPrincipal2); + daoTestUser3 = new User<X500Principal>(daoTestPrincipal3); + unknownUser = new User<X500Principal>(unknownPrincipal); + + daoTestUser1Subject = new Subject(); + daoTestUser1Subject.getPrincipals().add(daoTestUser1.getUserID()); + + daoTestUser2Subject = new Subject(); + daoTestUser2Subject.getPrincipals().add(daoTestUser2.getUserID()); + + anonSubject = new Subject(); + anonSubject.getPrincipals().add(unknownUser.getUserID()); + } + + LdapGroupDAO<X500Principal> getGroupDAO() + { + return new LdapGroupDAO<X500Principal>(config, + new LdapUserDAO<X500Principal>(config)); + } + + String getGroupID() + { + return "CadcDaoTestGroup-" + System.currentTimeMillis(); + } + + @Test + public void testOneGroup() throws Exception + { + // do everything as owner + Subject.doAs(daoTestUser1Subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + Group expectGroup = new Group(getGroupID(), daoTestUser1); + Group actualGroup = getGroupDAO().addGroup(expectGroup); + log.debug("addGroup: " + expectGroup.getID()); + assertGroupsEqual(expectGroup, actualGroup); + + Group otherGroup = new Group(getGroupID(), daoTestUser1); + otherGroup = getGroupDAO().addGroup(otherGroup); + log.debug("addGroup: " + otherGroup.getID()); + + // modify group fields + // description + expectGroup.description = "Happy testing"; + actualGroup = getGroupDAO().modifyGroup(expectGroup); + assertGroupsEqual(expectGroup, actualGroup); + + expectGroup.description = null; + actualGroup = getGroupDAO().modifyGroup(expectGroup); + assertGroupsEqual(expectGroup, actualGroup); + + // userMembers + expectGroup.getUserMembers().add(daoTestUser2); + actualGroup = getGroupDAO().modifyGroup(expectGroup); + assertGroupsEqual(expectGroup, actualGroup); + + expectGroup.getUserMembers().remove(daoTestUser2); + actualGroup = getGroupDAO().modifyGroup(expectGroup); + assertGroupsEqual(expectGroup, actualGroup); + + // groupMembers + expectGroup.getGroupMembers().add(otherGroup); + actualGroup = getGroupDAO().modifyGroup(expectGroup); + assertGroupsEqual(expectGroup, actualGroup); + + expectGroup.getGroupMembers().remove(otherGroup); + actualGroup = getGroupDAO().modifyGroup(expectGroup); + assertGroupsEqual(expectGroup, actualGroup); + + expectGroup.description = "Happy testing"; + expectGroup.getUserMembers().add(daoTestUser2); + expectGroup.getGroupMembers().add(otherGroup); + + // userAdmins + expectGroup.getUserAdmins().add(daoTestUser3); + actualGroup = getGroupDAO().modifyGroup(expectGroup); + assertGroupsEqual(expectGroup, actualGroup); + + // groupAdmins + Group adminGroup = new Group(getGroupID(), daoTestUser1); + adminGroup = getGroupDAO().addGroup(adminGroup); + expectGroup.getGroupAdmins().add(adminGroup); + actualGroup = getGroupDAO().modifyGroup(expectGroup); + assertGroupsEqual(expectGroup, actualGroup); + + // delete the group + getGroupDAO().deleteGroup(expectGroup.getID()); + try + { + getGroupDAO().getGroup(expectGroup.getID()); + fail("get on deleted group should throw exception"); + } + catch (GroupNotFoundException ignore) {} + + // reactivate the group + actualGroup = getGroupDAO().addGroup(expectGroup); + assertTrue(actualGroup instanceof ActivatedGroup); + assertGroupsEqual(expectGroup, actualGroup); + + // get the activated group + actualGroup = getGroupDAO().getGroup(expectGroup.getID()); + assertGroupsEqual(expectGroup, actualGroup); + + // delete the group + getGroupDAO().deleteGroup(expectGroup.getID()); + + return null; + } + catch (Exception e) + { + e.printStackTrace(); + throw new Exception("Problems", e); + } + } + }); + } + + @Test + public void testSearchOwnerGroups() throws Exception + { + Subject.doAs(daoTestUser1Subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + String groupID = getGroupID(); + Group testGroup = new Group(groupID, daoTestUser1); + testGroup = getGroupDAO().addGroup(testGroup); + + Collection<Group> groups = + getGroupDAO().getGroups(daoTestUser1.getUserID(), + Role.OWNER, null); + assertNotNull(groups); + + boolean found = false; + for (Group group : groups) + { + if (group.getID().equals(group.getID())) + { + found = true; + } + } + if (!found) + { + fail("Group for owner not found"); + } + + groups = getGroupDAO().getGroups(daoTestUser1.getUserID(), + Role.OWNER, groupID); + assertNotNull(groups); + assertEquals(1, groups.size()); + assertTrue(groups.iterator().next().equals(testGroup)); + + getGroupDAO().deleteGroup(groupID); + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + return null; + } + }); + } + + @Test + public void testSearchMemberGroups() throws Exception + { + final String groupID = getGroupID(); + final String testGroup1ID = groupID + ".1"; + final String testGroup2ID = groupID + ".2"; + + Subject.doAs(daoTestUser1Subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + Group testGroup1 = new Group(testGroup1ID, daoTestUser1); + testGroup1.getUserMembers().add(daoTestUser2); + testGroup1 = getGroupDAO().addGroup(testGroup1); + log.debug("add group: " + testGroup1ID); + + Group testGroup2 = new Group(testGroup2ID, daoTestUser1); + testGroup2.getUserMembers().add(daoTestUser2); + testGroup2 = getGroupDAO().addGroup(testGroup2); + log.debug("add group: " + testGroup2ID); + Thread.sleep(1000); //sleep to let memberof plugin in LDAP do its work + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + return null; + } + }); + + Subject.doAs(daoTestUser2Subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + Collection<Group> groups = + getGroupDAO().getGroups(daoTestUser2.getUserID(), + Role.MEMBER, null); + + assertNotNull(groups); + assertTrue(groups.size() >= 2); + + log.debug("testSearchMemberGroups groups found: " + groups.size()); + boolean found1 = false; + boolean found2 = false; + for (Group group : groups) + { + log.debug("member group: " + group.getID()); + if (group.getID().equals(testGroup1ID)) + { + found1 = true; + } + if (group.getID().equals(testGroup2ID)) + { + found2 = true; + } + } + if (!found1) + { + fail("Test group 1 not found"); + } + if (!found2) + { + fail("Test group 2 not found"); + } + + groups = getGroupDAO().getGroups(daoTestUser2.getUserID(), + Role.MEMBER, testGroup1ID); + assertNotNull(groups); + assertTrue(groups.size() == 1); + assertTrue(groups.iterator().next().getID().equals(testGroup1ID)); + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + return null; + } + }); + + Subject.doAs(daoTestUser1Subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + getGroupDAO().deleteGroup(testGroup1ID); + getGroupDAO().deleteGroup(testGroup2ID); + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + return null; + } + }); + } + + @Test + public void testSearchAdminGroups() throws Exception + { + final String groupID = getGroupID(); + final String testGroup1ID = groupID + ".1"; + final String testGroup2ID = groupID + ".2"; + + Subject.doAs(daoTestUser1Subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + Group testGroup1 = new Group(testGroup1ID, daoTestUser1); + testGroup1.getUserAdmins().add(daoTestUser2); + testGroup1 = getGroupDAO().addGroup(testGroup1); + log.debug("add group: " + testGroup1ID); + + Group testGroup2 = new Group(testGroup2ID, daoTestUser1); + testGroup2.getUserAdmins().add(daoTestUser2); + testGroup2 = getGroupDAO().addGroup(testGroup2); + log.debug("add group: " + testGroup2ID); + Thread.sleep(1000); // sleep to let memberof plugin do its work + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + return null; + } + }); + + Subject.doAs(daoTestUser2Subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + Collection<Group> groups = + getGroupDAO().getGroups(daoTestUser2.getUserID(), + Role.ADMIN, null); + + log.debug("testSearchAdminGroups groups found: " + groups.size()); + assertNotNull(groups); + assertTrue(groups.size() >= 2); + + boolean found1 = false; + boolean found2 = false; + for (Group group : groups) + { + log.debug("admin group: " + group.getID()); + if (group.getID().equals(testGroup1ID)) + { + found1 = true; + } + if (group.getID().equals(testGroup2ID)) + { + found2 = true; + } + } + if (!found1) + { + fail("Admin group " + testGroup1ID + " not found"); + } + if (!found2) + { + fail("Admin group " + testGroup2ID + " not found"); + } + + groups = getGroupDAO().getGroups(daoTestUser2.getUserID(), + Role.ADMIN, testGroup1ID); + assertNotNull(groups); + assertTrue(groups.size() == 1); + assertTrue(groups.iterator().next().getID().equals(testGroup1ID)); + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + return null; + } + }); + + Subject.doAs(daoTestUser1Subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + getGroupDAO().deleteGroup(testGroup1ID); + getGroupDAO().deleteGroup(testGroup2ID); + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + return null; + } + }); + } + + @Test + public void testGetGroupNames() throws Exception + { + final String groupID = getGroupID(); + final String testGroup1ID = groupID + ".1"; + final String testGroup2ID = groupID + ".2"; + + Subject.doAs(daoTestUser1Subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + Group testGroup1 = new Group(testGroup1ID, daoTestUser1); + testGroup1 = getGroupDAO().addGroup(testGroup1); + log.debug("add group: " + testGroup1ID); + + Group testGroup2 = new Group(testGroup2ID, daoTestUser1); + testGroup2 = getGroupDAO().addGroup(testGroup2); + log.debug("add group: " + testGroup2ID); + //Thread.sleep(1000); // sleep to let memberof plugin do its work + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + return null; + } + }); + + Subject.doAs(daoTestUser1Subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + Collection<String> groups = getGroupDAO().getGroupNames(); + + log.debug("testGetGroupNames groups found: " + groups.size()); + assertNotNull(groups); + assertTrue(groups.size() >= 2); + + boolean found1 = false; + boolean found2 = false; + for (String name : groups) + { + log.debug("group: " + name); + if (name.equals(testGroup1ID)) + { + found1 = true; + } + if (name.equals(testGroup2ID)) + { + found2 = true; + } + } + if (!found1) + { + fail("Admin group " + testGroup1ID + " not found"); + } + if (!found2) + { + fail("Admin group " + testGroup2ID + " not found"); + } + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + return null; + } + }); + + Subject.doAs(daoTestUser1Subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + getGroupDAO().deleteGroup(testGroup1ID); + getGroupDAO().deleteGroup(testGroup2ID); + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + return null; + } + }); + } + + @Test + public void testAddGroupExceptions() throws Exception + { + Subject.doAs(anonSubject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + getGroupDAO().addGroup(new Group(getGroupID(), daoTestUser1)); + fail("addGroup with anonymous access should throw " + + "AccessControlException"); + } + catch (AccessControlException ignore) {} + return null; + } + }); + + Subject.doAs(daoTestUser1Subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + getGroupDAO().addGroup(new Group("foo", unknownUser)); + fail("addGroup with unknown user should throw " + + "AccessControlException"); + } + catch (AccessControlException ignore) {} + + Group group = getGroupDAO().addGroup(new Group(getGroupID(), + daoTestUser1)); + + try + { + getGroupDAO().addGroup(group); + fail("addGroup with existing group should throw " + + "GroupAlreadyExistsException"); + } + catch (GroupAlreadyExistsException ignore) {} + + getGroupDAO().deleteGroup(group.getID()); + return null; + } + }); + } + + @Test + public void testGetGroupExceptions() throws Exception + { + final String groupID = getGroupID(); + + Subject.doAs(daoTestUser1Subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + getGroupDAO().getGroup(groupID); + fail("getGroup with unknown group should throw " + + "GroupNotFoundException"); + } + catch (GroupNotFoundException ignore) {} + + getGroupDAO().addGroup(new Group(groupID, daoTestUser1)); + return null; + } + }); + + Subject.doAs(anonSubject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + getGroupDAO().getGroup(groupID); + fail("getGroup with anonymous access should throw " + + "AccessControlException"); + } + catch (AccessControlException ignore) {} + return null; + } + }); + + Subject.doAs(daoTestUser1Subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + getGroupDAO().getGroup(groupID); + //fail("getGroup with anonymous access should throw " + + // "AccessControlException"); + } + catch (AccessControlException ignore) {} + return null; + } + }); + + // All access ACI's will allow anonymous access +// Subject.doAs(daoTestUser2Subject, new PrivilegedExceptionAction<Object>() +// { +// public Object run() throws Exception +// { +// try +// { +// getGroupDAO().getGroup(groupID); +// fail("getGroup with anonymous access should throw " + +// "AccessControlException"); +// } +// catch (AccessControlException ignore) {} +// return null; +// } +// }); + } + + @Test + public void testModifyGroupExceptions() throws Exception + { + final String groupID = getGroupID(); + + Subject.doAs(daoTestUser1Subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + getGroupDAO().addGroup(new Group(groupID, daoTestUser1)); + try + { + getGroupDAO().modifyGroup(new Group("foo", daoTestUser1)); + fail("modifyGroup with unknown user should throw " + + "GroupNotFoundException"); + } + catch (GroupNotFoundException ignore) {} + + return null; + } + }); + + Subject.doAs(anonSubject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + getGroupDAO().getGroup(groupID); + fail("getGroup with anonymous access should throw " + + "AccessControlException"); + } + catch (AccessControlException ignore) {} + return null; + } + }); + + Subject.doAs(daoTestUser1Subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + getGroupDAO().deleteGroup(groupID); + return null; + } + }); + } + + @Test + public void testDeleteGroupExceptions() throws Exception + { + final String groupID = getGroupID(); + + Subject.doAs(daoTestUser1Subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + getGroupDAO().deleteGroup(groupID); + fail("deleteGroup with unknown group should throw " + + "GroupNotFoundException"); + } + catch (GroupNotFoundException ignore) {} + + getGroupDAO().addGroup(new Group(groupID, daoTestUser1)); + return null; + } + }); + + Subject.doAs(anonSubject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + getGroupDAO().deleteGroup(groupID); + fail("deleteGroup with anonymous access should throw " + + "AccessControlException"); + } + catch (AccessControlException ignore) {} + return null; + } + }); + + Subject.doAs(daoTestUser1Subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + getGroupDAO().deleteGroup(groupID); + return null; + } + }); + } + + @Test + public void testSearchGroupsExceptions() throws Exception + { + final String groupID = getGroupID(); + + Subject.doAs(daoTestUser1Subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + getGroupDAO().addGroup(new Group(groupID, daoTestUser1)); + + try + { + getGroupDAO().getGroups(unknownPrincipal, Role.OWNER, + groupID); + fail("searchGroups with unknown user should throw " + + "UserNotFoundException"); + } + catch (AccessControlException ignore) {} + + try + { + getGroupDAO().getGroups(daoTestPrincipal1, Role.OWNER, + "foo"); + fail("searchGroups with unknown user should throw " + + "GroupNotFoundException"); + } + catch (GroupNotFoundException ignore) {} + return null; + } + }); + + Subject.doAs(anonSubject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + getGroupDAO().getGroups(daoTestPrincipal1, Role.OWNER, + groupID); + fail("searchGroups with anonymous access should throw " + + "AccessControlException"); + } + catch (AccessControlException ignore) {} + return null; + } + }); + + // + // change the user +// Subject.doAs(daoTestUser2Subject, new PrivilegedExceptionAction<Object>() +// { +// public Object run() throws Exception +// { +// try +// { +// Group group = getGroupDAO().getGroup(groupID); +// assertTrue(group == null); +// +// fail("searchGroups with un-authorized user should throw " + +// "AccessControlException"); +// } +// catch (AccessControlException ignore) +// { +// +// } +// +// return null; +// } +// }); + + Subject.doAs(daoTestUser1Subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + getGroupDAO().deleteGroup(groupID); + return null; + } + }); + } + + private void assertGroupsEqual(Group gr1, Group gr2) + { + if ((gr1 == null) && (gr2 == null)) + { + return; + } + assertEquals(gr1, gr2); + assertEquals(gr1.getID(), gr2.getID()); + assertEquals(gr1.description, gr2.description); + assertEquals(gr1.getOwner(), gr2.getOwner()); + + assertEquals(gr1.getGroupMembers(), gr2.getGroupMembers()); + assertEquals(gr1.getGroupMembers().size(), gr2.getGroupMembers().size()); + for (Group gr : gr1.getGroupMembers()) + { + assertTrue(gr2.getGroupMembers().contains(gr)); + } + + assertEquals(gr1.getUserMembers(), gr2.getUserMembers()); + assertEquals(gr1.getUserMembers().size(), gr2.getUserMembers() + .size()); + for (User<?> user : gr1.getUserMembers()) + { + assertTrue(gr2.getUserMembers().contains(user)); + } + + assertEquals(gr1.getGroupAdmins(), gr2.getGroupAdmins()); + assertEquals(gr1.getGroupAdmins().size(), gr2.getGroupAdmins().size()); + for (Group gr : gr1.getGroupAdmins()) + { + assertTrue(gr2.getGroupAdmins().contains(gr)); + } + + assertEquals(gr1.getUserAdmins(), gr2.getUserAdmins()); + assertEquals(gr1.getUserAdmins().size(), gr2.getUserAdmins() + .size()); + for (User<?> user : gr1.getUserAdmins()) + { + assertTrue(gr2.getUserAdmins().contains(user)); + } + + assertEquals(gr1.getProperties(), gr2.getProperties()); + for (GroupProperty prop : gr1.getProperties()) + { + assertTrue(gr2.getProperties().contains(prop)); + } + } + +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..abce3f7810d0941c878c2ea03a98de9c093dfc00 --- /dev/null +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAOTest.java @@ -0,0 +1,311 @@ +/* + ************************************************************************ + ******************* 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.ldap; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.security.Principal; +import java.security.PrivilegedExceptionAction; +import java.util.Collection; + +import javax.security.auth.Subject; +import javax.security.auth.x500.X500Principal; + +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.junit.BeforeClass; +import org.junit.Test; + +import ca.nrc.cadc.ac.PersonalDetails; +import ca.nrc.cadc.ac.User; +import ca.nrc.cadc.ac.UserDetails; +import ca.nrc.cadc.auth.HttpPrincipal; +import ca.nrc.cadc.util.Log4jInit; + +import com.unboundid.ldap.sdk.DN; + +public class LdapUserDAOTest extends AbstractLdapDAOTest +{ + private static final Logger log = Logger.getLogger(LdapUserDAOTest.class); + + static final String testUserX509DN = "cn=cadcdaotest1,ou=cadc,o=hia,c=ca"; + + static String testUserDN; + static User<X500Principal> testUser; + static LdapConfig config; + + @BeforeClass + public static void setUpBeforeClass() + throws Exception + { + Log4jInit.setLevel("ca.nrc.cadc.ac", Level.INFO); + + // get the configuration of the development server from and config files... + config = getLdapConfig(); + + testUser = new User<X500Principal>(new X500Principal(testUserX509DN)); + testUser.details.add(new PersonalDetails("CADC", "DAOTest1")); + testUser.getIdentities().add(new HttpPrincipal("CadcDaoTest1")); + + testUserDN = "uid=cadcdaotest1," + config.getUsersDN(); + } + + LdapUserDAO<X500Principal> getUserDAO() + { + return new LdapUserDAO<X500Principal>(config); + } + + /** + * Test of getUser method, of class LdapUserDAO. + */ + @Test + public void testGetUser() throws Exception + { + 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 + { + User<X500Principal> actual = getUserDAO().getUser(testUser.getUserID()); + check(testUser, actual); + + return null; + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + } + }); + + } + + /** + * Test of getUserGroups method, of class LdapUserDAO. + */ + @Test + public void testGetUserGroups() throws Exception + { + 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 + { + Collection<DN> groups = getUserDAO().getUserGroups(testUser.getUserID(), false); + assertNotNull(groups); + assertTrue(!groups.isEmpty()); + for (DN groupDN : groups) + log.debug(groupDN); + + groups = getUserDAO().getUserGroups(testUser.getUserID(), true); + assertNotNull(groups); + assertTrue(!groups.isEmpty()); + for (DN groupDN : groups) + log.debug(groupDN); + + return null; + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + } + }); + } + + /** + * Test of getUserGroups method, of class LdapUserDAO. + */ + @Test + public void testIsMember() throws Exception + { + 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 + { + boolean isMember = getUserDAO().isMember(testUser.getUserID(), "foo"); + assertFalse(isMember); + + String groupDN = "cn=cadcdaotestgroup1," + config.getGroupsDN(); + isMember = getUserDAO().isMember(testUser.getUserID(), groupDN); + assertTrue(isMember); + + return null; + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + } + }); + } + + /** + * Test of getMember. + */ + @Test + public void testGetMember() throws Exception + { + 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 + { + User<X500Principal> actual = getUserDAO().getMember(new DN(testUserDN)); + check(testUser, actual); + return null; + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + } + }); + + // should also work as a different user + subject = new Subject(); + subject.getPrincipals().add(new HttpPrincipal("CadcDaoTest2")); + + // do everything as owner + Subject.doAs(subject, new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + User<X500Principal> actual = getUserDAO().getMember(new DN(testUserDN)); + check(testUser, actual); + return null; + } + catch (Exception e) + { + throw new Exception("Problems", e); + } + } + }); + } + + private static void check(final User<? extends Principal> user1, final User<? extends Principal> user2) + { + assertEquals(user1, user2); + assertEquals(user1.details, user2.details); + assertEquals(user1.details.size(), user2.details.size()); + assertEquals(user1.getIdentities(), user2.getIdentities()); + for(UserDetails d1 : user1.details) + { + assertTrue(user2.details.contains(d1)); + if(d1 instanceof PersonalDetails) + { + PersonalDetails pd1 = (PersonalDetails)d1; + boolean found = false; + for(UserDetails d2 : user2.details) + { + if(d2 instanceof PersonalDetails) + { + PersonalDetails pd2 = (PersonalDetails)d2; + assertEquals(pd1, pd2); // already done in contains above but just in case + assertEquals(pd1.address, pd2.address); + assertEquals(pd1.city, pd2.city); + assertEquals(pd1.country, pd2.country); + assertEquals(pd1.email, pd2.email); + assertEquals(pd1.institute, pd2.institute); + found = true; + } + assertTrue(found); + } + } + } + + } + +} diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/AddGroupMemberActionTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/AddGroupMemberActionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..56fa6154db4f7a2ed1629abfa28de4eef024e7ab --- /dev/null +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/AddGroupMemberActionTest.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.server.web; + +import ca.nrc.cadc.ac.Group; +import ca.nrc.cadc.ac.GroupAlreadyExistsException; +import ca.nrc.cadc.ac.server.GroupPersistence; +import ca.nrc.cadc.util.Log4jInit; +import java.security.Principal; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.easymock.EasyMock; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author jburke + */ +public class AddGroupMemberActionTest +{ + private final static Logger log = Logger.getLogger(AddGroupMemberActionTest.class); + + @BeforeClass + public static void setUpClass() + { + Log4jInit.setLevel("ca.nrc.cadc.ac", Level.INFO); + } + + @Test + public void testExceptions() + { + try + { + Group group = new Group("group", null); + Group member = new Group("member", null); + group.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.replay(groupPersistence); + + GroupLogInfo logInfo = EasyMock.createMock(GroupLogInfo.class); + + AddGroupMemberAction action = new AddGroupMemberAction(logInfo, "group", "member") + { + @Override + <T extends Principal> GroupPersistence<T> getGroupPersistence() + { + return groupPersistence; + }; + }; + + try + { + action.run(); + fail("duplicate group member should throw GroupAlreadyExistsException"); + } + catch (GroupAlreadyExistsException ignore) {} + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + fail("unexpected error: " + t.getMessage()); + } + } + + @Test + public void testRun() throws Exception + { + try + { + Group group = new Group("group", null); + Group member = new Group("member", null); + 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); + + AddGroupMemberAction action = new AddGroupMemberAction(logInfo, "group", "member") + { + @Override + <T extends Principal> GroupPersistence<T> getGroupPersistence() + { + return groupPersistence; + }; + }; + + action.run(); + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + fail("unexpected error: " + t.getMessage()); + } + } + +} diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/AddUserMemberActionTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/AddUserMemberActionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6488fd768583dd7d06841a16547158a6c8b32b6a --- /dev/null +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/AddUserMemberActionTest.java @@ -0,0 +1,205 @@ +/* + ************************************************************************ + ******************* 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.ac.Group; +import ca.nrc.cadc.ac.GroupAlreadyExistsException; +import ca.nrc.cadc.ac.MemberAlreadyExistsException; +import ca.nrc.cadc.ac.User; +import ca.nrc.cadc.ac.server.GroupPersistence; +import ca.nrc.cadc.ac.server.UserPersistence; +import ca.nrc.cadc.auth.AuthenticationUtil; +import ca.nrc.cadc.util.Log4jInit; +import java.security.Principal; +import javax.security.auth.x500.X500Principal; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.easymock.EasyMock; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author jburke + */ +public class AddUserMemberActionTest +{ + private final static Logger log = Logger.getLogger(AddUserMemberActionTest.class); + + @BeforeClass + public static void setUpClass() + { + Log4jInit.setLevel("ca.nrc.cadc.ac", Level.INFO); + } + + @Test + @SuppressWarnings("unchecked") + 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) + { + @Override + <T extends Principal> GroupPersistence<T> getGroupPersistence() + { + return groupPersistence; + }; + + @Override + <T extends Principal> UserPersistence<T> getUserPersistence() + { + return userPersistence; + }; + }; + + try + { + action.run(); + fail("duplicate group member should throw MemberAlreadyExistsException"); + } + catch (MemberAlreadyExistsException ignore) {} + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + fail("unexpected error: " + t.getMessage()); + } + } + + @Test + @SuppressWarnings("unchecked") + public void testRun() throws Exception + { + 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 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) + { + @Override + <T extends Principal> GroupPersistence<T> getGroupPersistence() + { + return groupPersistence; + }; + + @Override + <T extends Principal> UserPersistence<T> getUserPersistence() + { + return userPersistence; + }; + }; + + action.run(); + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + fail("unexpected error: " + t.getMessage()); + } + } + +} diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/DeleteGroupActionTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/DeleteGroupActionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4562671a6951e209e759a96993499782ede5a9e8 --- /dev/null +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/DeleteGroupActionTest.java @@ -0,0 +1,136 @@ +/* + ************************************************************************ + ******************* 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.ac.Group; +import ca.nrc.cadc.ac.MemberAlreadyExistsException; +import ca.nrc.cadc.ac.User; +import ca.nrc.cadc.ac.server.GroupPersistence; +import ca.nrc.cadc.ac.server.UserPersistence; +import ca.nrc.cadc.auth.AuthenticationUtil; +import ca.nrc.cadc.util.Log4jInit; +import java.security.Principal; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.easymock.EasyMock; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author jburke + */ +public class DeleteGroupActionTest +{ + private final static Logger log = Logger.getLogger(DeleteGroupActionTest.class); + + @BeforeClass + public static void setUpClass() + { + Log4jInit.setLevel("ca.nrc.cadc.ac", Level.INFO); + } + + @Test + 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") + { + @Override + <T extends Principal> GroupPersistence<T> getGroupPersistence() + { + return groupPersistence; + }; + }; + + action.run(); + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + fail("unexpected error: " + t.getMessage()); + } + } + +} diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/GetGroupNamesActionTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/GetGroupNamesActionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0cb59383950ce877c3c5c88a4ee1da506adecce7 --- /dev/null +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/GetGroupNamesActionTest.java @@ -0,0 +1,159 @@ +/* + ************************************************************************ + ******************* 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.ac.server.GroupPersistence; +import ca.nrc.cadc.util.Log4jInit; +import ca.nrc.cadc.uws.server.SyncOutput; + +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.easymock.EasyMock; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +import javax.servlet.http.HttpServletResponse; +import java.io.PrintWriter; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Collection; + +import static org.junit.Assert.fail; + +/** + * + * @author jburke + */ +public class GetGroupNamesActionTest +{ + private final static Logger log = Logger.getLogger(GetGroupNamesActionTest.class); + + @BeforeClass + public static void setUpClass() + { + Log4jInit.setLevel("ca.nrc.cadc.ac", Level.INFO); + } + + @Test + @Ignore + public void testRun() throws Exception + { + try + { + Collection<String> groupNames = new ArrayList<String>(); + groupNames.add("foo"); + groupNames.add("bar"); + + final GroupPersistence mockPersistence = EasyMock.createMock(GroupPersistence.class); + EasyMock.expect(mockPersistence.getGroupNames()).andReturn(groupNames).once(); + + final PrintWriter mockWriter = EasyMock.createMock(PrintWriter.class); + mockWriter.write("foo", 0, 3); + EasyMock.expectLastCall(); + mockWriter.write(44); + EasyMock.expectLastCall(); + mockWriter.write("bar", 0, 3); + EasyMock.expectLastCall(); + mockWriter.write("\n"); + EasyMock.expectLastCall(); + + final SyncOutput mockSyncOutput = + EasyMock.createMock(SyncOutput.class); + + mockSyncOutput.setHeader("Content-Type", "text/csv"); + + final HttpServletResponse mockResponse = EasyMock.createMock(HttpServletResponse.class); + mockResponse.setContentType("text/csv"); + EasyMock.expectLastCall(); + EasyMock.expect(mockResponse.getWriter()).andReturn(mockWriter).once(); + + GroupLogInfo mockLog = EasyMock.createMock(GroupLogInfo.class); + + EasyMock.replay(mockPersistence, mockWriter, mockResponse, mockLog); + + GetGroupNamesAction action = new GetGroupNamesAction(mockLog) + { + @Override + <T extends Principal> GroupPersistence<T> getGroupPersistence() + { + return mockPersistence; + }; + }; + + action.run(); + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + fail("unexpected error: " + t.getMessage()); + } + } + +} diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/GroupActionFactoryTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/GroupActionFactoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f62d030cc6b0f9131a9681250664fbee8a97444c --- /dev/null +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/GroupActionFactoryTest.java @@ -0,0 +1,369 @@ +/** + ************************************************************************ + ******************* 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/>. + * + ************************************************************************ + */ + +package ca.nrc.cadc.ac.server.web; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.Test; + +import ca.nrc.cadc.util.Log4jInit; + +import java.net.URL; + +public class GroupActionFactoryTest +{ + private final static Logger log = Logger.getLogger(GroupActionFactoryTest.class); + + public GroupActionFactoryTest() + { + Log4jInit.setLevel("ca.nrc.cadc.ac", Level.INFO); + } + + @Test + public void testCreateAddGroupMemberAction() + { + try + { + 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); + EasyMock.verify(request); + Assert.assertTrue("Wrong action", action instanceof AddGroupMemberAction); + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + Assert.fail("unexpected error: " + t.getMessage()); + } + } + + @Test + public void testCreateAddUserMemberAction() + { + try + { + 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); + EasyMock.verify(request); + Assert.assertTrue("Wrong action", action instanceof AddUserMemberAction); + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + Assert.fail("unexpected error: " + t.getMessage()); + } + } + + @Test + public void testCreateCreateGroupAction() + { + try + { + 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); + EasyMock.verify(request); + Assert.assertTrue("Wrong action", action instanceof CreateGroupAction); + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + Assert.fail("unexpected error: " + t.getMessage()); + } + } + + @Test + public void testCreateDeleteGroupAction() + { + try + { + 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); + EasyMock.verify(request); + Assert.assertTrue("Wrong action", action instanceof DeleteGroupAction); + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + Assert.fail("unexpected error: " + t.getMessage()); + } + } + + @Test + public void testCreateGetGroupAction() + { + try + { + 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); + EasyMock.verify(request); + Assert.assertTrue("Wrong action", action instanceof GetGroupAction); + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + Assert.fail("unexpected error: " + t.getMessage()); + } + } + + @Test + public void testCreateGetGroupNamesAction() + { + try + { + 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); + EasyMock.verify(request); + Assert.assertTrue("Wrong action", action instanceof GetGroupNamesAction); + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + Assert.fail("unexpected error: " + t.getMessage()); + } + } + + @Test + public void testCreateModifyGroupAction() + { + try + { + StringBuffer sb = new StringBuffer(); + sb.append("http://localhost:80/ac/groups/foo"); + + 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); + EasyMock.verify(request); + Assert.assertTrue("Wrong action", action instanceof ModifyGroupAction); + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + Assert.fail("unexpected error: " + t.getMessage()); + } + } + + @Test + public void testCreateRemoveGroupMemberAction() + { + try + { + 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); + EasyMock.verify(request); + Assert.assertTrue("Wrong action", action instanceof RemoveGroupMemberAction); + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + Assert.fail("unexpected error: " + t.getMessage()); + } + } + + @Test + public void testCreateRemoveUserMemberAction() + { + try + { + 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); + EasyMock.verify(request); + Assert.assertTrue("Wrong action", action instanceof RemoveUserMemberAction); + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + Assert.fail("unexpected error: " + t.getMessage()); + } + } + + @Test + public void testBadRequests() + { + try + { + TestRequest[] testRequests = + { + new TestRequest("", "POST"), + new TestRequest("", "DELETE"), + new TestRequest("", "HEAD"), + new TestRequest("groupName/groupMembers", "GET"), + new TestRequest("groupName/groupMembers", "POST"), + new TestRequest("groupName/groupMembers", "PUT"), + new TestRequest("groupName/groupMembers", "DELETE"), + new TestRequest("groupName/groupMembers", "HEAD"), + new TestRequest("groupName/misspelled/id", "GET"), + new TestRequest("groupName/groupMembers/groupMemberName", "GET"), + new TestRequest("groupName/groupMembers/groupMemberName", "POST"), + new TestRequest("groupName/groupMembers/groupMemberName", "HEAD"), + new TestRequest("groupName/userMembers/userMemberName", "GET"), + new TestRequest("groupName/userMembers/userMemberName", "POST"), + new TestRequest("groupName/userMembers/userMemberName", "HEAD"), + new TestRequest("groupName/groupMembers/groupMemberName/tooManySegments", "GET"), + new TestRequest("groupName/groupMembers/groupMemberName/tooManySegments", "POST"), + new TestRequest("groupName/groupMembers/groupMemberName/tooManySegments", "PUT"), + new TestRequest("groupName/groupMembers/groupMemberName/tooManySegments", "HEAD"), + new TestRequest("groupName/groupMembers/groupMemberName/tooManySegments", "DELETE"), + }; + + for (TestRequest testRequest : testRequests) + { + + 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 + { + GroupsActionFactory.getGroupsAction(request, null); + Assert.fail("Should have been a bad request: " + testRequest.method + " on " + testRequest.path); + } + catch (IllegalArgumentException e) + { + // expected + } + EasyMock.verify(request); + } + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + Assert.fail("unexpected error: " + t.getMessage()); + } + } + + private class TestRequest + { + public String path; + public String method; + public String paramName; + public String paramValue; + + public TestRequest(String path, String method) + { + this(path, method, null, null); + } + public TestRequest(String path, String method, 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 + + ((paramName == null) ? "" : "?" + paramName + "=" + paramValue); + } + + } + +} diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/GroupsActionTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/GroupsActionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..08b28e9725675f4d955688e194198862144b9f42 --- /dev/null +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/GroupsActionTest.java @@ -0,0 +1,264 @@ +/* + ************************************************************************ + ******************* 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.ac.GroupAlreadyExistsException; +import ca.nrc.cadc.ac.GroupNotFoundException; +import ca.nrc.cadc.ac.MemberAlreadyExistsException; +import ca.nrc.cadc.ac.MemberNotFoundException; +import ca.nrc.cadc.ac.UserNotFoundException; +import ca.nrc.cadc.net.TransientException; +import ca.nrc.cadc.util.Log4jInit; + +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.security.AccessControlException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.easymock.EasyMock; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author jburke + */ +public class GroupsActionTest +{ + private final static Logger log = Logger.getLogger(GroupsActionTest.class); + + @BeforeClass + public static void setUpClass() + { + Log4jInit.setLevel("ca.nrc.cadc.ac", Level.INFO); + } + + @Test + public void testDoActionAccessControlException() throws Exception + { + String message = "Permission Denied"; + int responseCode = 403; + Exception e = new AccessControlException(""); + testDoAction(message, responseCode, e); + } + + @Test + public void testDoActionIllegalArgumentException() throws Exception + { + String message = "message"; + int responseCode = 400; + Exception e = new IllegalArgumentException("message"); + testDoAction(message, responseCode, e); + } + + @Test + public void testDoActionMemberNotFoundException() throws Exception + { + String message = "Member not found: foo"; + int responseCode = 404; + Exception e = new MemberNotFoundException("foo"); + testDoAction(message, responseCode, e); + } + + @Test + public void testDoActionGroupNotFoundException() throws Exception + { + String message = "Group not found: foo"; + int responseCode = 404; + Exception e = new GroupNotFoundException("foo"); + testDoAction(message, responseCode, e); + } + + @Test + public void testDoActionUserNotFoundException() throws Exception + { + String message = "User not found: foo"; + int responseCode = 404; + Exception e = new UserNotFoundException("foo"); + testDoAction(message, responseCode, e); + } + + @Test + public void testDoActionMemberAlreadyExistsException() throws Exception + { + String message = "Member already exists: foo"; + int responseCode = 409; + Exception e = new MemberAlreadyExistsException("foo"); + testDoAction(message, responseCode, e); + } + + @Test + public void testDoActionGroupAlreadyExistsException() throws Exception + { + String message = "Group already exists: foo"; + int responseCode = 409; + Exception e = new GroupAlreadyExistsException("foo"); + testDoAction(message, responseCode, e); + } + + @Test + public void testDoActionUnsupportedOperationException() throws Exception + { + String message = "Not yet implemented."; + int responseCode = 501; + Exception e = new UnsupportedOperationException(); + testDoAction(message, responseCode, e); + } + + @Test + public void testDoActionTransientException() throws Exception + { + try + { + HttpServletResponse response = EasyMock.createMock(HttpServletResponse.class); + EasyMock.expect(response.isCommitted()).andReturn(Boolean.FALSE); + response.setContentType("text/plain"); + EasyMock.expectLastCall().once(); + EasyMock.expect(response.getWriter()).andReturn(new PrintWriter(new StringWriter())); + EasyMock.expectLastCall().once(); + response.setStatus(503); + 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); + action.setException(new TransientException("foo")); + action.doAction(null, response); + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + fail("unexpected error: " + t.getMessage()); + } + } + + private void testDoAction(String message, int responseCode, Exception e) + throws Exception + { + try + { + HttpServletResponse response = EasyMock.createMock(HttpServletResponse.class); + EasyMock.expect(response.isCommitted()).andReturn(Boolean.FALSE); + response.setContentType("text/plain"); + EasyMock.expectLastCall().once(); + EasyMock.expect(response.getWriter()).andReturn(new PrintWriter(new StringWriter())); + EasyMock.expectLastCall().once(); + response.setStatus(responseCode); + 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); + action.setException(e); + action.doAction(null, response); + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + fail("unexpected error: " + t.getMessage()); + } + } + + public class GroupsActionImpl extends GroupsAction + { + Exception exception; + + public GroupsActionImpl(GroupLogInfo logInfo) + { + super(logInfo); + } + + public Object run() throws Exception + { + throw exception; + } + + public void setException(Exception e) + { + this.exception = e; + } + } + +} diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/RemoveGroupMemberActionTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/RemoveGroupMemberActionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..7ccc5abb9753fd6ad5f1336e1ddfd4b46d8c1638 --- /dev/null +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/RemoveGroupMemberActionTest.java @@ -0,0 +1,176 @@ +/* + ************************************************************************ + ******************* 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.ac.Group; +import ca.nrc.cadc.ac.GroupAlreadyExistsException; +import ca.nrc.cadc.ac.GroupNotFoundException; +import ca.nrc.cadc.ac.server.GroupPersistence; +import ca.nrc.cadc.util.Log4jInit; +import java.security.Principal; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.easymock.EasyMock; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author jburke + */ +public class RemoveGroupMemberActionTest +{ + private final static Logger log = Logger.getLogger(RemoveGroupMemberActionTest.class); + + @BeforeClass + public static void setUpClass() + { + Log4jInit.setLevel("ca.nrc.cadc.ac", Level.INFO); + } + + @Test + public void testExceptions() + { + try + { + 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") + { + @Override + <T extends Principal> GroupPersistence<T> getGroupPersistence() + { + return groupPersistence; + }; + }; + + try + { + action.run(); + fail("unknown group member should throw GroupNotFoundException"); + } + catch (GroupNotFoundException ignore) {} + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + fail("unexpected error: " + t.getMessage()); + } + } + + @Test + public void testRun() throws Exception + { + try + { + 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") + { + @Override + <T extends Principal> GroupPersistence<T> getGroupPersistence() + { + return groupPersistence; + }; + }; + + action.run(); + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + fail("unexpected error: " + t.getMessage()); + } + } +} diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/RemoveUserMemberActionTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/RemoveUserMemberActionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..fea4de56d5d4ff31e3f08e473eeb5d8f8111fc12 --- /dev/null +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/RemoveUserMemberActionTest.java @@ -0,0 +1,206 @@ +/* + ************************************************************************ + ******************* 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.ac.Group; +import ca.nrc.cadc.ac.MemberAlreadyExistsException; +import ca.nrc.cadc.ac.MemberNotFoundException; +import ca.nrc.cadc.ac.User; +import ca.nrc.cadc.ac.server.GroupPersistence; +import ca.nrc.cadc.ac.server.UserPersistence; +import ca.nrc.cadc.auth.AuthenticationUtil; +import ca.nrc.cadc.util.Log4jInit; +import java.security.Principal; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.easymock.EasyMock; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author jburke + */ +public class RemoveUserMemberActionTest +{ + private final static Logger log = Logger.getLogger(RemoveUserMemberActionTest.class); + + @BeforeClass + public static void setUpClass() + { + Log4jInit.setLevel("ca.nrc.cadc.ac", Level.INFO); + } + + @Test + @SuppressWarnings("unchecked") + 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) + { + @Override + <T extends Principal> GroupPersistence<T> getGroupPersistence() + { + return groupPersistence; + }; + + @Override + <T extends Principal> UserPersistence<T> getUserPersistence() + { + return userPersistence; + }; + }; + + try + { + action.run(); + fail("unknown group member should throw MemberNotFoundException"); + } + catch (MemberNotFoundException ignore) {} + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + fail("unexpected error: " + t.getMessage()); + } + } + + @Test + @SuppressWarnings("unchecked") + public void testRun() throws Exception + { + 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); + 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) + { + @Override + <T extends Principal> GroupPersistence<T> getGroupPersistence() + { + return groupPersistence; + }; + + @Override + <T extends Principal> UserPersistence<T> getUserPersistence() + { + return userPersistence; + }; + }; + + action.run(); + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + fail("unexpected error: " + t.getMessage()); + } + } + +} diff --git a/projects/cadcAccessControl/build.xml b/projects/cadcAccessControl/build.xml index 25762598f1a728a912d6fe99a1a6c27352a4e9cf..a3b964ed3878c53e9c2aec9a667ebce0cc72ca79 100644 --- a/projects/cadcAccessControl/build.xml +++ b/projects/cadcAccessControl/build.xml @@ -8,7 +8,7 @@ * 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 @@ -31,10 +31,10 @@ * 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 @@ -44,7 +44,7 @@ * 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 @@ -54,7 +54,7 @@ * 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 @@ -67,31 +67,37 @@ ************************************************************************ --> - <!DOCTYPE project> <project default="build" basedir="."> <property environment="env"/> <property file="local.build.properties" /> - + <!-- site-specific build properties or overrides of values in opencadc.properties --> <property file="${env.CADC_PREFIX}/etc/local.properties" /> - + <!-- site-specific targets, e.g. install, cannot duplicate those in opencadc.targets.xml --> <import file="${env.CADC_PREFIX}/etc/local.targets.xml" optional="true" /> <!-- default properties and targets --> <property file="${env.CADC_PREFIX}/etc/opencadc.properties" /> <import file="${env.CADC_PREFIX}/etc/opencadc.targets.xml"/> - + <!-- developer convenience: place for extra targets and properties --> <import file="extras.xml" optional="true" /> - <property name="project" value="cadcAccessControl" /> + <property name="project" value="cadcAccessControl" /> - <property name="cadcUtil" value="${lib}/cadcUtil.jar" /> + <property name="cadcUtil" value="${lib}/cadcUtil.jar" /> + <property name="cadcRegistryClient" value="${lib}/cadcRegistryClient.jar" /> + + <property name="jdom2" value="${ext.lib}/jdom2.jar" /> + <property name="javacsv" value="${ext.lib}/javacsv.jar" /> + <property name="log4j" value="${ext.lib}/log4j.jar" /> + <property name="unboundid" value="${ext.lib}/unboundid-ldapsdk-se.jar" /> - <property name="jars" value="${cadcUtil}:${ext.lib}/log4j.jar" /> - + + <property name="jars" value="${jdom2}:${log4j}:${javacsv}:${unboundid}:${cadcUtil}:${cadcRegistryClient}" /> + <target name="build" depends="compile"> <jar jarfile="${build}/lib/${project}.jar" basedir="${build}/class" @@ -101,23 +107,13 @@ </target> <!-- JAR files needed to run the test suite --> - <property name="testingJars" value="${build}/class:${jars}:${ext.lib}/junit.jar:${ext.lib}/xerces.jar:${ext.dev}/easymock.jar:${ext.dev}/cglib.jar:${ext.dev}/objenesis.jar:${ext.dev}/asm.jar" /> - - <target name="test" depends="compile-test"> - <echo message="Running test" /> - - <!-- Run the junit test suite --> - <echo message="Running test suite..." /> - <junit printsummary="yes" haltonfailure="yes" fork="yes"> - <classpath> - <pathelement path="${build}/class"/> - <pathelement path="${build}/test/class"/> - <pathelement path="${testingJars}"/> - </classpath> - <test name="ca.nrc.cadc.ac.UserTest" /> - <test name="ca.nrc.cadc.ac.GroupTest" /> - <formatter type="plain" usefile="false" /> - </junit> - </target> + <property name="xerces" value="${ext.lib}/xerces.jar" /> + <property name="asm" value="${ext.dev}/asm.jar" /> + <property name="cglib" value="${ext.dev}/cglib.jar" /> + <property name="easymock" value="${ext.dev}/easymock.jar" /> + <property name="junit" value="${ext.dev}/junit.jar" /> + <property name="objenesis" value="${ext.dev}/objenesis.jar" /> + <property name="testingJars" value="${build}/class:${jars}:${xerces}:${asm}:${cglib}:${easymock}:${junit}:${objenesis}" /> + </project> diff --git a/projects/cadcAccessControl/doc/AccessControl.png b/projects/cadcAccessControl/doc/AccessControl.png index 52bcea3a9f84a12817a27af6e2e3f7623e5b6b6f..14156bbd6833002185ee0487130121422e2ddd03 100644 Binary files a/projects/cadcAccessControl/doc/AccessControl.png and b/projects/cadcAccessControl/doc/AccessControl.png differ diff --git a/projects/cadcAccessControl/doc/auth.zargo b/projects/cadcAccessControl/doc/auth.zargo index 57aa2846f75e01db9d2e032775009c297468d492..8c12b4da6d7e9a1d815ec1a2a2bbb330da46723c 100644 Binary files a/projects/cadcAccessControl/doc/auth.zargo and b/projects/cadcAccessControl/doc/auth.zargo differ diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/AC.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/AC.java new file mode 100755 index 0000000000000000000000000000000000000000..cacb9a00c2efacc78ee92aa9d23ed35449fe38d9 --- /dev/null +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/AC.java @@ -0,0 +1,93 @@ +/* + ************************************************************************ + ******************* 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; + +/** + * Holder of commonly used consts in cadcAccessControl + */ +public class AC +{ + // Denotes a description given to a group + public static final String PROPERTY_GROUP_DESCRIPTION = "ivo://ivoa.net/gms#description"; + + // Denotes the DN of a group owner + public static final String PROPERTY_OWNER_DN = "ivo://ivoa.net/gms#owner_dn"; + + // Denotes the DN of a user + public static final String PROPERTY_USER_DN = "ivo://ivoa.net/gms#user_dn"; + + // Denotes a group readable by public + public static final String PROPERTY_PUBLIC = "ivo://ivoa.net/gms#public"; + + public static final String GMS_SERVICE_URI = "ivo://cadc.nrc.ca/canfargms"; + + // Group URI attribute once the group name is appended + public static final String GROUP_URI = "ivo://cadc.nrc.ca/gms#"; + +} diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/ActivatedGroup.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/ActivatedGroup.java new file mode 100644 index 0000000000000000000000000000000000000000..22e445ede8750b77db6dd5f0bc07db03420531db --- /dev/null +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/ActivatedGroup.java @@ -0,0 +1,85 @@ +/* + ************************************************************************ + ******************* 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; + + +public class ActivatedGroup extends Group +{ + public ActivatedGroup(Group group) + { + super(group.getID(), group.getOwner()); + this.description = group.description; + this.properties = group.getProperties(); + this.lastModified = group.lastModified; + this.getUserMembers().addAll(group.getUserMembers()); + this.getGroupMembers().addAll(group.getGroupMembers()); + this.getUserAdmins().addAll(group.getUserAdmins()); + this.getGroupAdmins().addAll(group.getGroupAdmins()); + } +} diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/Group.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/Group.java index e89798147a80a826b7c03c819ed51ac35f48748a..c8e8048ee08a45712e47a93380c8441dd42f650a 100644 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/Group.java +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/Group.java @@ -1,104 +1,136 @@ /* ************************************************************************ - **** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** + ******************* CANADIAN ASTRONOMY DATA CENTRE ******************* + ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** * - * (c) 2014. (c) 2014. - * National Research Council Conseil national de recherches - * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 - * All rights reserved Tous droits reserves + * (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 denie toute garantie - * expressed, implied, or statu- enoncee, implicite ou legale, - * tory, of any kind with respect de quelque nature que se soit, - * to the software, including concernant le logiciel, y com- - * without limitation any war- pris sans restriction toute - * ranty of merchantability or garantie de valeur marchande - * fitness for a particular pur- ou de pertinence pour un usage - * pose. NRC shall not be liable particulier. Le CNRC ne - * in any event for any damages, pourra en aucun cas etre tenu - * whether direct or indirect, responsable de tout dommage, - * special or general, consequen- direct ou indirect, particul- - * tial or incidental, arising ier ou general, accessoire ou - * from the use of the software. fortuit, resultant de l'utili- - * sation du logiciel. + * 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 $ * - * @author adriand - * - * @version $Revision: $ - * - * - **** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** ************************************************************************ */ - package ca.nrc.cadc.ac; import java.security.Principal; +import java.util.Date; import java.util.HashSet; import java.util.Set; public class Group { private String groupID; - + private User<? extends Principal> owner; - + // group's properties protected Set<GroupProperty> properties = new HashSet<GroupProperty>(); // group's user members - private Set<User<? extends Principal>> userMembers = - new HashSet<User<? extends Principal>>(); + private Set<User<? extends Principal>> userMembers = new HashSet<User<? extends Principal>>(); + // group's group members private Set<Group> groupMembers = new HashSet<Group>(); - + + // group's user admins + private Set<User<? extends Principal>> userAdmins = new HashSet<User<? extends Principal>>(); + + // group's group admins + private Set<Group> groupAdmins = new HashSet<Group>(); + public String description; + public Date lastModified; - // Access Control properties - /** - * group that can read details of this group - * Note: this class does not enforce any access control rules - */ - public Group groupRead; - /** - * group that can read and write details of this group - * Note: this class does not enforce any access control rules - */ - public Group groupWrite; /** - * flag that show whether the details of this group are publicly readable - * Note: this class does not enforce any access control rules + * Ctor. + * + * @param groupID Unique ID for the group. Must be a valid URI fragment + * component, so it's restricted to alphanumeric + * and "-", ".","_","~" characters. */ - public boolean publicRead = false; + public Group(String groupID) + { + this(groupID, null); + } /** * Ctor. * - * @param groupID - * Unique ID for the group. Must be a valid URI fragment component, - * so it's restricted to alphanumeric and "-", ".","_","~" characters. - * @param owner - * Owner/Creator of the group. + * @param groupID Unique ID for the group. Must be a valid URI fragment + * component, so it's restricted to alphanumeric + * and "-", ".","_","~" characters. + * @param owner Owner/Creator of the group. */ - public Group(final String groupID, - final User<? extends Principal> owner) + public Group(String groupID, User<? extends Principal> owner) { - if(groupID == null) + if (groupID == null) { throw new IllegalArgumentException("Null groupID"); } - - // check for invalid path characters in groupID - if(!groupID.matches("^[a-zA-Z0-9\\-\\.~_]*$")) - throw new IllegalArgumentException("Invalid group ID " + groupID - + ": may not contain space ( ), slash (/), escape (\\), or percent (%)"); - this.groupID = groupID; - if(owner == null) + if (!groupID.matches("^[a-zA-Z0-9\\-\\.~_]*$")) { - throw new IllegalArgumentException("Null owner"); + throw new IllegalArgumentException("Invalid group ID " + groupID + + ": may not contain space ( ), slash (/), escape (\\), or percent (%)"); } + + this.groupID = groupID; this.owner = owner; } @@ -147,7 +179,24 @@ public class Group { return groupMembers; } + + /** + * + * @return individual user admins of this group + */ + public Set<User<? extends Principal>> getUserAdmins() + { + return userAdmins; + } + /** + * + * @return group admins of this group + */ + public Set<Group> getGroupAdmins() + { + return groupAdmins; + } /* (non-Javadoc) * @see java.lang.Object#hashCode() @@ -155,7 +204,7 @@ public class Group @Override public int hashCode() { - return 31 + groupID.hashCode(); + return 31 + groupID.toLowerCase().hashCode(); } /* (non-Javadoc) @@ -177,17 +226,16 @@ public class Group return false; } Group other = (Group) obj; - if (!groupID.equals(other.groupID)) + if (!groupID.equalsIgnoreCase(other.groupID)) { return false; } return true; } - + @Override public String toString() { return getClass().getSimpleName() + "[" + groupID + "]"; } - } diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/GroupAlreadyExistsException.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/GroupAlreadyExistsException.java new file mode 100755 index 0000000000000000000000000000000000000000..7e3e096185d78d55b19b0730f4bec3be27feb56c --- /dev/null +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/GroupAlreadyExistsException.java @@ -0,0 +1,81 @@ +/* + ************************************************************************ + ******************* 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; + +public class GroupAlreadyExistsException extends Exception +{ + /** + * Thrown when there is a group conflict. + * + */ + public GroupAlreadyExistsException(String message) + { + super(message); + } +} diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/GroupNotFoundException.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/GroupNotFoundException.java new file mode 100755 index 0000000000000000000000000000000000000000..a03e53649d4cbda5052a8a893ef76593cc917af5 --- /dev/null +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/GroupNotFoundException.java @@ -0,0 +1,81 @@ +/* + ************************************************************************ + ******************* 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; + +public class GroupNotFoundException extends Exception +{ + /** + * Thrown when a group cannot be found. + * + */ + public GroupNotFoundException(String message) + { + super(message); + } +} diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/GroupProperty.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/GroupProperty.java index 5ddfa8016e0e75077bf34bac7b7b02b32291d4bc..2c4c89aad4ddf08e1e14fcd59f39c3002f20f1ae 100644 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/GroupProperty.java +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/GroupProperty.java @@ -1,71 +1,71 @@ /* -************************************************************************ -******************* CANADIAN ASTRONOMY DATA CENTRE ******************* -************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -* -* (c) 2009. (c) 2009. -* 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/>. -* -* -************************************************************************ -*/ - + ************************************************************************ + ******************* 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; /** @@ -73,7 +73,33 @@ package ca.nrc.cadc.ac; * */ public class GroupProperty -{ +{ + /** + * Name of the GroupProperty element. + */ + public static final String NAME = "property"; + + /** + * Name of the property key attribute in the GroupProperty element. + */ + public static final String KEY_ATTRIBUTE = "key"; + + /** + * Name of the property type attribute in the GroupProperty element. + */ + public static final String TYPE_ATTRIBUTE = "type"; + + /** + * Name of the property readOnly attribute in the GroupProperty element. + */ + public static final String READONLY_ATTRIBUTE = "readOnly"; + + /** + * Allowed types. + */ + public static final String STRING_TYPE = "String"; + public static final String INTEGER_TYPE = "Integer"; + // The property identifier private String key; @@ -82,21 +108,21 @@ public class GroupProperty // true if the property cannot be modified. private boolean readOnly; - /** * GroupProperty constructor. * * @param key The property key. Cannot be null. * @param value The property value. + * @param readOnly */ public GroupProperty(String key, Object value, boolean readOnly) { - if(key == null) + if (key == null) { throw new IllegalArgumentException("Null key"); } - if(value == null) + if (value == null) { throw new IllegalArgumentException("Null value"); } @@ -128,9 +154,7 @@ public class GroupProperty { return readOnly; } - - /* (non-Javadoc) * @see java.lang.Object#hashCode() */ @@ -139,7 +163,7 @@ public class GroupProperty { final int prime = 31; int result = 1; - result = prime * result + ((key == null) ? 0 : key.hashCode()); + result = prime * result + (key == null ? 0 : key.hashCode()); return result; } @@ -164,11 +188,10 @@ public class GroupProperty GroupProperty other = (GroupProperty) obj; return key.equals(other.key); } - + @Override public String toString() { return getClass().getSimpleName() + "[" + key + ": " + value + "]"; } - } diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/GroupReader.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/GroupReader.java new file mode 100755 index 0000000000000000000000000000000000000000..70ef1830f10432669f5b0bbd27be53286fa8d2b4 --- /dev/null +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/GroupReader.java @@ -0,0 +1,302 @@ +/* + ************************************************************************ + ******************* 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; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; +import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; +import java.security.Principal; +import java.text.DateFormat; +import java.text.ParseException; +import java.util.List; + +import org.jdom2.Document; +import org.jdom2.Element; +import org.jdom2.JDOMException; + +import ca.nrc.cadc.date.DateUtil; +import ca.nrc.cadc.xml.XmlUtil; + +public class GroupReader +{ + + /** + * Construct a Group from an XML String source. + * + * @param xml String of the XML. + * @return Group Group. + * @throws ca.nrc.cadc.ac.ReaderException + * @throws java.io.IOException + * @throws java.net.URISyntaxException + */ + public static Group read(String xml) + throws ReaderException, IOException, URISyntaxException + { + if (xml == null) + { + throw new IllegalArgumentException("XML must not be null"); + } + return read(new StringReader(xml)); + } + + /** + * Construct a Group from a InputStream. + * + * @param in InputStream. + * @return Group Group. + * @throws ca.nrc.cadc.ac.ReaderException + * @throws java.io.IOException + * @throws java.net.URISyntaxException + */ + public static Group read(InputStream in) + throws ReaderException, IOException + { + if (in == null) + { + throw new IOException("stream closed"); + } + InputStreamReader reader; + try + { + reader = new InputStreamReader(in, "UTF-8"); + } + catch (UnsupportedEncodingException e) + { + throw new RuntimeException("UTF-8 encoding not supported"); + } + return read(reader); + } + + /** + * Construct a Group from a Reader. + * + * @param reader Reader. + * @return Group Group. + * @throws ca.nrc.cadc.ac.ReaderException + * @throws java.io.IOException + * @throws java.net.URISyntaxException + */ + public static Group read(Reader reader) + throws ReaderException, IOException + { + if (reader == null) + { + throw new IllegalArgumentException("reader must not be null"); + } + + Document document; + try + { + document = XmlUtil.buildDocument(reader); + } + catch (JDOMException jde) + { + String error = "XML failed validation: " + jde.getMessage(); + throw new ReaderException(error, jde); + } + + Element root = document.getRootElement(); + + String groupElemName = root.getName(); + + if (!groupElemName.equalsIgnoreCase("group")) + { + String error = "Expected group element, found " + groupElemName; + throw new ReaderException(error); + } + + return parseGroup(root); + } + + protected static Group parseGroup(Element groupElement) + throws ReaderException + { + String uri = groupElement.getAttributeValue("uri"); + if (uri == null) + { + String error = "group missing required uri attribute"; + throw new ReaderException(error); + } + + // 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; + Element ownerElement = groupElement.getChild("owner"); + if (ownerElement != null) + { + // Owner user + Element userElement = ownerElement.getChild("user"); + if (userElement == null) + { + String error = "owner missing required user element"; + throw new ReaderException(error); + } + user = UserReader.parseUser(userElement); + } + + Group group = new Group(groupID, user); + + // description + Element descriptionElement = groupElement.getChild("description"); + if (descriptionElement != null) + { + group.description = descriptionElement.getText(); + } + + // lastModified + Element lastModifiedElement = groupElement.getChild("lastModified"); + if (lastModifiedElement != null) + { + try + { + DateFormat df = DateUtil.getDateFormat(DateUtil.IVOA_DATE_FORMAT, DateUtil.UTC); + group.lastModified = df.parse(lastModifiedElement.getText()); + } + catch (ParseException e) + { + String error = "Unable to parse group lastModified because " + e.getMessage(); + + throw new ReaderException(error); + } + + } + + // properties + Element propertiesElement = groupElement.getChild("properties"); + if (propertiesElement != null) + { + List<Element> propertyElements = propertiesElement.getChildren("property"); + for (Element propertyElement : propertyElements) + { + group.getProperties().add(GroupPropertyReader.read(propertyElement)); + } + + } + + // groupMembers + Element groupMembersElement = groupElement.getChild("groupMembers"); + if (groupMembersElement != null) + { + List<Element> groupElements = groupMembersElement.getChildren("group"); + for (Element groupMember : groupElements) + { + group.getGroupMembers().add(parseGroup(groupMember)); + } + + } + + // userMembers + Element userMembersElement = groupElement.getChild("userMembers"); + if (userMembersElement != null) + { + List<Element> userElements = userMembersElement.getChildren("user"); + for (Element userMember : userElements) + { + group.getUserMembers().add(UserReader.parseUser(userMember)); + } + } + + // groupAdmins + Element groupAdminsElement = groupElement.getChild("groupAdmins"); + if (groupAdminsElement != null) + { + List<Element> groupElements = groupAdminsElement.getChildren("group"); + for (Element groupMember : groupElements) + { + group.getGroupAdmins().add(parseGroup(groupMember)); + } + + } + + // userAdmins + Element userAdminsElement = groupElement.getChild("userAdmins"); + if (userAdminsElement != null) + { + List<Element> userElements = userAdminsElement.getChildren("user"); + for (Element userMember : userElements) + { + group.getUserAdmins().add(UserReader.parseUser(userMember)); + } + } + + return group; + } +} diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/GroupWriter.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/GroupWriter.java new file mode 100755 index 0000000000000000000000000000000000000000..93fcd13c61f9a5492beb3468049997cbeb908b25 --- /dev/null +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/GroupWriter.java @@ -0,0 +1,268 @@ +/* + ************************************************************************ + ******************* 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; + +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; + +import org.jdom2.Attribute; +import org.jdom2.Document; +import org.jdom2.Element; +import org.jdom2.output.Format; +import org.jdom2.output.XMLOutputter; + +import ca.nrc.cadc.date.DateUtil; +import ca.nrc.cadc.util.StringBuilderWriter; + +public class GroupWriter +{ + /** + * Write a Group to a StringBuilder. + * @param group + * @param builder + * @throws java.io.IOException + * @throws ca.nrc.cadc.ac.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 ca.nrc.cadc.ac.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 ca.nrc.cadc.ac.WriterException + */ + public static void write(Group group, Writer writer) + throws IOException, WriterException + { + if (group == null) + { + throw new WriterException("null group"); + } + + write(getGroupElement(group), writer); + } + + /** + * + * @param group + * @return + * @throws ca.nrc.cadc.ac.WriterException + */ + public static Element getGroupElement(Group group) + throws WriterException + { + return getGroupElement(group, true); + } + + public static Element getGroupElement(Group group, boolean deepCopy) + throws WriterException + { + // Create the root group element. + Element groupElement = new Element("group"); + String groupURI = AC.GROUP_URI + group.getID(); + groupElement.setAttribute(new Attribute("uri", groupURI)); + + // Group owner + if (group.getOwner() != null) + { + Element ownerElement = new Element("owner"); + Element userElement = UserWriter.getUserElement(group.getOwner()); + ownerElement.addContent(userElement); + groupElement.addContent(ownerElement); + } + + if (deepCopy) + { + // Group description + if (group.description != null) + { + Element descriptionElement = new Element("description"); + descriptionElement.setText(group.description); + groupElement.addContent(descriptionElement); + } + + // lastModified + if (group.lastModified != null) + { + Element lastModifiedElement = new Element("lastModified"); + DateFormat df = DateUtil.getDateFormat(DateUtil.IVOA_DATE_FORMAT, DateUtil.UTC); + lastModifiedElement.setText(df.format(group.lastModified)); + groupElement.addContent(lastModifiedElement); + } + + // Group properties + if (!group.getProperties().isEmpty()) + { + Element propertiesElement = new Element("properties"); + for (GroupProperty property : group.getProperties()) + { + propertiesElement.addContent(GroupPropertyWriter.write(property)); + } + groupElement.addContent(propertiesElement); + } + + // Group groupMembers. + if ((group.getGroupMembers() != null) && (!group.getGroupMembers().isEmpty())) + { + Element groupMembersElement = new Element("groupMembers"); + for (Group groupMember : group.getGroupMembers()) + { + groupMembersElement.addContent(getGroupElement(groupMember, false)); + } + groupElement.addContent(groupMembersElement); + } + + // Group userMembers + if ((group.getUserMembers() != null) && (!group.getUserMembers().isEmpty())) + { + Element userMembersElement = new Element("userMembers"); + for (User<? extends Principal> userMember : group.getUserMembers()) + { + userMembersElement.addContent(UserWriter.getUserElement(userMember)); + } + groupElement.addContent(userMembersElement); + } + + // Group groupAdmins. + if ((group.getGroupAdmins() != null) && (!group.getGroupAdmins().isEmpty())) + { + Element groupAdminsElement = new Element("groupAdmins"); + for (Group groupMember : group.getGroupAdmins()) + { + groupAdminsElement.addContent(getGroupElement(groupMember, false)); + } + groupElement.addContent(groupAdminsElement); + } + + // Group userAdmins + if ((group.getUserAdmins() != null) && (!group.getUserAdmins().isEmpty())) + { + Element userAdminsElement = new Element("userAdmins"); + for (User<? extends Principal> userMember : group.getUserAdmins()) + { + userAdminsElement.addContent(UserWriter.getUserElement(userMember)); + } + groupElement.addContent(userAdminsElement); + } + } + + return groupElement; + } + + /** + * Write to root Element to a writer. + * + * @param root Root Element to write. + * @param writer Writer to write to. + * @throws IOException if the writer fails to write. + */ + private static void write(Element root, Writer writer) + throws IOException + { + XMLOutputter outputter = new XMLOutputter(); + outputter.setFormat(Format.getPrettyFormat()); + outputter.output(new Document(root), writer); + } + +} diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/GroupsReader.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/GroupsReader.java new file mode 100755 index 0000000000000000000000000000000000000000..656bdeccb031fb47872caa553a41ee7808909845 --- /dev/null +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/GroupsReader.java @@ -0,0 +1,188 @@ +/* + ************************************************************************ + ******************* 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; + +import ca.nrc.cadc.xml.XmlUtil; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; +import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.List; +import org.jdom2.Document; +import org.jdom2.Element; +import org.jdom2.JDOMException; + +public class GroupsReader +{ + /** + * Construct a list of Group's from an XML String source. + * + * @param xml String of the XML. + * @return Groups List of Group. + * @throws ca.nrc.cadc.ac.ReaderException + * @throws java.io.IOException + * @throws java.net.URISyntaxException + */ + public static List<Group> read(String xml) + throws ReaderException, IOException, URISyntaxException + { + if (xml == null) + { + throw new IllegalArgumentException("XML must not be null"); + } + return read(new StringReader(xml)); + } + + /** + * Construct a list of Group's from a InputStream. + * + * @param in InputStream. + * @return Groups List of Group. + * @throws ca.nrc.cadc.ac.ReaderException + * @throws java.io.IOException + * @throws java.net.URISyntaxException + */ + public static List<Group> read(InputStream in) + throws ReaderException, IOException, URISyntaxException + { + if (in == null) + { + throw new IOException("stream closed"); + } + InputStreamReader reader; + try + { + reader = new InputStreamReader(in, "UTF-8"); + } + catch (UnsupportedEncodingException e) + { + throw new RuntimeException("UTF-8 encoding not supported"); + } + return read(reader); + } + + /** + * Construct a List of Group's from a Reader. + * + * @param reader Reader. + * @return Groups List of Group. + * @throws ca.nrc.cadc.ac.ReaderException + * @throws java.io.IOException + * @throws java.net.URISyntaxException + */ + public static List<Group> read(Reader reader) + throws ReaderException, IOException, URISyntaxException + { + if (reader == null) + { + throw new IllegalArgumentException("reader must not be null"); + } + + Document document; + try + { + document = XmlUtil.buildDocument(reader); + } + catch (JDOMException jde) + { + String error = "XML failed validation: " + jde.getMessage(); + throw new ReaderException(error, jde); + } + + Element root = document.getRootElement(); + + String groupElemName = root.getName(); + + if (!groupElemName.equalsIgnoreCase("groups")) + { + String error = "Expected groups element, found " + groupElemName; + throw new ReaderException(error); + } + + return parseGroups(root); + } + + protected static List<Group> parseGroups(Element groupsElement) + throws URISyntaxException, ReaderException + { + List<Group> groups = new ArrayList<Group>(); + + List<Element> groupElements = groupsElement.getChildren("group"); + for (Element groupElement : groupElements) + { + groups.add(GroupReader.parseGroup(groupElement)); + } + + return groups; + } +} diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/GroupsWriter.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/GroupsWriter.java new file mode 100755 index 0000000000000000000000000000000000000000..0bdcf1f09ebeb40da3610f6a5ce69be834f86540 --- /dev/null +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/GroupsWriter.java @@ -0,0 +1,107 @@ +package ca.nrc.cadc.ac; + +import ca.nrc.cadc.util.StringBuilderWriter; +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.util.Collection; +import org.jdom2.Document; +import org.jdom2.Element; +import org.jdom2.output.Format; +import org.jdom2.output.XMLOutputter; + +public class GroupsWriter +{ + /** + * Write a List of Group's to a StringBuilder. + * @param groups List of Group's to write. + * @param builder + * @throws java.io.IOException + * @throws ca.nrc.cadc.ac.WriterException + */ + public static void write(Collection<Group> groups, StringBuilder builder) + throws IOException, WriterException + { + write(groups, new StringBuilderWriter(builder)); + } + + /** + * Write a List of Group's to an OutputStream. + * + * @param groups List of Group's to write. + * @param out OutputStream to write to. + * @throws IOException if the writer fails to write. + * @throws ca.nrc.cadc.ac.WriterException + */ + public static void write(Collection<Group> groups, 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(groups, new BufferedWriter(outWriter)); + } + + /** + * Write a List of Group's to a Writer. + * + * @param groups List of Group's to write. + * @param writer Writer to write to. + * @throws IOException if the writer fails to write. + * @throws ca.nrc.cadc.ac.WriterException + */ + public static void write(Collection<Group> groups, Writer writer) + throws IOException, WriterException + { + if (groups == null) + { + throw new WriterException("null groups"); + } + + write(getGroupsElement(groups), writer); + } + + /** + * + * @param groups List of Group's to write. + * @return Element of list of Group's. + * @throws ca.nrc.cadc.ac.WriterException + */ + public static Element getGroupsElement(Collection<Group> groups) + throws WriterException + { + Element groupsElement = new Element("groups"); + + for (Group group : groups) + { + groupsElement.addContent(GroupWriter.getGroupElement(group)); + } + + return groupsElement; + } + + /** + * Write to root Element to a writer. + * + * @param root Root Element to write. + * @param writer Writer to write to. + * @throws IOException if the writer fails to write. + */ + private static void write(Element root, Writer writer) + throws IOException + { + XMLOutputter outputter = new XMLOutputter(); + outputter.setFormat(Format.getPrettyFormat()); + outputter.output(new Document(root), writer); + } + +} \ No newline at end of file diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/MemberAlreadyExistsException.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/MemberAlreadyExistsException.java new file mode 100755 index 0000000000000000000000000000000000000000..1dea9e6e8d70a0aceeb361c0b8bb3dbd4be8c0bb --- /dev/null +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/MemberAlreadyExistsException.java @@ -0,0 +1,86 @@ +/* + ************************************************************************ + ******************* 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; + +/** + * Thrown when there is a member conflict. + * + */ +public class MemberAlreadyExistsException extends Exception +{ + public MemberAlreadyExistsException() + { + super(); + } + + public MemberAlreadyExistsException(String message) + { + super(message); + } +} diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/MemberNotFoundException.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/MemberNotFoundException.java new file mode 100755 index 0000000000000000000000000000000000000000..854bba82089b19a51ee6315d8f827a145851f4b4 --- /dev/null +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/MemberNotFoundException.java @@ -0,0 +1,86 @@ +/* + ************************************************************************ + ******************* 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; + +/** + * Thrown when a member could not be found. + * + */ +public class MemberNotFoundException extends Exception +{ + public MemberNotFoundException() + { + super(); + } + + public MemberNotFoundException(String message) + { + super(message); + } +} diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/PersonalDetails.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/PersonalDetails.java index a5ca2405f39ea169147858ebeba054c9963e08eb..60d9a81348e5eb65a9d6563c28703376d713af78 100644 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/PersonalDetails.java +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/PersonalDetails.java @@ -1,51 +1,124 @@ /* ************************************************************************ - **** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** + ******************* CANADIAN ASTRONOMY DATA CENTRE ******************* + ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** * - * (c) 2014. (c) 2014. - * National Research Council Conseil national de recherches - * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 - * All rights reserved Tous droits reserves + * (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 denie toute garantie - * expressed, implied, or statu- enoncee, implicite ou legale, - * tory, of any kind with respect de quelque nature que se soit, - * to the software, including concernant le logiciel, y com- - * without limitation any war- pris sans restriction toute - * ranty of merchantability or garantie de valeur marchande - * fitness for a particular pur- ou de pertinence pour un usage - * pose. NRC shall not be liable particulier. Le CNRC ne - * in any event for any damages, pourra en aucun cas etre tenu - * whether direct or indirect, responsable de tout dommage, - * special or general, consequen- direct ou indirect, particul- - * tial or incidental, arising ier ou general, accessoire ou - * from the use of the software. fortuit, resultant de l'utili- - * sation du logiciel. + * 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 $ * - * @author adriand - * - * @version $Revision: $ - * - * - **** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** ************************************************************************ */ - package ca.nrc.cadc.ac; public class PersonalDetails implements UserDetails { + /** + * Name of the PersonalDetails element. + */ + public static final String NAME = "personalDetails"; + + /** + * Name of the firstName element. + */ + public static final String FIRSTNAME = "firstName"; + + /** + * Name of the lastName element. + */ + public static final String LASTNAME = "lastName"; + + /** + * Name of the email element. + */ + public static final String EMAIL = "email"; + + /** + * Name of the email element. + */ + public static final String ADDRESS = "address"; + + /** + * Name of the email element. + */ + public static final String INSTITUTE = "institute"; + + /** + * Name of the email element. + */ + public static final String CITY = "city"; + + /** + * Name of the email element. + */ + public static final String COUNTRY = "country"; + private String firstName; private String lastName; - private String email; - private String address; - private String institute; - private String city; - private String country; + public String email; + public String address; + public String institute; + public String city; + public String country; - public PersonalDetails(String firstName, String lastName, String email, - String address, String institute, String city, String country) + public PersonalDetails(String firstName, String lastName) { if (firstName == null) { @@ -55,34 +128,9 @@ public class PersonalDetails implements UserDetails { throw new IllegalArgumentException("null lastName"); } - if (email == null) - { - throw new IllegalArgumentException("null email"); - } - if (address == null) - { - throw new IllegalArgumentException("null address"); - } - if (institute == null) - { - throw new IllegalArgumentException("null institute"); - } - if (city == null) - { - throw new IllegalArgumentException("null city"); - } - if (country == null) - { - throw new IllegalArgumentException("null country"); - } this.firstName = firstName; this.lastName = lastName; - this.email = email; - this.address = address; - this.institute = institute; - this.city = city; - this.country = country; } public String getFirstName() @@ -95,45 +143,15 @@ public class PersonalDetails implements UserDetails return lastName; } - public String getEmail() - { - return email; - } - - public String getAddress() - { - return address; - } - - public String getInstitute() - { - return institute; - } - - public String getCity() - { - return city; - } - - public String getCountry() - { - return country; - } - /* (non-Javadoc) * @see ca.nrc.cadc.auth.model.UserDetails#hashCode() */ @Override public int hashCode() { - final int prime = 31; + int prime = 31; int result = 1; - result = prime * result + address.hashCode(); - result = prime * result + city.hashCode(); - result = prime * result + country.hashCode(); - result = prime * result + email.hashCode(); result = prime * result + firstName.hashCode(); - result = prime * result + institute.hashCode(); result = prime * result + lastName.hashCode(); return result; } @@ -163,31 +181,7 @@ public class PersonalDetails implements UserDetails { return false; } - if (!lastName.equals(other.lastName)) - { - return false; - } - if (!email.equals(other.email)) - { - return false; - } - if (!institute.equals(other.institute)) - { - return false; - } - if (!address.equals(other.address)) - { - return false; - } - if (!city.equals(other.city)) - { - return false; - } - if (!country.equals(other.country)) - { - return false; - } - return true; + return lastName.equals(other.lastName); } /* (non-Javadoc) @@ -196,8 +190,9 @@ public class PersonalDetails implements UserDetails @Override public String toString() { - return getClass().getSimpleName() + "[" + firstName + ", " - + lastName + ", " + email + ", " + address + ", " - + institute + ", " + city + ", " + country + "]"; + return getClass().getSimpleName() + "[" + firstName + ", " + + lastName + ", " + email + ", " + address + ", " + + institute + ", " + city + ", " + country + "]"; } + } diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/PosixDetails.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/PosixDetails.java index 12d8dec1b4560d9d3b68a681dc36793d51c81247..af282d6d006b05657c490ea9944f31e2074adc0a 100644 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/PosixDetails.java +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/PosixDetails.java @@ -1,37 +1,71 @@ /* ************************************************************************ - **** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** + ******************* CANADIAN ASTRONOMY DATA CENTRE ******************* + ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** * - * (c) 2014. (c) 2014. - * National Research Council Conseil national de recherches - * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 - * All rights reserved Tous droits reserves + * (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 denie toute garantie - * expressed, implied, or statu- enoncee, implicite ou legale, - * tory, of any kind with respect de quelque nature que se soit, - * to the software, including concernant le logiciel, y com- - * without limitation any war- pris sans restriction toute - * ranty of merchantability or garantie de valeur marchande - * fitness for a particular pur- ou de pertinence pour un usage - * pose. NRC shall not be liable particulier. Le CNRC ne - * in any event for any damages, pourra en aucun cas etre tenu - * whether direct or indirect, responsable de tout dommage, - * special or general, consequen- direct ou indirect, particul- - * tial or incidental, arising ier ou general, accessoire ou - * from the use of the software. fortuit, resultant de l'utili- - * sation du logiciel. + * 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 $ * - * @author adriand - * - * @version $Revision: $ - * - * - **** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** ************************************************************************ */ - package ca.nrc.cadc.ac; /** @@ -39,10 +73,30 @@ package ca.nrc.cadc.ac; */ public class PosixDetails implements UserDetails { + /** + * Name of the PosixDetails element. + */ + public static final String NAME = "posixDetails"; + + /** + * Name of the uid element. + */ + public static final String UID = "uid"; + + /** + * Name of the gid element. + */ + public static final String GID = "gid"; + + /** + * Name of the homeDirectory element. + */ + public static final String HOME_DIRECTORY = "homeDirectory"; + private long uid; private long gid; private String homeDirectory; - + /** * user login shell */ @@ -50,12 +104,9 @@ public class PosixDetails implements UserDetails /** * - * @param uid - * posix uid - * @param gid - * posix gid - * @param homeDirectory - * home directory + * @param uid posix uid + * @param gid posix gid + * @param homeDirectory home directory */ public PosixDetails(long uid, long gid, String homeDirectory) { @@ -64,8 +115,9 @@ public class PosixDetails implements UserDetails if (homeDirectory == null) { throw new IllegalArgumentException( - "null home directory in POSIX details"); + "null home directory in POSIX details"); } + this.homeDirectory = homeDirectory; } @@ -101,11 +153,11 @@ public class PosixDetails implements UserDetails @Override public int hashCode() { - final int prime = 31; + int prime = 31; int result = 1; - result = prime * result + (int) (gid ^ (gid >>> 32)); + result = prime * result + (int) (gid ^ gid >>> 32); result = prime * result + homeDirectory.hashCode(); - result = prime * result + (int) (uid ^ (uid >>> 32)); + result = prime * result + (int) (uid ^ uid >>> 32); return result; } @@ -145,8 +197,8 @@ public class PosixDetails implements UserDetails @Override public String toString() { - return getClass().getSimpleName() + "[" + uid + ", " + gid + ", " - + homeDirectory + "]"; + return getClass().getSimpleName() + "[" + uid + ", " + + gid + ", " + homeDirectory + "]"; } } diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/ReaderException.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/ReaderException.java new file mode 100755 index 0000000000000000000000000000000000000000..397d1e62113993fc59cee4f79bbf9a62ea27a62e --- /dev/null +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/ReaderException.java @@ -0,0 +1,110 @@ +/* + ************************************************************************ + ******************* 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; + +import java.io.IOException; + +/** + * Class for all Exceptions that occur during reading. + */ +public class ReaderException extends IOException +{ + /** + * Constructs a new exception with the specified detail message. The + * cause is not initialized, and may subsequently be initialized by + * a call to {@link #initCause}. + * + * @param message the detail message. The detail message is saved for + * later retrieval by the {@link #getMessage()} method. + */ + public ReaderException(String message) + { + super(message); + } + + /** + * Constructs a new exception with the specified detail message and + * cause. <p>Note that the detail message associated with + * <code>cause</code> is <i>not</i> automatically incorporated in + * this exception's detail message. + * + * @param message the detail message (which is saved for later retrieval + * by the {@link #getMessage()} method). + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A <tt>null</tt> value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + * @since 1.4 + */ + public ReaderException(String message, Throwable cause) + { + super(message, cause); + } + +} diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/Role.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/Role.java new file mode 100644 index 0000000000000000000000000000000000000000..3223ef4e70001625b2c5521961c6b8117b52eb54 --- /dev/null +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/Role.java @@ -0,0 +1,112 @@ +/* + ************************************************************************ + ******************* 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; + +/** + * + * @author jburke + */ +public enum Role +{ + OWNER("owner"), + MEMBER("member"), + ADMIN("admin"); + + private final String value; + + private Role(String value) + { + this.value = value; + } + + public static Role toValue(String s) + { + for (Role role : values()) + if (role.value.equals(s)) + return role; + throw new IllegalArgumentException("invalid value: " + s); + } + + public String getValue() + { + return value; + } + + public int checksum() + { + return value.hashCode(); + } + + @Override + public String toString() + { + return this.getClass().getSimpleName() + "[" + value + "]"; + } + +} diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/User.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/User.java index 3174d0136d7d2fbbc5bdd0a4fa5e758118ae0ded..22f609ad0ee492fc483f24a34a0f3b87c6ae87b3 100644 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/User.java +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/User.java @@ -1,39 +1,71 @@ /* ************************************************************************ - **** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** + ******************* CANADIAN ASTRONOMY DATA CENTRE ******************* + ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** * - * (c) 2014. (c) 2014. - * National Research Council Conseil national de recherches - * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 - * All rights reserved Tous droits reserves + * (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 denie toute garantie - * expressed, implied, or statu- enoncee, implicite ou legale, - * tory, of any kind with respect de quelque nature que se soit, - * to the software, including concernant le logiciel, y com- - * without limitation any war- pris sans restriction toute - * ranty of merchantability or garantie de valeur marchande - * fitness for a particular pur- ou de pertinence pour un usage - * pose. NRC shall not be liable particulier. Le CNRC ne - * in any event for any damages, pourra en aucun cas etre tenu - * whether direct or indirect, responsable de tout dommage, - * special or general, consequen- direct ou indirect, particul- - * tial or incidental, arising ier ou general, accessoire ou - * from the use of the software. fortuit, resultant de l'utili- - * sation du logiciel. + * 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 $ * - * @author adriand - * - * @version $Revision: $ - * - * - **** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** ************************************************************************ */ - - - package ca.nrc.cadc.ac; import java.security.Principal; @@ -43,46 +75,42 @@ import java.util.Set; public class User<T extends Principal> { private T userID; - - private Set<Principal> principals = new HashSet<Principal>(); + private Set<Principal> identities = new HashSet<Principal>(); + public Set<UserDetails> details = new HashSet<UserDetails>(); - - + public User(final T userID) { - if(userID == null) + if (userID == null) { throw new IllegalArgumentException("null userID"); } this.userID = userID; } - - - public Set<Principal> getPrincipals() + + public Set<Principal> getIdentities() { - return principals; + return identities; } - + public T getUserID() { return userID; } - /* (non-Javadoc) * @see java.lang.Object#hashCode() */ @Override public int hashCode() { - final int prime = 31; + int prime = 31; int result = 1; result = prime * result + userID.hashCode(); return result; } - /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @@ -101,18 +129,36 @@ public class User<T extends Principal> { return false; } - User<?> other = (User<?>) obj; + User other = (User) obj; if (!userID.equals(other.userID)) { return false; } return true; } - + @Override public String toString() { return getClass().getSimpleName() + "[" + userID.getName() + "]"; } - + + public <S extends UserDetails> Set<S> getDetails( + final Class<S> userDetailsClass) + { + final Set<S> matchedDetails = new HashSet<S>(); + + for (final UserDetails ud : details) + { + if (ud.getClass() == userDetailsClass) + { + // This casting shouldn't happen, but it's the only way to + // do this without a lot of work. + // jenkinsd 2014.09.26 + matchedDetails.add((S) ud); + } + } + + return matchedDetails; + } } diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/UserDetails.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/UserDetails.java index d03035c1be2377d4de5ebd9174729138006da364..92c259f181c9108f7ba6d56a5772022e112e7eee 100644 --- a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/UserDetails.java +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/UserDetails.java @@ -1,56 +1,99 @@ /* ************************************************************************ - **** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** - * - * (c) 2014. (c) 2014. - * National Research Council Conseil national de recherches - * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 - * All rights reserved Tous droits reserves - * - * NRC disclaims any warranties Le CNRC denie toute garantie - * expressed, implied, or statu- enoncee, implicite ou legale, - * tory, of any kind with respect de quelque nature que se soit, - * to the software, including concernant le logiciel, y com- - * without limitation any war- pris sans restriction toute - * ranty of merchantability or garantie de valeur marchande - * fitness for a particular pur- ou de pertinence pour un usage - * pose. NRC shall not be liable particulier. Le CNRC ne - * in any event for any damages, pourra en aucun cas etre tenu - * whether direct or indirect, responsable de tout dommage, - * special or general, consequen- direct ou indirect, particul- - * tial or incidental, arising ier ou general, accessoire ou - * from the use of the software. fortuit, resultant de l'utili- - * sation du logiciel. - * - * - * @author adriand - * - * @version $Revision: $ - * - * - **** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** + ******************* 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; -public interface UserDetails +public abstract interface UserDetails { - + /** + * Name of the UserDetails element. + */ + public static final String NAME = "userDetails"; + + /** + * Name of the property type attribute in the UserDetails element. + */ + public static final String TYPE_ATTRIBUTE = "type"; + /* * (non-Javadoc) * * @see java.lang.Object#hashCode() */ - public int hashCode(); + public abstract int hashCode(); /* * (non-Javadoc) * * @see java.lang.Object#equals(java.lang.Object) */ - public boolean equals(Object obj); + public abstract boolean equals(Object paramObject); - public String toString(); + public abstract String toString(); } diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/UserNotFoundException.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/UserNotFoundException.java new file mode 100755 index 0000000000000000000000000000000000000000..9b9123c7aeb7c0a244b96767124fc1fc8416c9fc --- /dev/null +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/UserNotFoundException.java @@ -0,0 +1,82 @@ +/* + ************************************************************************ + ******************* 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; + +/** + * Thrown when a user could not be found. + * + */ +public class UserNotFoundException extends Exception +{ + public UserNotFoundException(String message) + { + super(message); + } + +} diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/UserReader.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/UserReader.java new file mode 100755 index 0000000000000000000000000000000000000000..a28883a34a6830c3ad1e4969284e09a6497d2615 --- /dev/null +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/UserReader.java @@ -0,0 +1,217 @@ +/* + ************************************************************************ + ******************* 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; + +import ca.nrc.cadc.xml.XmlUtil; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; +import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; +import java.security.Principal; +import java.util.List; +import org.jdom2.Document; +import org.jdom2.Element; +import org.jdom2.JDOMException; + +public class UserReader +{ + /** + * Construct a User from an XML String source. + * + * @param xml String of the XML. + * @return User User. + * @throws ca.nrc.cadc.ac.ReaderException + * @throws java.io.IOException + * @throws java.net.URISyntaxException + */ + public static User<? extends Principal> read(String xml) + throws ReaderException, IOException, URISyntaxException + { + if (xml == null) + { + throw new IllegalArgumentException("XML must not be null"); + } + return read(new StringReader(xml)); + } + + /** + * Construct a User from a InputStream. + * + * @param in InputStream. + * @return User User. + * @throws ca.nrc.cadc.ac.ReaderException + * @throws java.io.IOException + * @throws java.net.URISyntaxException + */ + public static User<? extends Principal> read(InputStream in) + throws ReaderException, IOException, URISyntaxException + { + if (in == null) + { + throw new IOException("stream closed"); + } + InputStreamReader reader; + try + { + reader = new InputStreamReader(in, "UTF-8"); + } + catch (UnsupportedEncodingException e) + { + throw new RuntimeException("UTF-8 encoding not supported"); + } + return read(reader); + } + + /** + * Construct a User from a Reader. + * + * @param reader Reader. + * @return User User. + * @throws ca.nrc.cadc.ac.ReaderException + * @throws java.io.IOException + */ + public static User<? extends Principal> read(Reader reader) + throws ReaderException, IOException + { + if (reader == null) + { + throw new IllegalArgumentException("reader must not be null"); + } + + // Create a JDOM Document from the XML + Document document; + try + { + document = XmlUtil.buildDocument(reader); + } + catch (JDOMException jde) + { + String error = "XML failed validation: " + jde.getMessage(); + throw new ReaderException(error, jde); + } + + // Root element and namespace of the Document + Element root = document.getRootElement(); + + return parseUser(root); + } + + protected static User<? extends Principal> parseUser(Element userElement) + throws ReaderException + { + // userID element of the User element + Element userIDElement = userElement.getChild("userID"); + if (userIDElement == null) + { + String error = "userID element not found in user element"; + throw new ReaderException(error); + } + + // identity element of the userID element + Element userIDIdentityElement = userIDElement.getChild("identity"); + if (userIDIdentityElement == null) + { + String error = "identity element not found in userID element"; + throw new ReaderException(error); + } + + Principal userID = IdentityReader.read(userIDIdentityElement); + + User<Principal> user = new User<Principal>(userID); + + // identities + Element identitiesElement = userElement.getChild("identities"); + if (identitiesElement != null) + { + List<Element> identityElements = identitiesElement.getChildren("identity"); + for (Element identityElement : identityElements) + { + user.getIdentities().add(IdentityReader.read(identityElement)); + } + + } + + // details + Element detailsElement = userElement.getChild("details"); + if (detailsElement != null) + { + List<Element> userDetailsElements = detailsElement.getChildren("userDetails"); + for (Element userDetailsElement : userDetailsElements) + { + user.details.add(UserDetailsReader.read(userDetailsElement)); + } + } + + return user; + } + +} diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/UserWriter.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/UserWriter.java new file mode 100755 index 0000000000000000000000000000000000000000..832e41a612a9ed88cb1c5fff6cc5af33753c4275 --- /dev/null +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/UserWriter.java @@ -0,0 +1,203 @@ +/* + ************************************************************************ + ******************* 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; + +import ca.nrc.cadc.util.StringBuilderWriter; +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.util.Set; +import org.jdom2.Document; +import org.jdom2.Element; +import org.jdom2.output.Format; +import org.jdom2.output.XMLOutputter; + +public class UserWriter +{ + /** + * Write a User to a StringBuilder. + * + * @param user User to write. + * @param builder StringBuilder to write to. + * @throws java.io.IOException if the writer fails to write. + * @throws ca.nrc.cadc.ac.WriterException + */ + public static void write(User<? extends Principal> user, StringBuilder builder) + throws IOException, WriterException + { + write(user, new StringBuilderWriter(builder)); + } + + /** + * Write a User to an OutputStream. + * + * @param user User to write. + * @param out OutputStream to write to. + * @throws IOException if the writer fails to write. + * @throws ca.nrc.cadc.ac.WriterException + */ + public static void write(User<? extends Principal> user, 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(user, new BufferedWriter(outWriter)); + } + + /** + * Write a User to a Writer. + * + * @param user User to write. + * @param writer Writer to write to. + * @throws IOException if the writer fails to write. + * @throws ca.nrc.cadc.ac.WriterException + */ + public static void write(User<? extends Principal> user, Writer writer) + throws IOException, WriterException + { + if (user == null) + { + throw new WriterException("null User"); + } + + write(getUserElement(user), writer); + } + + /** + * Build the member Element of a User. + * + * @param user User. + * @return member Element. + * @throws ca.nrc.cadc.ac.WriterException + */ + public static Element getUserElement(User<? extends Principal> user) + throws WriterException + { + // Create the user Element. + Element userElement = new Element("user"); + + // userID element + Element userIDElement = new Element("userID"); + userIDElement.addContent(IdentityWriter.write(user.getUserID())); + userElement.addContent(userIDElement); + + // identities + Set<Principal> identities = user.getIdentities(); + if (!identities.isEmpty()) + { + Element identitiesElement = new Element("identities"); + for (Principal identity : identities) + { + identitiesElement.addContent(IdentityWriter.write(identity)); + } + userElement.addContent(identitiesElement); + } + + // details + if (!user.details.isEmpty()) + { + Element detailsElement = new Element("details"); + Set<UserDetails> userDetails = user.details; + for (UserDetails userDetail : userDetails) + { + detailsElement.addContent(UserDetailsWriter.write(userDetail)); + } + userElement.addContent(detailsElement); + } + + return userElement; + } + + /** + * Write to root Element to a writer. + * + * @param root Root Element to write. + * @param writer Writer to write to. + * @throws IOException if the writer fails to write. + */ + private static void write(Element root, Writer writer) + throws IOException + { + XMLOutputter outputter = new XMLOutputter(); + outputter.setFormat(Format.getPrettyFormat()); + outputter.output(new Document(root), writer); + } + +} diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/WriterException.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/WriterException.java new file mode 100755 index 0000000000000000000000000000000000000000..3bf5a2b87b05ce9cb0c2279cbf7ad72c466801d1 --- /dev/null +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/WriterException.java @@ -0,0 +1,110 @@ +/* + ************************************************************************ + ******************* 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; + +import java.io.IOException; + +/** + * Base exception for all Writer class exceptions. + */ +public class WriterException extends IOException +{ + /** + * Constructs a new exception with the specified detail message. The + * cause is not initialized, and may subsequently be initialized by + * a call to {@link #initCause}. + * + * @param message the detail message. The detail message is saved for + * later retrieval by the {@link #getMessage()} method. + */ + public WriterException(String message) + { + super(message); + } + + /** + * Constructs a new exception with the specified detail message and + * cause. <p>Note that the detail message associated with + * <code>cause</code> is <i>not</i> automatically incorporated in + * this exception's detail message. + * + * @param message the detail message (which is saved for later retrieval + * by the {@link #getMessage()} method). + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A <tt>null</tt> value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + * @since 1.4 + */ + public WriterException(String message, Throwable cause) + { + super(message, cause); + } + +} diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/client/GMSClient.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/client/GMSClient.java new file mode 100755 index 0000000000000000000000000000000000000000..7609ee7326133d0d2975059fdd7666c0e3435f0c --- /dev/null +++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/client/GMSClient.java @@ -0,0 +1,1112 @@ +/* + ************************************************************************ + ******************* 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.client; + +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; +import java.net.URLEncoder; +import java.security.AccessControlContext; +import java.security.AccessControlException; +import java.security.AccessController; +import java.security.Principal; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +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 org.apache.log4j.Logger; + +import ca.nrc.cadc.ac.Group; +import ca.nrc.cadc.ac.GroupAlreadyExistsException; +import ca.nrc.cadc.ac.GroupNotFoundException; +import ca.nrc.cadc.ac.GroupReader; +import ca.nrc.cadc.ac.GroupWriter; +import ca.nrc.cadc.ac.GroupsReader; +import ca.nrc.cadc.ac.Role; +import ca.nrc.cadc.ac.UserNotFoundException; +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; + + +/** + * Client class for performing group searching and group actions + * with the access control web service. + */ +public class GMSClient +{ + private static final Logger log = Logger.getLogger(GMSClient.class); + + // socket factory to use when connecting + private SSLSocketFactory sslSocketFactory; + private SSLSocketFactory mySocketFactory; + + private String baseURL; + + /** + * Constructor. + * + * @param baseURL The URL of the supporting access control web service + * obtained from the registry. + */ + public GMSClient(String baseURL) + throws IllegalArgumentException + { + if (baseURL == null) + { + throw new IllegalArgumentException("baseURL is required"); + } + try + { + new URL(baseURL); + } + catch (MalformedURLException e) + { + throw new IllegalArgumentException("URL is malformed: " + + e.getMessage()); + } + + if (baseURL.endsWith("/")) + { + this.baseURL = baseURL.substring(0, baseURL.length() - 1); + } + else + { + this.baseURL = baseURL; + } + } + + /** + * Get a list of groups. + * + * @return The list of groups. + */ + public List<Group> getGroups() + { + throw new UnsupportedOperationException("Not yet implemented"); + } + + /** + * Create a new group. + * + * @param group The group to create + * @return The newly created group will all the information. + * @throws GroupAlreadyExistsException If a group with the same name already + * exists. + * @throws AccessControlException If unauthorized to perform this operation. + * @throws UserNotFoundException + * @throws IOException + */ + public Group createGroup(Group group) + throws GroupAlreadyExistsException, AccessControlException, + UserNotFoundException, IOException + { + URL createGroupURL = new URL(this.baseURL + "/groups"); + log.debug("createGroupURL request to " + createGroupURL.toString()); + + // reset the state of the cache + clearCache(); + + StringBuilder groupXML = new StringBuilder(); + GroupWriter.write(group, groupXML); + log.debug("createGroup: " + groupXML); + + byte[] bytes = groupXML.toString().getBytes("UTF-8"); + ByteArrayInputStream in = new ByteArrayInputStream(bytes); + + HttpUpload transfer = new HttpUpload(in, createGroupURL); + transfer.setSSLSocketFactory(getSSLSocketFactory()); + + transfer.run(); + + Throwable error = transfer.getThrowable(); + if (error != null) + { + log.debug("createGroup throwable", error); + // transfer returns a -1 code for anonymous uploads. + if ((transfer.getResponseCode() == -1) || + (transfer.getResponseCode() == 401) || + (transfer.getResponseCode() == 403)) + { + throw new AccessControlException(error.getMessage()); + } + if (transfer.getResponseCode() == 400) + { + throw new IllegalArgumentException(error.getMessage()); + } + if (transfer.getResponseCode() == 409) + { + throw new GroupAlreadyExistsException(error.getMessage()); + } + if (transfer.getResponseCode() == 404) + { + throw new UserNotFoundException(error.getMessage()); + } + throw new IOException(error); + } + + String retXML = transfer.getResponseBody(); + try + { + log.debug("createGroup returned: " + retXML); + return GroupReader.read(retXML); + } + catch (Exception bug) + { + log.error("Unexpected exception", bug); + throw new RuntimeException(bug); + } + } + + /** + * Get the group object. + * + * @param groupName Identifies the group to get. + * @return The group. + * @throws GroupNotFoundException If the group was not found. + * @throws AccessControlException If unauthorized to perform this operation. + * @throws java.io.IOException + */ + public Group getGroup(String groupName) + throws GroupNotFoundException, AccessControlException, IOException + { + URL getGroupURL = new URL(this.baseURL + "/groups/" + groupName); + log.debug("getGroup request to " + getGroupURL.toString()); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + HttpDownload transfer = new HttpDownload(getGroupURL, out); + + transfer.setSSLSocketFactory(getSSLSocketFactory()); + transfer.run(); + + Throwable error = transfer.getThrowable(); + if (error != null) + { + log.debug("getGroup throwable (" + transfer.getResponseCode() + ")", error); + // transfer returns a -1 code for anonymous access. + if ((transfer.getResponseCode() == -1) || + (transfer.getResponseCode() == 401) || + (transfer.getResponseCode() == 403)) + { + throw new AccessControlException(error.getMessage()); + } + if (transfer.getResponseCode() == 400) + { + throw new IllegalArgumentException(error.getMessage()); + } + if (transfer.getResponseCode() == 404) + { + throw new GroupNotFoundException(error.getMessage()); + } + throw new IOException(error); + } + + try + { + String groupXML = new String(out.toByteArray(), "UTF-8"); + log.debug("getGroup returned: " + groupXML); + return GroupReader.read(groupXML); + } + catch (Exception bug) + { + log.error("Unexpected exception", bug); + throw new RuntimeException(bug); + } + } + + /** + * Get the all group names. + * + * @return The list of names. + * @throws AccessControlException If unauthorized to perform this operation. + * @throws java.io.IOException + */ + public List<String> getGroupNames() + throws AccessControlException, IOException + { + final URL getGroupNamesURL = new URL(this.baseURL + "/groups"); + log.debug("getGroupNames request to " + getGroupNamesURL.toString()); + + final List<String> groupNames = new ArrayList<String>(); + final HttpDownload httpDownload = + new HttpDownload(getGroupNamesURL, new InputStreamWrapper() + { + @Override + public void read(final InputStream inputStream) throws IOException + { + try + { + InputStreamReader inReader = new InputStreamReader(inputStream); + BufferedReader reader = new BufferedReader(inReader); + String line; + while ((line = reader.readLine()) != null) { + groupNames.add(line); + } + } + catch (Exception bug) + { + log.error("Unexpected exception", bug); + throw new RuntimeException(bug); + } + } + }); + + httpDownload.setSSLSocketFactory(getSSLSocketFactory()); + httpDownload.run(); + + final Throwable error = httpDownload.getThrowable(); + + if (error != null) + { + final String errMessage = error.getMessage(); + final int responseCode = httpDownload.getResponseCode(); + + log.debug("getGroupNames response " + responseCode + ": " + + errMessage); + + if ((responseCode == 401) || (responseCode == 403) || + (responseCode == -1)) + { + throw new AccessControlException(errMessage); + } + if (responseCode == 400) + { + throw new IllegalArgumentException(errMessage); + } + throw new IOException("HttpResponse (" + responseCode + ") - " + errMessage); + } + + log.debug("Content-Length: " + httpDownload.getContentLength()); + log.debug("Content-Type: " + httpDownload.getContentType()); + + return groupNames; + } + + /** + * Update a group. + * + * @param group The update group object. + * @return The group after update. + * @throws IllegalArgumentException If cyclical membership is detected. + * @throws GroupNotFoundException If the group was not found. + * @throws UserNotFoundException If a member was not found. + * @throws AccessControlException If unauthorized to perform this operation. + * @throws java.io.IOException + */ + public void updateGroup(Group group) + throws IllegalArgumentException, GroupNotFoundException, UserNotFoundException, + AccessControlException, IOException + { + URL updateGroupURL = new URL(this.baseURL + "/groups/" + group.getID()); + log.debug("updateGroup request to " + updateGroupURL.toString()); + + // reset the state of the cache + clearCache(); + + StringBuilder groupXML = new StringBuilder(); + GroupWriter.write(group, groupXML); + log.debug("updateGroup: " + groupXML); + + HttpPost transfer = new HttpPost(updateGroupURL, groupXML.toString(), + "application/xml", false); + + transfer.setSSLSocketFactory(getSSLSocketFactory()); + transfer.run(); + + Throwable error = transfer.getThrowable(); + if (error != null) + { + // transfer returns a -1 code for anonymous access. + if ((transfer.getResponseCode() == -1) || + (transfer.getResponseCode() == 401) || + (transfer.getResponseCode() == 403)) + { + throw new AccessControlException(error.getMessage()); + } + if (transfer.getResponseCode() == 400) + { + throw new IllegalArgumentException(error.getMessage()); + } + if (transfer.getResponseCode() == 404) + { + if (error.getMessage() != null && error.getMessage().toLowerCase().contains("user")) + throw new UserNotFoundException(error.getMessage()); + else + throw new GroupNotFoundException(error.getMessage()); + } + throw new IOException(error); + } + } + + /** + * Delete the group. + * + * @param groupName Identifies the group to delete. + * @throws GroupNotFoundException If the group was not found. + * @throws AccessControlException If unauthorized to perform this operation. + * @throws java.io.IOException + */ + public void deleteGroup(String groupName) + throws GroupNotFoundException, AccessControlException, IOException + { + URL deleteGroupURL = new URL(this.baseURL + "/groups/" + groupName); + log.debug("deleteGroup request to " + deleteGroupURL.toString()); + + // reset the state of the cache + clearCache(); + + HttpURLConnection conn = + (HttpURLConnection) deleteGroupURL.openConnection(); + conn.setRequestMethod("DELETE"); + + SSLSocketFactory sf = getSSLSocketFactory(); + if ((sf != null) && ((conn instanceof HttpsURLConnection))) + { + ((HttpsURLConnection) conn) + .setSSLSocketFactory(sf); + } + + final int responseCode; + + try + { + responseCode = conn.getResponseCode(); + } + catch(Exception e) + { + throw new AccessControlException(e.getMessage()); + } + + if (responseCode != 200) + { + String errMessage = NetUtil.getErrorBody(conn); + log.debug("deleteGroup response " + responseCode + ": " + + errMessage); + + if ((responseCode == 401) || (responseCode == 403) || + (responseCode == -1)) + { + throw new AccessControlException(errMessage); + } + if (responseCode == 400) + { + throw new IllegalArgumentException(errMessage); + } + if (responseCode == 404) + { + throw new GroupNotFoundException(errMessage); + } + throw new IOException("HttpResponse (" + responseCode + ") - " + errMessage); + } + } + + /** + * Add a group as a member of another group. + * + * @param targetGroupName The group in which to add the group member. + * @param groupMemberName The group member to add. + * @throws IllegalArgumentException If cyclical membership is detected. + * @throws GroupNotFoundException If the group was not found. + * @throws AccessControlException If unauthorized to perform this operation. + * @throws java.io.IOException + */ + public void addGroupMember(String targetGroupName, String groupMemberName) + throws IllegalArgumentException, GroupNotFoundException, + AccessControlException, IOException + { + URL addGroupMemberURL = new URL(this.baseURL + "/groups/" + + targetGroupName + "/groupMembers/" + + groupMemberName); + log.debug("addGroupMember request to " + addGroupMemberURL.toString()); + + // reset the state of the cache + clearCache(); + + final InputStream is = new ByteArrayInputStream(new byte[0]); + final HttpUpload httpUpload = new HttpUpload(is, addGroupMemberURL); + + httpUpload.setSSLSocketFactory(getSSLSocketFactory()); + httpUpload.run(); + + final Throwable error = httpUpload.getThrowable(); + if (error != null) + { + final int responseCode = httpUpload.getResponseCode(); + final String errMessage = error.getMessage(); + + if ((responseCode == -1) || + (responseCode == 401) || + (responseCode == 403)) + { + throw new AccessControlException(errMessage); + } + if (responseCode == 400) + { + throw new IllegalArgumentException(errMessage); + } + if (responseCode == 404) + { + throw new GroupNotFoundException(errMessage); + } + throw new IOException(errMessage); + } + } + + /** + * Add a user as a member of a group. + * + * @param targetGroupName The group in which to add the group member. + * @param userID The user to add. + * @throws GroupNotFoundException If the group was not found. + * @throws UserNotFoundException If the member was not found. + * @throws java.io.IOException + * @throws AccessControlException If unauthorized to perform this operation. + */ + public void addUserMember(String targetGroupName, Principal userID) + throws GroupNotFoundException, UserNotFoundException, AccessControlException, IOException + { + String userIDType = AuthenticationUtil.getPrincipalType(userID); + String encodedUserID = URLEncoder.encode(userID.getName(), "UTF-8"); + URL addUserMemberURL = new URL(this.baseURL + "/groups/" + + targetGroupName + "/userMembers/" + + encodedUserID + "?idType=" + userIDType); + + log.debug("addUserMember request to " + addUserMemberURL.toString()); + + // reset the state of the cache + clearCache(); + + final InputStream is = new ByteArrayInputStream(new byte[0]); + final HttpUpload httpUpload = new HttpUpload(is, addUserMemberURL); + + httpUpload.setSSLSocketFactory(getSSLSocketFactory()); + httpUpload.run(); + + final Throwable error = httpUpload.getThrowable(); + if (error != null) + { + final int responseCode = httpUpload.getResponseCode(); + final String errMessage = error.getMessage(); + + if ((responseCode == -1) || + (responseCode == 401) || + (responseCode == 403)) + { + throw new AccessControlException(errMessage); + } + if (responseCode == 400) + { + throw new IllegalArgumentException(errMessage); + } + if (responseCode == 404) + { + if (errMessage != null && errMessage.toLowerCase().contains("user")) + throw new UserNotFoundException(errMessage); + else + throw new GroupNotFoundException(errMessage); + } + throw new IOException(errMessage); + } + } + + /** + * Remove a group as a member of another group. + * + * @param targetGroupName The group from which to remove the group member. + * @param groupMemberName The group member to remove. + * @throws GroupNotFoundException If the group was not found. + * @throws java.io.IOException + * @throws AccessControlException If unauthorized to perform this operation. + */ + public void removeGroupMember(String targetGroupName, + String groupMemberName) + throws GroupNotFoundException, AccessControlException, IOException + { + URL removeGroupMemberURL = new URL(this.baseURL + "/groups/" + + targetGroupName + "/groupMembers/" + + groupMemberName); + log.debug("removeGroupMember request to " + + removeGroupMemberURL.toString()); + + // reset the state of the cache + clearCache(); + + HttpURLConnection conn = + (HttpURLConnection) removeGroupMemberURL.openConnection(); + conn.setRequestMethod("DELETE"); + + SSLSocketFactory sf = getSSLSocketFactory(); + if ((sf != null) && ((conn instanceof HttpsURLConnection))) + { + ((HttpsURLConnection) conn) + .setSSLSocketFactory(getSSLSocketFactory()); + } + + // Try to handle anonymous access and throw AccessControlException + int responseCode = -1; + try + { + responseCode = conn.getResponseCode(); + } + catch (Exception ignore) {} + + if (responseCode != 200) + { + String errMessage = NetUtil.getErrorBody(conn); + log.debug("removeGroupMember response " + responseCode + ": " + + errMessage); + + if ((responseCode == -1) || + (responseCode == 401) || + (responseCode == 403)) + { + throw new AccessControlException(errMessage); + } + if (responseCode == 400) + { + throw new IllegalArgumentException(errMessage); + } + if (responseCode == 404) + { + throw new GroupNotFoundException(errMessage); + } + throw new IOException(errMessage); + } + } + + /** + * Remove a user as a member of a group. + * + * @param targetGroupName The group from which to remove the group member. + * @param userID The user to remove. + * @throws GroupNotFoundException If the group was not found. + * @throws UserNotFoundException If the member was not found. + * @throws java.io.IOException + * @throws AccessControlException If unauthorized to perform this operation. + */ + public void removeUserMember(String targetGroupName, Principal userID) + throws GroupNotFoundException, UserNotFoundException, AccessControlException, IOException + { + String userIDType = AuthenticationUtil.getPrincipalType(userID); + String encodedUserID = URLEncoder.encode(userID.toString(), "UTF-8"); + URL removeUserMemberURL = new URL(this.baseURL + "/groups/" + + targetGroupName + "/userMembers/" + + encodedUserID + "?idType=" + + userIDType); + + log.debug("removeUserMember request to " + + removeUserMemberURL.toString()); + + // reset the state of the cache + clearCache(); + + HttpURLConnection conn = + (HttpURLConnection) removeUserMemberURL.openConnection(); + conn.setRequestMethod("DELETE"); + + SSLSocketFactory sf = getSSLSocketFactory(); + if ((sf != null) && ((conn instanceof HttpsURLConnection))) + { + ((HttpsURLConnection) conn) + .setSSLSocketFactory(getSSLSocketFactory()); + } + + // Try to handle anonymous access and throw AccessControlException + int responseCode = -1; + try + { + responseCode = conn.getResponseCode(); + } + catch (Exception ignore) {} + + if (responseCode != 200) + { + String errMessage = NetUtil.getErrorBody(conn); + log.debug("removeUserMember response " + responseCode + ": " + + errMessage); + + if ((responseCode == -1) || + (responseCode == 401) || + (responseCode == 403)) + { + throw new AccessControlException(errMessage); + } + if (responseCode == 400) + { + throw new IllegalArgumentException(errMessage); + } + if (responseCode == 404) + { + if (errMessage != null && errMessage.toLowerCase().contains("user")) + throw new UserNotFoundException(errMessage); + else + throw new GroupNotFoundException(errMessage); + } + throw new IOException(errMessage); + } + } + + /** + * Get all the memberships of the user of a certain role. + * + * @param userID Identifies the user. + * @param role The role to look up. + * @return A list of groups for which the user has the role. + * @throws UserNotFoundException If the user does not exist. + * @throws AccessControlException If not allowed to peform the search. + * @throws IllegalArgumentException If a parameter is null. + * @throws IOException If an unknown error occured. + */ + public List<Group> getMemberships(Principal userID, Role role) + throws UserNotFoundException, AccessControlException, IOException + { + if (userID == null || role == null) + { + throw new IllegalArgumentException("userID and role are required."); + } + + List<Group> cachedGroups = getCachedGroups(userID, role); + if (cachedGroups != null) + { + return cachedGroups; + } + + String idType = AuthenticationUtil.getPrincipalType(userID); + String id = userID.getName(); + String roleString = role.getValue(); + + StringBuilder searchGroupURL = new StringBuilder(this.baseURL); + searchGroupURL.append("/search?"); + + searchGroupURL.append("ID=").append(URLEncoder.encode(id, "UTF-8")); + searchGroupURL.append("&IDTYPE=") + .append(URLEncoder.encode(idType, "UTF-8")); + searchGroupURL.append("&ROLE=") + .append(URLEncoder.encode(roleString, "UTF-8")); + + log.debug("getMemberships request to " + searchGroupURL.toString()); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + URL url = new URL(searchGroupURL.toString()); + HttpDownload transfer = new HttpDownload(url, out); + + transfer.setSSLSocketFactory(getSSLSocketFactory()); + transfer.run(); + + Throwable error = transfer.getThrowable(); + if (error != null) + { + log.debug("getMemberships throwable", error); + // transfer returns a -1 code for anonymous access. + if ((transfer.getResponseCode() == -1) || + (transfer.getResponseCode() == 401) || + (transfer.getResponseCode() == 403)) + { + throw new AccessControlException(error.getMessage()); + } + if (transfer.getResponseCode() == 404) + { + throw new UserNotFoundException(error.getMessage()); + } + if (transfer.getResponseCode() == 400) + { + throw new IllegalArgumentException(error.getMessage()); + } + throw new IOException(error); + } + + try + { + String groupsXML = new String(out.toByteArray(), "UTF-8"); + log.debug("getMemberships returned: " + groupsXML); + List<Group> groups = GroupsReader.read(groupsXML); + setCachedGroups(userID, groups, role); + return groups; + } + catch (Exception bug) + { + log.error("Unexpected exception", bug); + throw new RuntimeException(bug); + } + } + + /** + * Return the group, specified by paramter groupName, if the user, + * identified by userID, is a member of that group. Return null + * otherwise. + * + * This call is identical to getMemberShip(userID, groupName, Role.MEMBER) + * + * @param userID Identifies the user. + * @param groupName Identifies the group. + * @return The group or null of the user is not a member. + * @throws UserNotFoundException If the user does not exist. + * @throws AccessControlException If not allowed to peform the search. + * @throws IllegalArgumentException If a parameter is null. + * @throws IOException If an unknown error occured. + */ + public Group getMembership(Principal userID, String groupName) + throws UserNotFoundException, AccessControlException, IOException + { + return getMembership(userID, groupName, Role.MEMBER); + } + + /** + * Return the group, specified by paramter groupName, if the user, + * identified by userID, is a member (of type role) of that group. + * Return null otherwise. + * + * @param userID Identifies the user. + * @param groupName Identifies the group. + * @param role The membership role to search. + * @return The group or null of the user is not a member. + * @throws UserNotFoundException If the user does not exist. + * @throws AccessControlException If not allowed to peform the search. + * @throws IllegalArgumentException If a parameter is null. + * @throws IOException If an unknown error occured. + */ + public Group getMembership(Principal userID, String groupName, Role role) + throws UserNotFoundException, AccessControlException, IOException + { + if (userID == null || groupName == null || role == null) + { + throw new IllegalArgumentException("userID and role are required."); + } + + List<Group> cachedGroups = getCachedGroups(userID, role); + if (cachedGroups != null) + { + int index = cachedGroups.indexOf(new Group(groupName)); + if (index != -1) + { + return cachedGroups.get(index); + } + else + { + return null; + } + } + + String idType = AuthenticationUtil.getPrincipalType(userID); + String id = userID.getName(); + String roleString = role.getValue(); + + StringBuilder searchGroupURL = new StringBuilder(this.baseURL); + searchGroupURL.append("/search?"); + + searchGroupURL.append("ID=").append(URLEncoder.encode(id, "UTF-8")); + searchGroupURL.append("&IDTYPE=") + .append(URLEncoder.encode(idType, "UTF-8")); + searchGroupURL.append("&ROLE=") + .append(URLEncoder.encode(roleString, "UTF-8")); + searchGroupURL.append("&GROUPID=") + .append(URLEncoder.encode(groupName, "UTF-8")); + + log.debug("getMembership request to " + searchGroupURL.toString()); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + URL url = new URL(searchGroupURL.toString()); + HttpDownload transfer = new HttpDownload(url, out); + + transfer.setSSLSocketFactory(getSSLSocketFactory()); + transfer.run(); + + Throwable error = transfer.getThrowable(); + if (error != null) + { + log.debug("getMembership throwable", error); + // transfer returns a -1 code for anonymous access. + if ((transfer.getResponseCode() == -1) || + (transfer.getResponseCode() == 401) || + (transfer.getResponseCode() == 403)) + { + throw new AccessControlException(error.getMessage()); + } + if (transfer.getResponseCode() == 404) + { + throw new UserNotFoundException(error.getMessage()); + } + if (transfer.getResponseCode() == 400) + { + throw new IllegalArgumentException(error.getMessage()); + } + throw new IOException(error); + } + + try + { + String groupsXML = new String(out.toByteArray(), "UTF-8"); + log.debug("getMembership returned: " + groupsXML); + List<Group> groups = GroupsReader.read(groupsXML); + if (groups.size() == 0) + { + return null; + } + if (groups.size() == 1) + { + // don't cache these results as it is not a complete + // list of memberships--it only applies to one group. + return groups.get(0); + } + throw new IllegalStateException( + "Duplicate membership for " + id + " in group " + groupName); + } + catch (Exception bug) + { + log.error("Unexpected exception", bug); + throw new RuntimeException(bug); + } + } + + /** + * Check if userID is a member of groupName. + * + * This is equivalent to isMember(userID, groupName, Role.MEMBER) + * + * @param userID Identifies the user. + * @param groupName Identifies the group. + * @return True if the user is a member of the group + * @throws UserNotFoundException If the user does not exist. + * @throws AccessControlException If not allowed to peform the search. + * @throws IllegalArgumentException If a parameter is null. + * @throws IOException If an unknown error occured. + */ + public boolean isMember(Principal userID, String groupName) + throws UserNotFoundException, AccessControlException, IOException + { + return isMember(userID, groupName, Role.MEMBER); + } + + /** + * Check if userID is a member (of type role) of groupName. + * + * @param userID Identifies the user. + * @param groupName Identifies the group. + * @param role The type of membership. + * @return True if the user is a member of the group + * @throws UserNotFoundException If the user does not exist. + * @throws AccessControlException If not allowed to peform the search. + * @throws IllegalArgumentException If a parameter is null. + * @throws IOException If an unknown error occured. + */ + public boolean isMember(Principal userID, String groupName, Role role) + throws UserNotFoundException, AccessControlException, IOException + { + Group group = getMembership(userID, groupName, role); + return group != null; + } + + /** + * @param sslSocketFactory the sslSocketFactory to set + */ + public void setSSLSocketFactory(SSLSocketFactory sslSocketFactory) + { + if (mySocketFactory != null) + throw new IllegalStateException("Illegal use of GMSClient: " + + "cannot set SSLSocketFactory after using one created from Subject"); + this.sslSocketFactory = sslSocketFactory; + clearCache(); + } + + private int subjectHashCode = 0; + private SSLSocketFactory getSSLSocketFactory() + { + AccessControlContext ac = AccessController.getContext(); + Subject s = Subject.getSubject(ac); + + // no real Subject: can only use the one from setSSLSocketFactory + if (s == null || s.getPrincipals().isEmpty()) + { + return sslSocketFactory; + } + + // lazy init + if (this.mySocketFactory == null) + { + log.debug("getSSLSocketFactory: " + s); + this.mySocketFactory = SSLUtil.getSocketFactory(s); + this.subjectHashCode = s.hashCode(); + } + else + { + int c = s.hashCode(); + if (c != subjectHashCode) + throw new IllegalStateException("Illegal use of " + + this.getClass().getSimpleName() + + ": subject change not supported for internal SSLSocketFactory"); + } + return this.mySocketFactory; + } + + protected void clearCache() + { + AccessControlContext acContext = AccessController.getContext(); + Subject subject = Subject.getSubject(acContext); + + if (subject != null) + { + log.debug("Clearing cache"); + subject.getPrivateCredentials().clear(); + } + } + + protected List<Group> getCachedGroups(Principal userID, Role role) + { + AccessControlContext acContext = AccessController.getContext(); + Subject subject = Subject.getSubject(acContext); + + // only consult cache if the userID is of the calling subject + if (userIsSubject(userID, subject)) + { + Set groupCredentialSet = subject.getPrivateCredentials(GroupMemberships.class); + if ((groupCredentialSet != null) && + (groupCredentialSet.size() == 1)) + { + Iterator i = groupCredentialSet.iterator(); + GroupMemberships groupMemberships = ((GroupMemberships) i.next()); + return groupMemberships.memberships.get(role); + } + } + return null; + } + + protected void setCachedGroups(Principal userID, List<Group> groups, Role role) + { + AccessControlContext acContext = AccessController.getContext(); + Subject subject = Subject.getSubject(acContext); + + // only save to cache if the userID is of the calling subject + if (userIsSubject(userID, subject)) + { + log.debug("Caching groups for " + userID + ", role " + role); + + final GroupMemberships groupCredentials; + Set groupCredentialSet = subject.getPrivateCredentials(GroupMemberships.class); + if ((groupCredentialSet != null) && + (groupCredentialSet.size() == 1)) + { + Iterator i = groupCredentialSet.iterator(); + groupCredentials = ((GroupMemberships) i.next()); + } + else + { + groupCredentials = new GroupMemberships(); + subject.getPrivateCredentials().add(groupCredentials); + } + + groupCredentials.memberships.put(role, groups); + } + } + + protected boolean userIsSubject(Principal userID, Subject subject) + { + if (userID == null || subject == null) + { + return false; + } + + for (Principal subjectPrincipal : subject.getPrincipals()) + { + if (subjectPrincipal.equals(userID)) + { + return true; + } + } + return false; + } + + /** + * Class used to hold list of groups in which + * a user is a member. + */ + protected class GroupMemberships + { + Map<Role, List<Group>> memberships = new HashMap<Role, List<Group>>(); + + protected GroupMemberships() + { + } + + } + +} diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/GroupPropertyReaderWriterTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/GroupPropertyReaderWriterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..189352538636b4f9561ec7ab2a472012f8fb6f0e --- /dev/null +++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/GroupPropertyReaderWriterTest.java @@ -0,0 +1,178 @@ +/* + ************************************************************************ + ******************* 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; + +import org.apache.log4j.Logger; +import org.jdom2.Element; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author jburke + */ +public class GroupPropertyReaderWriterTest +{ + private static Logger log = Logger.getLogger(GroupPropertyReaderWriterTest.class); + + @Test + public void testReaderExceptions() + throws Exception + { + Element element = null; + try + { + GroupProperty gp = GroupPropertyReader.read(element); + fail("null element should throw ReaderException"); + } + catch (ReaderException e) {} + + element = new Element("foo"); + try + { + GroupProperty gp = GroupPropertyReader.read(element); + fail("element not named 'property' should throw ReaderException"); + } + catch (ReaderException e) {} + + element = new Element("property"); + try + { + GroupProperty gp = GroupPropertyReader.read(element); + fail("element without 'key' attribute should throw ReaderException"); + } + catch (ReaderException e) {} + + element.setAttribute("key", "foo"); + try + { + GroupProperty gp = GroupPropertyReader.read(element); + fail("element without 'type' attribute should throw ReaderException"); + } + catch (ReaderException e) {} + + element.setAttribute("type", "Double"); + try + { + GroupProperty gp = GroupPropertyReader.read(element); + fail("Unsupported 'type' should throw ReaderException"); + } + catch (ReaderException e) {} + } + + @Test + public void testWriterExceptions() + throws Exception + { + try + { + Element element = GroupPropertyWriter.write(null); + fail("null GroupProperty should throw WriterException"); + } + catch (WriterException e) {} + + GroupProperty gp = new GroupProperty("key", new Double(1.0), true); + try + { + Element element = GroupPropertyWriter.write(gp); + fail("Unsupported GroupProperty type should throw IllegalArgumentException"); + } + catch (IllegalArgumentException e) {} + } + + @Test + public void testReadWrite() + throws Exception + { + // String type + GroupProperty expected = new GroupProperty("key", "value", true); + Element element = GroupPropertyWriter.write(expected); + assertNotNull(element); + + GroupProperty actual = GroupPropertyReader.read(element); + assertNotNull(actual); + + assertEquals(expected, actual); + + // Integer tuype + expected = new GroupProperty("key", new Integer(1), false); + element = GroupPropertyWriter.write(expected); + assertNotNull(element); + + actual = GroupPropertyReader.read(element); + assertNotNull(actual); + + assertEquals(expected, actual); + } + +} diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/GroupPropertyTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/GroupPropertyTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b19171c414d64d3d812cc3c55e3ac6bf4709e2be --- /dev/null +++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/GroupPropertyTest.java @@ -0,0 +1,128 @@ +/* + ************************************************************************ + ******************* 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; + +import org.apache.log4j.Logger; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author jburke + */ +public class GroupPropertyTest +{ + private static Logger log = Logger.getLogger(GroupPropertyTest.class); + + @Test + public void simpleGroupPropertyTest() throws Exception + { + GroupProperty gp1 = new GroupProperty("key", "value", false); + + assertEquals("key", gp1.getKey()); + assertEquals("value", gp1.getValue()); + assertEquals(false, gp1.isReadOnly()); + + GroupProperty gp2 = gp1; + assertEquals(gp1.hashCode(), gp2.hashCode()); + assertEquals(gp1, gp2); + assertTrue(gp1 == gp2); + + // test toString + System.out.println(gp1); + } + + @Test + public void exceptionTests() + { + boolean thrown = false; + try + { + new GroupProperty(null, "value", true); + } + catch(IllegalArgumentException e) + { + thrown = true; + } + assertTrue(thrown); + + + thrown = false; + try + { + new GroupProperty("key", null, true); + } + catch(IllegalArgumentException e) + { + thrown = true; + } + assertTrue(thrown); + } + +} diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/GroupReaderWriterTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/GroupReaderWriterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c54f6ee56d0787551e5c3fb7c45a1fad85b67523 --- /dev/null +++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/GroupReaderWriterTest.java @@ -0,0 +1,188 @@ +/* + ************************************************************************ + ******************* 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; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.security.Principal; +import java.util.Date; + +import javax.security.auth.x500.X500Principal; + +import org.apache.log4j.Logger; +import org.junit.Test; + +import ca.nrc.cadc.auth.HttpPrincipal; +import ca.nrc.cadc.auth.OpenIdPrincipal; +import static org.junit.Assert.assertTrue; + +/** + * + * @author jburke + */ +public class GroupReaderWriterTest +{ + private static Logger log = Logger.getLogger(GroupReaderWriterTest.class); + + @Test + public void testReaderExceptions() + throws Exception + { + try + { + String s = null; + Group g = GroupReader.read(s); + fail("null String should throw IllegalArgumentException"); + } + catch (IllegalArgumentException e) {} + + try + { + InputStream in = null; + Group g = GroupReader.read(in); + fail("null InputStream should throw IOException"); + } + catch (IOException e) {} + + try + { + Reader r = null; + Group g = GroupReader.read(r); + fail("null element should throw ReaderException"); + } + catch (IllegalArgumentException e) {} + } + + @Test + public void testWriterExceptions() + throws Exception + { + try + { + GroupWriter.write(null, new StringBuilder()); + fail("null Group should throw WriterException"); + } + catch (WriterException e) {} + } + + @Test + public void testMinimalReadWrite() + throws Exception + { + Group expected = new Group("groupID", null); + + StringBuilder xml = new StringBuilder(); + GroupWriter.write(expected, xml); + assertFalse(xml.toString().isEmpty()); + + Group actual = GroupReader.read(xml.toString()); + assertNotNull(actual); + assertEquals(expected, actual); + } + + @Test + public void testMaximalReadWrite() + throws Exception + { + Group expected = new Group("groupID", new User<Principal>(new HttpPrincipal("foo"))); + expected.description = "description"; + expected.lastModified = new Date(); + expected.properties.add(new GroupProperty("key", "value", 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 xml = new StringBuilder(); + GroupWriter.write(expected, xml); + assertFalse(xml.toString().isEmpty()); + + Group actual = GroupReader.read(xml.toString()); + assertNotNull(actual); + assertEquals(expected, actual); + assertEquals(expected.description, actual.description); + assertEquals(expected.lastModified, actual.lastModified); + assertEquals(expected.getProperties(), actual.getProperties()); + assertEquals(expected.getGroupMembers(), actual.getGroupMembers()); + assertEquals(expected.getUserMembers(), actual.getUserMembers()); + } + +} diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/GroupTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/GroupTest.java index 3e48c9a0c5cb5a5446d4645d7470db1951d7b37c..6451d53418baf3c5fa1099b97b738c508f27b70b 100644 --- a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/GroupTest.java +++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/GroupTest.java @@ -1,44 +1,80 @@ /* ************************************************************************ - **** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** + ******************* CANADIAN ASTRONOMY DATA CENTRE ******************* + ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** * - * (c) 2014. (c) 2014. - * National Research Council Conseil national de recherches - * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 - * All rights reserved Tous droits reserves + * (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 denie toute garantie - * expressed, implied, or statu- enoncee, implicite ou legale, - * tory, of any kind with respect de quelque nature que se soit, - * to the software, including concernant le logiciel, y com- - * without limitation any war- pris sans restriction toute - * ranty of merchantability or garantie de valeur marchande - * fitness for a particular pur- ou de pertinence pour un usage - * pose. NRC shall not be liable particulier. Le CNRC ne - * in any event for any damages, pourra en aucun cas etre tenu - * whether direct or indirect, responsable de tout dommage, - * special or general, consequen- direct ou indirect, particul- - * tial or incidental, arising ier ou general, accessoire ou - * from the use of the software. fortuit, resultant de l'utili- - * sation du logiciel. + * 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 $ * - * @author adriand - * - * @version $Revision: $ - * - * - **** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** ************************************************************************ */ - - - package ca.nrc.cadc.ac; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + import org.apache.log4j.Logger; import org.junit.Test; -import static org.junit.Assert.*; import ca.nrc.cadc.auth.HttpPrincipal; @@ -49,55 +85,54 @@ public class GroupTest @Test public void simpleGroupTest() throws Exception { + Group group1 = new Group("TestGroup"); + Group group2 = group1; + assertEquals(group1.hashCode(), group2.hashCode()); + assertEquals(group1, group2); + assertTrue(group1 == group2); User<HttpPrincipal> owner = new User<HttpPrincipal>(new HttpPrincipal("owner")); - Group group1 = new Group("TestGroup", owner); + Group group3 = new Group("TestGroup", owner); User<HttpPrincipal> user = new User<HttpPrincipal>(new HttpPrincipal("user")); - group1.getUserMembers().add(user); - assertEquals(1, group1.getUserMembers().size()); + group3.getUserMembers().add(user); + assertEquals(1, group3.getUserMembers().size()); - Group group2 = group1; - assertEquals(group1.hashCode(), group2.hashCode()); - assertEquals(group1, group2); - assertTrue(group1 == group2); + Group group4 = group3; + assertEquals(group3.hashCode(), group4.hashCode()); + assertEquals(group3, group4); + assertTrue(group3 == group4); - group2 = new Group("TestGroup", owner); - assertEquals(group1.hashCode(), group2.hashCode()); - assertEquals(group1,group2); + group4 = new Group("TestGroup", owner); + assertEquals(group3.hashCode(), group4.hashCode()); + assertEquals(group3,group4); - group2.getUserMembers().add(user); - assertEquals(group1.hashCode(), group2.hashCode()); - assertEquals(group1,group2); + group4.getUserMembers().add(user); + assertEquals(group3.hashCode(), group4.hashCode()); + assertEquals(group3,group4); - group1.getGroupMembers().add(group2); - assertEquals(group1.hashCode(), group2.hashCode()); - assertEquals(group1,group2); + group3.getGroupMembers().add(group4); + assertEquals(group3.hashCode(), group4.hashCode()); + assertEquals(group3,group4); - group1.description = "Test group"; - assertEquals(group1.hashCode(), group2.hashCode()); - assertEquals(group1,group2); + group4.getUserAdmins().add(user); + assertEquals(group3.hashCode(), group4.hashCode()); + assertEquals(group3,group4); - // group read and write equality tests - group1.groupRead = group2; - assertEquals(group1.hashCode(), group2.hashCode()); - assertEquals(group1,group2); + group3.getGroupAdmins().add(group4); + assertEquals(group3.hashCode(), group4.hashCode()); + assertEquals(group3,group4); - // group write equality tests - group1.groupWrite = group2; - assertEquals(group1.hashCode(), group2.hashCode()); - assertEquals(group1,group2); - - group1.publicRead = true; - assertEquals(group1.hashCode(), group2.hashCode()); - assertEquals(group1,group2); + group3.description = "Test group"; + assertEquals(group3.hashCode(), group4.hashCode()); + assertEquals(group3,group4); - group2 = new Group("NewTestGroup-._~.", owner); - assertFalse(group1.hashCode() == group2.hashCode()); - assertFalse(group1.equals(group2)); + group4 = new Group("NewTestGroup-._~.", owner); + assertFalse(group3.hashCode() == group4.hashCode()); + assertFalse(group3.equals(group4)); // test toString - System.out.println(group1); + System.out.println(group3); } @Test @@ -119,10 +154,11 @@ public class GroupTest try { new Group("NewTestGroup", null); + thrown = true; } catch(IllegalArgumentException e) { - thrown = true; + fail("Owner can be null"); } assertTrue(thrown); @@ -160,4 +196,5 @@ public class GroupTest } assertTrue(thrown); } + } diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/GroupsReaderWriterTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/GroupsReaderWriterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..3a6d595ccca502e3a72dff9b814ea8d60fcf7f0c --- /dev/null +++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/GroupsReaderWriterTest.java @@ -0,0 +1,156 @@ +/* + ************************************************************************ + ******************* 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; + +import ca.nrc.cadc.auth.HttpPrincipal; +import ca.nrc.cadc.auth.OpenIdPrincipal; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import javax.security.auth.x500.X500Principal; +import org.apache.log4j.Logger; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; +import org.junit.Test; + +/** + * + * @author jburke + */ +public class GroupsReaderWriterTest +{ + private static Logger log = Logger.getLogger(GroupsReaderWriterTest.class); + + @Test + public void testReaderExceptions() + throws Exception + { + try + { + String s = null; + List<Group> g = GroupsReader.read(s); + fail("null String should throw IllegalArgumentException"); + } + catch (IllegalArgumentException e) {} + + try + { + InputStream in = null; + List<Group> g = GroupsReader.read(in); + fail("null InputStream should throw IOException"); + } + catch (IOException e) {} + + try + { + Reader r = null; + List<Group> g = GroupsReader.read(r); + fail("null element should throw ReaderException"); + } + catch (IllegalArgumentException e) {} + } + + @Test + public void testWriterExceptions() + throws Exception + { + try + { + GroupsWriter.write(null, new StringBuilder()); + fail("null Group should throw WriterException"); + } + catch (WriterException e) {} + } + + @Test + public void testMinimalReadWrite() + throws Exception + { + List<Group> expected = new ArrayList<Group>(); + expected.add(new Group("group1", null)); + expected.add(new Group("group2", null)); + + StringBuilder xml = new StringBuilder(); + GroupsWriter.write(expected, xml); + assertFalse(xml.toString().isEmpty()); + + List<Group> actual = GroupsReader.read(xml.toString()); + assertNotNull(actual); + assertEquals(expected.size(), actual.size()); + assertEquals(expected.get(0), actual.get(0)); + assertEquals(expected.get(1), actual.get(1)); + } + +} diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/IdentityReaderWriterTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/IdentityReaderWriterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..cabd9e945345acd6c2aa10aff8b78d5460980cf5 --- /dev/null +++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/IdentityReaderWriterTest.java @@ -0,0 +1,192 @@ +/* + ************************************************************************ + ******************* 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; + +import ca.nrc.cadc.auth.HttpPrincipal; +import ca.nrc.cadc.auth.NumericPrincipal; +import ca.nrc.cadc.auth.OpenIdPrincipal; +import java.security.Principal; +import javax.management.remote.JMXPrincipal; +import javax.security.auth.x500.X500Principal; +import org.apache.log4j.Logger; +import org.jdom2.Element; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author jburke + */ +public class IdentityReaderWriterTest +{ + private static Logger log = Logger.getLogger(IdentityReaderWriterTest.class); + + @Test + public void testReaderExceptions() + throws Exception + { + Element element = null; + try + { + Principal p = IdentityReader.read(element); + fail("null element should throw ReaderException"); + } + catch (ReaderException e) {} + + element = new Element("foo"); + try + { + Principal p = IdentityReader.read(element); + fail("element not named 'identity' should throw ReaderException"); + } + catch (ReaderException e) {} + + element = new Element("identity"); + try + { + Principal p = IdentityReader.read(element); + fail("element without 'type' attribute should throw ReaderException"); + } + catch (ReaderException e) {} + + element.setAttribute("type", "foo"); + try + { + Principal p = IdentityReader.read(element); + fail("element with unknown 'type' attribute should throw ReaderException"); + } + catch (ReaderException e) {} + } + + @Test + public void testWriterExceptions() + throws Exception + { + try + { + Element element = IdentityWriter.write(null); + fail("null Identity should throw WriterException"); + } + catch (WriterException e) {} + + Principal p = new JMXPrincipal("foo"); + try + { + Element element = IdentityWriter.write(p); + fail("Unsupported Principal type should throw IllegalArgumentException"); + } + catch (IllegalArgumentException e) {} + } + + @Test + public void testReadWrite() + throws Exception + { + // X500 + Principal expected = new X500Principal("cn=foo,o=bar"); + Element element = IdentityWriter.write(expected); + assertNotNull(element); + + Principal actual = IdentityReader.read(element); + assertNotNull(actual); + + assertEquals(expected, actual); + + // UID + expected = new NumericPrincipal(123l); + element = IdentityWriter.write(expected); + assertNotNull(element); + + actual = IdentityReader.read(element); + assertNotNull(actual); + + assertEquals(expected, actual); + + // OpenID + expected = new OpenIdPrincipal("bar"); + element = IdentityWriter.write(expected); + assertNotNull(element); + + actual = IdentityReader.read(element); + assertNotNull(actual); + + assertEquals(expected, actual); + + // HTTP + expected = new HttpPrincipal("baz"); + element = IdentityWriter.write(expected); + assertNotNull(element); + + actual = IdentityReader.read(element); + assertNotNull(actual); + + assertEquals(expected, actual); + } + +} diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/PersonalDetailsTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/PersonalDetailsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..48e99a6f17b87201d88b06e737072e192fd956ac --- /dev/null +++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/PersonalDetailsTest.java @@ -0,0 +1,130 @@ +/* + ************************************************************************ + ******************* 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; + +import org.apache.log4j.Logger; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author jburke + */ +public class PersonalDetailsTest +{ + private static Logger log = Logger.getLogger(PersonalDetailsTest.class); + + @Test + public void simplePersonalDetailsTest() throws Exception + { + PersonalDetails pd1 = new PersonalDetails("firstname", "lastname"); + + assertEquals("firstname", pd1.getFirstName()); + assertEquals("lastname", pd1.getLastName()); + + PersonalDetails pd2 = pd1; + assertEquals(pd1.hashCode(), pd2.hashCode()); + assertEquals(pd1, pd2); + assertTrue(pd1 == pd2); + + // test toString + System.out.println(pd1); + } + + @Test + public void exceptionTests() + { + boolean thrown = false; + try + { + new PersonalDetails(null, "lastname"); + } + catch(IllegalArgumentException e) + { + thrown = true; + } + assertTrue(thrown); + + + thrown = false; + try + { + new PersonalDetails("firstname", null); + } + catch(IllegalArgumentException e) + { + thrown = true; + } + assertTrue(thrown); + } + +} diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/PosixDetailsTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/PosixDetailsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ba5ecc6a1918edfc8f64d683b6a721e61fd1241b --- /dev/null +++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/PosixDetailsTest.java @@ -0,0 +1,116 @@ +/* + ************************************************************************ + ******************* 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; + +import org.apache.log4j.Logger; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author jburke + */ +public class PosixDetailsTest +{ + private static Logger log = Logger.getLogger(PosixDetailsTest.class); + + @Test + public void simplePosixDetailsTest() throws Exception + { + PosixDetails pd1 = new PosixDetails(1l, 2l, "/dev/null"); + + assertEquals(1l, pd1.getUid()); + assertEquals(2l, pd1.getGid()); + assertEquals("/dev/null", pd1.getHomeDirectory()); + + PosixDetails pd2 = pd1; + assertEquals(pd1.hashCode(), pd2.hashCode()); + assertEquals(pd1, pd2); + assertTrue(pd1 == pd2); + + // test toString + System.out.println(pd1); + } + + @Test + public void exceptionTests() + { + boolean thrown = false; + try + { + new PosixDetails(1l, 2l, null); + } + catch(IllegalArgumentException e) + { + thrown = true; + } + assertTrue(thrown); + } + +} diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/RoleTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/RoleTest.java new file mode 100644 index 0000000000000000000000000000000000000000..2c6af1400d8ba1dd6d29e52d08496b87dbb33024 --- /dev/null +++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/RoleTest.java @@ -0,0 +1,153 @@ +/* + ************************************************************************ + ******************* 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; + +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 static org.junit.Assert.*; + +/** + * + * @author jburke + */ +public class RoleTest +{ + private final static Logger log = Logger.getLogger(RoleTest.class); + + @BeforeClass + public static void setUpClass() + { + Log4jInit.setLevel("ca.nrc.cadc.ac", Level.INFO); + } + /** + * Test of values method, of class Role. + */ + @Test + public void testValues() + { + Role[] expResult = new Role[] { Role.OWNER, Role.MEMBER, Role.ADMIN }; + Role[] result = Role.values(); + assertArrayEquals(expResult, result); + } + + /** + * Test of valueOf method, of class Role. + */ + @Test + public void testValueOf() + { + assertEquals(Role.OWNER, Role.valueOf("OWNER")); + assertEquals(Role.MEMBER, Role.valueOf("MEMBER")); + assertEquals(Role.ADMIN, Role.valueOf("ADMIN")); + } + + /** + * Test of toValue method, of class Role. + */ + @Test + public void testToValue() + { + try + { + Role.toValue("foo"); + fail("invalid value should throw IllegalArgumentException"); + } + catch (IllegalArgumentException ignore) {} + + assertEquals(Role.OWNER, Role.toValue("owner")); + assertEquals(Role.MEMBER, Role.toValue("member")); + assertEquals(Role.ADMIN, Role.toValue("admin")); + } + + /** + * Test of getValue method, of class Role. + */ + @Test + public void testGetValue() + { + assertEquals("owner", Role.OWNER.getValue()); + assertEquals("member", Role.MEMBER.getValue()); + assertEquals("admin", Role.ADMIN.getValue()); + } + + /** + * Test of checksum method, of class Role. + */ + @Test + public void testChecksum() + { + assertEquals("owner".hashCode(), Role.OWNER.checksum()); + assertEquals("member".hashCode(), Role.MEMBER.checksum()); + assertEquals("admin".hashCode(), Role.ADMIN.checksum()); + } + +} diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/UserDetailsReaderWriterTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/UserDetailsReaderWriterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..159333bdda86d33cb8938558c3dabff602ee1ecc --- /dev/null +++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/UserDetailsReaderWriterTest.java @@ -0,0 +1,175 @@ +/* + ************************************************************************ + ******************* 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; + +import ca.nrc.cadc.auth.HttpPrincipal; +import ca.nrc.cadc.auth.NumericPrincipal; +import ca.nrc.cadc.auth.OpenIdPrincipal; +import java.security.Principal; +import javax.management.remote.JMXPrincipal; +import javax.security.auth.x500.X500Principal; +import org.apache.log4j.Logger; +import org.jdom2.Element; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author jburke + */ +public class UserDetailsReaderWriterTest +{ + private static Logger log = Logger.getLogger(UserDetailsReaderWriterTest.class); + + @Test + public void testReaderExceptions() + throws Exception + { + Element element = null; + try + { + UserDetails ud = UserDetailsReader.read(element); + fail("null element should throw ReaderException"); + } + catch (ReaderException e) {} + + element = new Element("foo"); + try + { + UserDetails ud = UserDetailsReader.read(element); + fail("element not named 'userDetails' should throw ReaderException"); + } + catch (ReaderException e) {} + + element = new Element(UserDetails.NAME); + try + { + UserDetails ud = UserDetailsReader.read(element); + fail("element without 'type' attribute should throw ReaderException"); + } + catch (ReaderException e) {} + + element.setAttribute("type", "foo"); + try + { + UserDetails ud = UserDetailsReader.read(element); + fail("element with unknown 'type' attribute should throw ReaderException"); + } + catch (ReaderException e) {} + } + + @Test + public void testWriterExceptions() + throws Exception + { + try + { + Element element = UserDetailsWriter.write(null); + fail("null UserDetails should throw WriterException"); + } + catch (WriterException e) {} + } + + @Test + public void testReadWritePersonalDetails() + throws Exception + { + PersonalDetails expected = new PersonalDetails("firstname", "lastname"); + expected.address = "address"; + expected.city = "city"; + expected.country = "country"; + expected.email = "email"; + expected.institute = "institute"; + Element element = UserDetailsWriter.write(expected); + assertNotNull(element); + + PersonalDetails actual = (PersonalDetails) UserDetailsReader.read(element); + assertNotNull(actual); + assertEquals(expected, actual); + assertEquals(expected.address, actual.address); + assertEquals(expected.city, actual.city); + assertEquals(expected.country, actual.country); + assertEquals(expected.email, actual.email); + assertEquals(expected.institute, actual.institute); + } + + @Test + public void testReadWritePosixDetails() + throws Exception + { + UserDetails expected = new PosixDetails(123l, 456, "/dev/null"); + Element element = UserDetailsWriter.write(expected); + assertNotNull(element); + + UserDetails actual = UserDetailsReader.read(element); + assertNotNull(actual); + assertEquals(expected, actual); + } + +} diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/UserReaderWriterTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/UserReaderWriterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..5f4d3e8d31debc38a2add8a522553985260fd552 --- /dev/null +++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/UserReaderWriterTest.java @@ -0,0 +1,147 @@ +/* + ************************************************************************ + ******************* 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; + +import ca.nrc.cadc.auth.HttpPrincipal; +import ca.nrc.cadc.auth.NumericPrincipal; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.security.Principal; +import org.apache.log4j.Logger; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author jburke + */ +public class UserReaderWriterTest +{ + private static Logger log = Logger.getLogger(UserReaderWriterTest.class); + + @Test + public void testReaderExceptions() + throws Exception + { + try + { + String s = null; + User<? extends Principal> u = UserReader.read(s); + fail("null String should throw IllegalArgumentException"); + } + catch (IllegalArgumentException e) {} + + try + { + InputStream in = null; + User<? extends Principal> u = UserReader.read(in); + fail("null InputStream should throw IOException"); + } + catch (IOException e) {} + + try + { + Reader r = null; + User<? extends Principal> u = UserReader.read(r); + fail("null Reader should throw IllegalArgumentException"); + } + catch (IllegalArgumentException e) {} + } + + @Test + public void testWriterExceptions() + throws Exception + { + try + { + UserWriter.write(null, new StringBuilder()); + fail("null User should throw WriterException"); + } + catch (WriterException e) {} + } + + @Test + public void testReadWrite() + throws Exception + { + User<? extends Principal> expected = new User<Principal>(new HttpPrincipal("foo")); + expected.getIdentities().add(new NumericPrincipal(123l)); + expected.details.add(new PersonalDetails("firstname", "lastname")); + + StringBuilder xml = new StringBuilder(); + UserWriter.write(expected, xml); + assertFalse(xml.toString().isEmpty()); + + User<? extends Principal> actual = UserReader.read(xml.toString()); + assertNotNull(actual); + assertEquals(expected, actual); + } + +} diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/UserTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/UserTest.java index 0fce989ccfd154bcb79f29134780d0d486ec9a21..78b636ffbec33f7ca5276c9948b755900b1bca7f 100644 --- a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/UserTest.java +++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/UserTest.java @@ -1,42 +1,73 @@ /* ************************************************************************ - **** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** + ******************* CANADIAN ASTRONOMY DATA CENTRE ******************* + ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** * - * (c) 2014. (c) 2014. - * National Research Council Conseil national de recherches - * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 - * All rights reserved Tous droits reserves + * (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 denie toute garantie - * expressed, implied, or statu- enoncee, implicite ou legale, - * tory, of any kind with respect de quelque nature que se soit, - * to the software, including concernant le logiciel, y com- - * without limitation any war- pris sans restriction toute - * ranty of merchantability or garantie de valeur marchande - * fitness for a particular pur- ou de pertinence pour un usage - * pose. NRC shall not be liable particulier. Le CNRC ne - * in any event for any damages, pourra en aucun cas etre tenu - * whether direct or indirect, responsable de tout dommage, - * special or general, consequen- direct ou indirect, particul- - * tial or incidental, arising ier ou general, accessoire ou - * from the use of the software. fortuit, resultant de l'utili- - * sation du logiciel. + * 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 $ * - * @author adriand - * - * @version $Revision: $ - * - * - **** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** ************************************************************************ - */ + */package ca.nrc.cadc.ac; -package ca.nrc.cadc.ac; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import javax.security.auth.x500.X500Principal; @@ -65,8 +96,7 @@ public class UserTest assertEquals(user1, user2); assertEquals(user1.hashCode(), user2.hashCode()); - user1.details.add(new PersonalDetails("Joe", "Raymond", - "jr@email.com", "123 Street", "CADC", "Victoria", "CA")); + user1.details.add(new PersonalDetails("Joe", "Raymond")); assertEquals(user1, user2); assertEquals(user1.hashCode(), user2.hashCode()); @@ -78,7 +108,7 @@ public class UserTest assertFalse(user3.equals(user4)); assertFalse(user3.hashCode() == user4.hashCode()); - user1.getPrincipals().add(new X500Principal("cn=aaa,ou=ca")); + user1.getIdentities().add(new X500Principal("cn=aaa,ou=ca")); assertEquals(user1, user2); assertEquals(user1.hashCode(), user2.hashCode()); @@ -93,8 +123,7 @@ public class UserTest // visual test of toString System.out.println(user1); - System.out.println(new PersonalDetails("Joe", "Raymond", - "jr@email.com", "123 Street", "CADC", "Victoria", "CA")); + System.out.println(new PersonalDetails("Joe", "Raymond")); System.out.println(new PosixDetails(12, 23,"/home/myhome")); } @@ -116,8 +145,7 @@ public class UserTest thrown = false; try { - new PersonalDetails(null, "Raymond", - "jr@email.com", "123 Street", "CADC", "Victoria", "CA"); + new PersonalDetails(null, "Raymond"); } catch(IllegalArgumentException e) { @@ -128,8 +156,7 @@ public class UserTest thrown = false; try { - new PersonalDetails("Joe", null, - "jr@email.com", "123 Street", "CADC", "Victoria", "CA"); + new PersonalDetails("Joe", null); } catch(IllegalArgumentException e) { @@ -137,65 +164,6 @@ public class UserTest } assertTrue(thrown); - thrown = false; - try - { - new PersonalDetails("Joe", "Raymond", - null, "123 Street", "CADC", "Victoria", "CA"); - } - catch(IllegalArgumentException e) - { - thrown = true; - } - assertTrue(thrown); - - thrown = false; - try - { - new PersonalDetails("Joe", "Raymond", - "jr@email.com", null, "CADC", "Victoria", "CA"); - } - catch(IllegalArgumentException e) - { - thrown = true; - } - assertTrue(thrown); - - thrown = false; - try - { - new PersonalDetails("Joe", "Raymond", - "jr@email.com", "123 Street", null, "Victoria", "CA"); - } - catch(IllegalArgumentException e) - { - thrown = true; - } - assertTrue(thrown); - - thrown = false; - try - { - new PersonalDetails("Joe", "Raymond", - "jr@email.com", "123 Street", "CADC", null, "CA"); - } - catch(IllegalArgumentException e) - { - thrown = true; - } - assertTrue(thrown); - - thrown = false; - try - { - new PersonalDetails("Joe", "Raymond", - "jr@email.com", "123 Street", "CADC", "Victoria", null); - } - catch(IllegalArgumentException e) - { - thrown = true; - } - assertTrue(thrown); thrown = false; try @@ -230,4 +198,19 @@ public class UserTest } assertTrue(thrown); } + + @Test + public void getDetails() throws Exception + { + final User<HttpPrincipal> testSubject = + new User<HttpPrincipal>(new HttpPrincipal("test")); + + testSubject.details.add(new PersonalDetails("First", "Last")); + + assertTrue("Should be empty.", + testSubject.getDetails(PosixDetails.class).isEmpty()); + + assertEquals("Should be 1.", 1, + testSubject.getDetails(PersonalDetails.class).size()); + } } diff --git a/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/client/GMSClientTest.java b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/client/GMSClientTest.java new file mode 100644 index 0000000000000000000000000000000000000000..3025fb37678ac4fc3d0f464e6b320f9ced4ebcaf --- /dev/null +++ b/projects/cadcAccessControl/test/src/ca/nrc/cadc/ac/client/GMSClientTest.java @@ -0,0 +1,245 @@ +/* + ************************************************************************ + ******************* 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.client; + +import java.net.URI; +import java.net.URL; +import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.List; + +import javax.security.auth.Subject; + +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.junit.Assert; +import org.junit.Test; + +import ca.nrc.cadc.ac.AC; +import ca.nrc.cadc.ac.Group; +import ca.nrc.cadc.ac.Role; +import ca.nrc.cadc.auth.HttpPrincipal; +import ca.nrc.cadc.reg.client.RegistryClient; +import ca.nrc.cadc.util.Log4jInit; + +public class GMSClientTest +{ + + private static final Logger log = Logger.getLogger(GMSClientTest.class); + + public GMSClientTest() + { + Log4jInit.setLevel("ca.nrc.cadc.ac", Level.DEBUG); + } + + @Test + public void testUserIsSubject() + { + try + { + Subject subject = new Subject(); + HttpPrincipal userID = new HttpPrincipal("test"); + HttpPrincipal userID2 = new HttpPrincipal("test2"); + subject.getPrincipals().add(userID); + + RegistryClient regClient = new RegistryClient(); + URL baseURL = regClient.getServiceURL(new URI(AC.GMS_SERVICE_URI), + "https"); + GMSClient client = new GMSClient(baseURL.toString()); + + Assert.assertFalse(client.userIsSubject(null, null)); + Assert.assertFalse(client.userIsSubject(userID, null)); + Assert.assertFalse(client.userIsSubject(null, subject)); + Assert.assertFalse(client.userIsSubject(userID2, subject)); + Assert.assertTrue(client.userIsSubject(userID, subject)); + + HttpPrincipal userID3 = new HttpPrincipal("test3"); + subject.getPrincipals().add(userID3); + + Assert.assertTrue(client.userIsSubject(userID, subject)); + Assert.assertFalse(client.userIsSubject(userID2, subject)); + Assert.assertTrue(client.userIsSubject(userID3, subject)); + } + catch (Throwable t) + { + log.error("Unexpected exception", t); + Assert.fail("Unexpected exception: " + t.getMessage()); + } + } + + @Test + public void testGroupCaching() + { + try + { + Subject subject = new Subject(); + final HttpPrincipal test1UserID = new HttpPrincipal("test"); + subject.getPrincipals().add(test1UserID); + + RegistryClient regClient = new RegistryClient(); + URL baseURL = regClient.getServiceURL(new URI(AC.GMS_SERVICE_URI), + "https"); + final GMSClient client = new GMSClient(baseURL.toString()); + + Subject.doAs(subject, new PrivilegedExceptionAction<Object>() + { + @Override + public Object run() throws Exception + { + + List<Group> initial = client.getCachedGroups(test1UserID, Role.MEMBER); + Assert.assertNull("Cache should be null", initial); + + List<Group> expected = new ArrayList<Group>(); + Group group1 = new Group("1"); + Group group2 = new Group("2"); + expected.add(group1); + expected.add(group2); + + client.setCachedGroups(test1UserID, expected, Role.MEMBER); + + List<Group> actual = client.getCachedGroups(test1UserID, Role.MEMBER); + Assert.assertEquals("Wrong cached groups", expected, actual); + + // check against another role + actual = client.getCachedGroups(test1UserID, Role.OWNER); + Assert.assertNull("Cache should be null", actual); + + // check against another userid + final HttpPrincipal anotherUserID = new HttpPrincipal("anotheruser"); + actual = client.getCachedGroups(anotherUserID, Role.MEMBER); + Assert.assertNull("Cache should be null", actual); + + return null; + } + }); + + subject = new Subject(); + final HttpPrincipal test2UserID = new HttpPrincipal("test2"); + subject.getPrincipals().add(test2UserID); + + // do the same but as a different user + Subject.doAs(subject, new PrivilegedExceptionAction<Object>() + { + @Override + public Object run() throws Exception + { + + List<Group> initial = client.getCachedGroups(test2UserID, Role.MEMBER); + Assert.assertNull("Cache should be null", initial); + + List<Group> expected = new ArrayList<Group>(); + Group group1 = new Group("1"); + Group group2 = new Group("2"); + expected.add(group1); + expected.add(group2); + + client.setCachedGroups(test2UserID, expected, Role.MEMBER); + + List<Group> actual = client.getCachedGroups(test2UserID, Role.MEMBER); + Assert.assertEquals("Wrong cached groups", expected, actual); + + // check against another role + actual = client.getCachedGroups(test2UserID, Role.OWNER); + Assert.assertNull("Cache should be null", actual); + + // check against another userid + final HttpPrincipal anotherUserID = new HttpPrincipal("anotheruser"); + actual = client.getCachedGroups(anotherUserID, Role.MEMBER); + Assert.assertNull("Cache should be null", actual); + + return null; + } + }); + + // do the same without a subject + + List<Group> initial = client.getCachedGroups(test1UserID, Role.MEMBER); + Assert.assertNull("Cache should be null", initial); + + List<Group> newgroups = new ArrayList<Group>(); + Group group1 = new Group("1"); + Group group2 = new Group("2"); + newgroups.add(group1); + newgroups.add(group2); + + client.setCachedGroups(test1UserID, newgroups, Role.MEMBER); + + List<Group> actual = client.getCachedGroups(test1UserID, Role.MEMBER); + Assert.assertNull("Cache should still be null", actual); + } + catch (Throwable t) + { + log.error("Unexpected exception", t); + Assert.fail("Unexpected exception: " + t.getMessage()); + } + } + +}