/** * '$RCSfile$' * Copyright: 2004 Regents of the University of California and the * National Center for Ecological Analysis and Synthesis * Purpose: To test the Access Controls in metacat by JUnit * * '$Author: daigle $' * '$Date: 2009-08-14 14:26:08 -0700 (Fri, 14 Aug 2009) $' * '$Revision: 5027 $' * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package edu.ucsb.nceas.metacattest; import java.io.IOException; import java.io.StringReader; import java.util.Vector; import junit.framework.Test; import junit.framework.TestSuite; import edu.ucsb.nceas.MCTestCase; import edu.ucsb.nceas.metacat.accesscontrol.AccessControlException; import edu.ucsb.nceas.metacat.accesscontrol.AccessControlList; import edu.ucsb.nceas.metacat.client.InsufficientKarmaException; import edu.ucsb.nceas.metacat.client.MetacatAuthException; import edu.ucsb.nceas.metacat.client.MetacatException; import edu.ucsb.nceas.metacat.client.MetacatInaccessibleException; import edu.ucsb.nceas.metacat.properties.PropertyService; import edu.ucsb.nceas.utilities.PropertyNotFoundException; import edu.ucsb.nceas.utilities.access.DocInfoHandler; import edu.ucsb.nceas.utilities.access.XMLAccessDAO; import edu.ucsb.nceas.utilities.access.AccessControlInterface; import org.xml.sax.ContentHandler; import org.xml.sax.ErrorHandler; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.XMLReaderFactory; /** * A JUnit test for testing Access Control API in Metacat. Note that this is different * than the Access Control test. That test is more concerned with making sure different * combinations of access rules act appropriately. This test is more concerned with the * funtioning of the API itself. */ public class AccessAPITest extends MCTestCase { /** * Constructor to build the test * * @param name * the name of the test method */ public AccessAPITest(String name) { super(name); } /** * Establish a testing framework by initializing appropriate objects */ public void setUp() throws Exception { metacatConnectionNeeded = true; super.setUp(); } /** * Release any objects after tests are complete */ public void tearDown() { } /** * Create a suite of tests to be run together */ public static Test suite() { TestSuite suite = new TestSuite(); suite.addTest(new AccessAPITest("initialize")); // Test basic functions suite.addTest(new AccessAPITest("testSetSingleAccess")); suite.addTest(new AccessAPITest("testSetBlockAccess")); return suite; } /** * Run an initial test that always passes to check that the test harness is * working. */ public void initialize() { assertTrue(1 == 1); } /** * Test adding access records for single principals. */ public void testSetSingleAccess() { String principal = null; Vector accessDAOList = null; Vector realAccessDAOList = null; XMLAccessDAO accessDAO = null; String accessXML = null; try { debug("AccessAPITest.testSetSingleAccess Running"); m.login(username, password); // insert a document for us to test with String docId = generateDocumentId() + ".1"; String testDoc = getTestDocFromFile(testdatadir + "accessBlockTestFile1.xml"); // debug("test doc: " + testDoc); insertDocumentId(docId, testDoc, SUCCESS, false); // test inserting a single access record with allowFirst permission order and allow read // access. We expect this to succeed. debug("AccessAPITest.testSetSingleAccess - Test 1, add user allowFirst allow read access"); principal = "uid=test30,o=NCEAS,dc=ecoinformatics,dc=org"; setSingleAccess(docId, principal, "READ", AccessControlInterface.ALLOW, AccessControlInterface.ALLOWFIRST, true); accessDAOList = new Vector(); accessDAO = new XMLAccessDAO(); accessDAO.setGuid(docId); accessDAO.setPrincipalName(principal); accessDAO.setPermission(new Long(AccessControlInterface.READ)); accessDAO.setPermType(AccessControlInterface.ALLOW); accessDAO.setPermOrder(AccessControlInterface.ALLOWFIRST); accessDAOList.add(accessDAO); // get the access control for this doc id from metacat and make sure this // access record is in that list. accessXML = m.getAccessControl(docId); realAccessDAOList = getAccessDAOList(docId, accessXML); compareAccessDAOs(realAccessDAOList, accessDAOList, false); // test inserting a single access record with denyFirst permission order and allow read // access. We expect this to fail since a single doc cannot have multiple permission orders. debug("AccessAPITest.testSetSingleAccess - Test 2, add user denyFirst allow read/write access"); principal = "uid=test31,o=NCEAS,dc=ecoinformatics,dc=org"; setSingleAccess(docId, principal, Integer.toString(AccessControlInterface.READ | AccessControlInterface.WRITE), AccessControlInterface.ALLOW, AccessControlInterface.DENYFIRST, false); } catch (AccessControlException ace) { fail("AccessAPITest.testSetSingleAccess - Access Control error: " + ace.getMessage()); } catch (IOException ioe) { fail("AccessAPITest.testSetSingleAccess - I/O error: " + ioe.getMessage()); } catch (MetacatAuthException mae) { fail("AccessAPITest.testSetSingleAccess - Metacat authentication error: " + mae.getMessage()); } catch (MetacatException me) { fail("AccessAPITest.testSetSingleAccess - Metacat error: " + me.getMessage()); } catch (InsufficientKarmaException ike) { fail("AccessAPITest.testSetSingleAccess - Insufficient karma error: " + ike.getMessage()); } catch (MetacatInaccessibleException mie) { fail("AccessAPITest.testSetSingleAccess - Metacat Inaccessible Error: " + mie.getMessage()); } } /** * Test setting a block of access for a document. Each call should replace the access for that * document. */ public void testSetBlockAccess() { String accessBlockXML = null; String accessXML = null; Vector realAccessDAOList = null; Vector accessBlockDAOList = null; try { debug("AccessAPITest.testSetBlockAccess - Running"); // log in m.login(username, password); // insert a document for us to test with String docId = generateDocumentId() + ".1"; String testDoc = getTestDocFromFile(testdatadir + "accessBlockTestFile1.xml"); // debug("test doc: " + testDoc); insertDocumentId(docId, testDoc, SUCCESS, false); // replace access for doc using the access section in accessBlock1.xml, // then test that the access was updated and that is the only access // for the doc debug("AccessAPITest.testSetBlockAccess - Test 1 using accessBlock1.xml"); accessBlockXML = getTestDocFromFile(testdatadir + "accessBlock1.xml"); setBlockAccess(docId, accessBlockXML, true); accessXML = m.getAccessControl(docId); realAccessDAOList = getAccessDAOList(docId, accessXML); accessBlockDAOList = getAccessDAOList(docId, accessBlockXML); debugAccessDAOList(accessBlockDAOList); compareAccessDAOs(realAccessDAOList, accessBlockDAOList, true); // replace access for doc using the access section in accessBlock2.xml, // then test that the access was updated and that is the only access // for the doc debug("AccessAPITest.testSetBlockAccess - Test 2 using accessBlock2.xml"); accessBlockXML = getTestDocFromFile(testdatadir + "accessBlock2.xml"); setBlockAccess(docId, accessBlockXML, true); accessXML = m.getAccessControl(docId); realAccessDAOList = getAccessDAOList(docId, accessXML); accessBlockDAOList = getAccessDAOList(docId, accessBlockXML); debugAccessDAOList(accessBlockDAOList); compareAccessDAOs(realAccessDAOList, accessBlockDAOList, true); // replace access for doc using the access section in accessBlock3.xml, // then test that the access was updated and that is the only access // for the doc debug("AccessAPITest.testSetBlockAccess - Test 3 using accessBlock3.xml"); accessBlockXML = getTestDocFromFile(testdatadir + "accessBlock3.xml"); setBlockAccess(docId, accessBlockXML, true); accessXML = m.getAccessControl(docId); realAccessDAOList = getAccessDAOList(docId, accessXML); accessBlockDAOList = getAccessDAOList(docId, accessBlockXML); debugAccessDAOList(accessBlockDAOList); compareAccessDAOs(realAccessDAOList, accessBlockDAOList, true); // replace access for doc using the access section in accessBlock4.xml, // then test that the access was updated and that is the only access // for the doc debug("AccessAPITest.testSetBlockAccess - Test 4 using accessBlock4.xml"); accessBlockXML = getTestDocFromFile(testdatadir + "accessBlock4.xml"); setBlockAccess(docId, accessBlockXML, true); accessXML = m.getAccessControl(docId); realAccessDAOList = getAccessDAOList(docId, accessXML); accessBlockDAOList = getAccessDAOList(docId, accessBlockXML); debugAccessDAOList(accessBlockDAOList); compareAccessDAOs(realAccessDAOList, accessBlockDAOList, true); // replace access for doc using the access section in accessBlock5.xml, // then test that the access was updated and that is the only access // for the doc debug("AccessAPITest.testSetBlockAccess - Test 5 using accessBlock5.xml"); accessBlockXML = getTestDocFromFile(testdatadir + "accessBlock5.xml"); setBlockAccess(docId, accessBlockXML, true); accessXML = m.getAccessControl(docId); realAccessDAOList = getAccessDAOList(docId, accessXML); accessBlockDAOList = getAccessDAOList(docId, accessBlockXML); debugAccessDAOList(accessBlockDAOList); compareAccessDAOs(realAccessDAOList, accessBlockDAOList, true); // replace access for doc using the access section in accessBlock6.xml, // then test that the access was updated and that is the only access // for the doc debug("AccessAPITest.testSetBlockAccess - Test 6 using accessBlock6.xml"); accessBlockXML = getTestDocFromFile(testdatadir + "accessBlock6.xml"); setBlockAccess(docId, accessBlockXML, true); accessXML = m.getAccessControl(docId); realAccessDAOList = getAccessDAOList(docId, accessXML); accessBlockDAOList = getAccessDAOList(docId, accessBlockXML); debugAccessDAOList(accessBlockDAOList); compareAccessDAOs(realAccessDAOList, accessBlockDAOList, true); // replace access for doc using the access section in accessBlock7.xml, // then test that the access was updated and that is the only access // for the doc debug("AccessAPITest.testSetBlockAccess - Test 7 using accessBlock7.xml"); accessBlockXML = getTestDocFromFile(testdatadir + "accessBlock7.xml"); setBlockAccess(docId, accessBlockXML, true); accessXML = m.getAccessControl(docId); realAccessDAOList = getAccessDAOList(docId, accessXML); accessBlockDAOList = getAccessDAOList(docId, accessBlockXML); debugAccessDAOList(accessBlockDAOList); compareAccessDAOs(realAccessDAOList, accessBlockDAOList, true); // replace access for doc using the access section in accessBlock8.xml, // then test that the access was updated and that is the only access // for the doc debug("AccessAPITest.testSetBlockAccess - Test 8 using accessBlock8.xml"); accessBlockXML = getTestDocFromFile(testdatadir + "accessBlock8.xml"); setBlockAccess(docId, accessBlockXML, true); accessXML = m.getAccessControl(docId); realAccessDAOList = getAccessDAOList(docId, accessXML); accessBlockDAOList = getAccessDAOList(docId, accessBlockXML); debugAccessDAOList(accessBlockDAOList); compareAccessDAOs(realAccessDAOList, accessBlockDAOList, true); // replace access for doc using the access section in accessBlock9.xml, // then test that the access was updated and that is the only access // for the doc debug("AccessAPITest.testSetBlockAccess - Test 9 using accessBlock9.xml"); accessBlockXML = getTestDocFromFile(testdatadir + "accessBlock9.xml"); setBlockAccess(docId, accessBlockXML, true); accessXML = m.getAccessControl(docId); realAccessDAOList = getAccessDAOList(docId, accessXML); accessBlockDAOList = getAccessDAOList(docId, accessBlockXML); debugAccessDAOList(accessBlockDAOList); compareAccessDAOs(realAccessDAOList, accessBlockDAOList, true); } catch (AccessControlException ace) { fail("AccessAPITest.testSetBlockAccess - Access Control error: " + ace.getMessage()); } catch (IOException ioe) { fail("AccessAPITest.testSetBlockAccess - I/O error: " + ioe.getMessage()); } catch (MetacatAuthException mae) { fail("AccessAPITest.testSetBlockAccess - Metacat authentication error: " + mae.getMessage()); } catch (MetacatException me) { fail("AccessAPITest.testSetBlockAccess - Metacat error: " + me.getMessage()); } catch (InsufficientKarmaException ike) { fail("AccessAPITest.testSetBlockAccess - Metacat error: " + ike.getMessage()); } catch (MetacatInaccessibleException mie) { fail("AccessAPITest.testSetBlockAccess - Metacat Inaccessible Error: " + mie.getMessage()); } } /** * Insert a single row of access for a document. * * @param docId * the id of the document to update * @param principal * the principal credentails * @param permission * the permission * @param permType * the permission type * @param permOrder * the permission order * @param successExpected * if true, we expect the insert to succeed, otherwise, we expect * it to fail * @return the metacat response xml */ private String setSingleAccess(String docId, String principal, String permission, String permType, String permOrder, boolean successExpected) { debug("AccessAPITest.setSingleAccess - docid: " + docId + ", prinicpal: " + principal + ", permission: " + permission + ", permType: " + permType + ", permOrder: " + permOrder + ", errorExpected: " + successExpected); String response = null; try { // set the access using metacat client response = m.setAccess(docId, principal, permission, permType, permOrder); debug("AccessAPITest.setSingleAccess - response: " + response); if (successExpected) { assertTrue(response, (response.indexOf("") != -1)); } else { assertTrue(response, (response.indexOf("") == -1)); } } catch (MetacatInaccessibleException mie) { fail("AccessAPITest.setSingleAccess - Metacat inaccessible: " + mie.getMessage()); } catch (InsufficientKarmaException ike) { } catch (MetacatException me) { if (successExpected) { fail("AccessAPITest.setSingleAccess - Metacat error: " + me.getMessage()); } else { debug("AccessAPITest.setSingleAccess - Expected Metacat error: " + me.getMessage()); } } catch (Exception e) { fail("AccessAPITest.setSingleAccess - General error: " + e.getMessage()); } return response; } /** * Replace a block of access * * @param docId * the id of the doc we want to update * @param accessBlockXML * the access xml section * @param successExpected * if true, we expect the insert to succeed, otherwise, we expect * it to fail * @return the metacat response xml */ private String setBlockAccess(String docId, String accessBlockXML, boolean successExpected) { debug("AccessAPITest.setBlockAccess - docid: " + docId + ", accessBlockXML: " + accessBlockXML + ", errorExpected: " + successExpected); String response = null; try { // set the access using metacat client response = m.setAccess(docId, accessBlockXML); debug("AccessAPITest.setBlockAccess - response: " + response); if (successExpected) { assertTrue(response, (response.indexOf("") != -1)); } else { assertTrue(response, (response.indexOf("") == -1)); } } catch (MetacatInaccessibleException mie) { fail("AccessAPITest.setBlockAccess - Metacat inaccessible: " + mie.getMessage()); } catch (InsufficientKarmaException ike) { } catch (MetacatException me) { if (successExpected) { fail("AccessAPITest.setBlockAccess - Metacat error: " + me.getMessage()); } else { debug("AccessAPITest.setBlockAccess - Expected Metacat error: " + me.getMessage()); } } catch (Exception e) { fail("AccessAPITest.setBlockAccess - General error: " + e.getMessage()); } return response; } /** * Compare two lists of XML Access DAO objects. The first list is the master * list and the second is the sub list. All elements of the sub list must be * in the master list or a failed assertion is generated. If the exactMatch * parameter is true, the master and sub lists must be the same, otherwise, * the sub list can be a subset of the master list. * * @param mainAccessDAOList * The main list of DAOs * @param subAccessDAOList * The sub list of DAOs * @param exactMatch * if true, the master and sub lists must be exactly the same, * otherwise, the sublist must only be a subset of the master */ private void compareAccessDAOs(Vector mainAccessDAOList, Vector subAccessDAOList, boolean exactMatch) { //debug("test access DAO: "); //debugAccessDAOList(subAccessDAOList); //debug("\naccess DAOs from database: "); //debugAccessDAOList(mainAccessDAOList); // if exactMatch is true, both lists must be the same size. The next section will // make sure elements match. if (exactMatch) { if (mainAccessDAOList.size() != subAccessDAOList.size()) { fail("AccessAPITest.compareAccessDAOs - access DAO list sizes do not match. " + "Primary DAO list size: " + mainAccessDAOList.size() + ", secondary DAO list size: " + subAccessDAOList.size()); } } // iterate through the sub list and make sure all its elements are in the master list for (XMLAccessDAO subAccessDAO : subAccessDAOList) { boolean matchFound = false; for (XMLAccessDAO mainAccessDAO : mainAccessDAOList) { /*System.out.println("subAccessDAO.docid: '" + subAccessDAO.getDocId() + "'"); System.out.println("mainAccessDAO.docid: '" + mainAccessDAO.getDocId() + "'"); System.out.println("subAccessDAO.permOrder: '" + subAccessDAO.getPermOrder() + "'"); System.out.println("mainAccessDAO.permOrder: '" + mainAccessDAO.getPermOrder() + "'"); System.out.println("subAccessDAO.permtype: '" + subAccessDAO.getPermType() + "'"); System.out.println("mainAccessDAO.docid: '" + mainAccessDAO.getPermType() + "'"); System.out.println("subAccessDAO.princname: '" + subAccessDAO.getPrincipalName() + "'"); System.out.println("mainAccessDAO.princname: '" + mainAccessDAO.getPrincipalName() + "'"); System.out.println("subAccessDAO.perm: '" + subAccessDAO.getPermission() + "'"); System.out.println("mainAccessDAO.perm: '" + mainAccessDAO.getPermission() + "'");*/ if (subAccessDAO.getGuid().equals(mainAccessDAO.getGuid()) && subAccessDAO.getPermOrder().equals(mainAccessDAO.getPermOrder()) && subAccessDAO.getPermType().equals(mainAccessDAO.getPermType()) && subAccessDAO.getPrincipalName().equals(mainAccessDAO.getPrincipalName()) && subAccessDAO.getPermission().equals(mainAccessDAO.getPermission())) { matchFound = true; break; } } if (!matchFound) { fail("AccessAPITest.compareAccessDAOs - secondary access DAO does not exist in " + "primary DAO list"); } } } /** * Get a vector of access DAO objects from an EML 2.1.0-like access section * of xml * * @param docId * the doc id that we are getting access for. this makes it * easier to create a DocInfoHandler object. * @param accessXML * the access xml we want to parse. * @return a list of XML access DAO objects. */ private Vector getAccessDAOList(String docId, String accessXML) throws AccessControlException { Vector accessControlList = null; XMLReader parser = null; DocInfoHandler docInfoHandler = new DocInfoHandler(docId); ContentHandler chandler = docInfoHandler; try { // Get an instance of the parser. the DocInfoHandler will handle // the extraction of access info. String parserName = PropertyService.getProperty("xml.saxparser"); parser = XMLReaderFactory.createXMLReader(parserName); // Turn off validation parser.setFeature("http://xml.org/sax/features/validation", false); parser.setContentHandler((ContentHandler)chandler); parser.setErrorHandler((ErrorHandler)chandler); parser.parse(new InputSource(new StringReader(accessXML))); accessControlList = docInfoHandler.getAccessControlList(); } catch (PropertyNotFoundException pnfe) { throw new AccessControlException("AccessAPITest.getAccessDAOList - " + "property error: " + pnfe.getMessage()); } catch (IOException ioe) { throw new AccessControlException("AccessAPITest.getAccessDAOList - " + "I/O error: " + ioe.getMessage()); } catch (SAXException se) { throw new AccessControlException("AccessAPITest.getAccessDAOList - " + "SAX error: " + se.getMessage()); } return accessControlList; } /** * Print out the contents of an access DAO list * @param accessDAOList */ private void debugAccessDAOList(Vector accessDAOList) { for (XMLAccessDAO xmlAccessDAO : accessDAOList) { debug("Guid: " + xmlAccessDAO.getGuid()); debug("Perm Order: " + xmlAccessDAO.getPermOrder()); debug("Perm Type: " + xmlAccessDAO.getPermType()); debug("Principal " + xmlAccessDAO.getPrincipalName()); String permissionStr = AccessControlList.txtValue(xmlAccessDAO.getPermission().intValue()); debug("Permission " + permissionStr); } } }