From 86156aaad4c6a74d80be9e7b8d5957716faf6aa0 Mon Sep 17 00:00:00 2001 From: Brian Caruso Date: Fri, 27 Sep 2013 16:03:28 -0400 Subject: [PATCH 1/3] Adding test for content negotiation --- utilities/testContentNegotiation/build.xml | 89 +++++++ utilities/testContentNegotiation/readme.md | 1 + .../TestContentNegotiation.java | 231 ++++++++++++++++++ 3 files changed, 321 insertions(+) create mode 100644 utilities/testContentNegotiation/build.xml create mode 100644 utilities/testContentNegotiation/readme.md create mode 100644 utilities/testContentNegotiation/src/edu/cornell/mannlib/vitro/testContentNegotiation/TestContentNegotiation.java diff --git a/utilities/testContentNegotiation/build.xml b/utilities/testContentNegotiation/build.xml new file mode 100644 index 000000000..34fdad5b2 --- /dev/null +++ b/utilities/testContentNegotiation/build.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + +clean - Delete all artifacts so the next build will be from scratch. +compile - Compile the Java source files. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/utilities/testContentNegotiation/readme.md b/utilities/testContentNegotiation/readme.md new file mode 100644 index 000000000..a7c81d543 --- /dev/null +++ b/utilities/testContentNegotiation/readme.md @@ -0,0 +1 @@ +This directory contains a simple java utility to test of content neogation of a running VIVO instance. diff --git a/utilities/testContentNegotiation/src/edu/cornell/mannlib/vitro/testContentNegotiation/TestContentNegotiation.java b/utilities/testContentNegotiation/src/edu/cornell/mannlib/vitro/testContentNegotiation/TestContentNegotiation.java new file mode 100644 index 000000000..d2ff5a112 --- /dev/null +++ b/utilities/testContentNegotiation/src/edu/cornell/mannlib/vitro/testContentNegotiation/TestContentNegotiation.java @@ -0,0 +1,231 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.testContentNegotiation; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + + + +import org.apache.http.NameValuePair; +import org.apache.http.Header; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.message.BasicNameValuePair; + +/** + * Utility to test content negotiation of some features + * of a running vivo instance. + * + * usage: + * java -cp $YOUR_CP edu.cornell.mannlib.vitro.testContentNegotiation VIVOURL email password + * + * This will return 0 and print "testContentNegotiation: Content negotiation tests passed.\n" + * on success. + * It will return 1 and print errors to STDOUT on failure. + */ +public class TestContentNegotiation{ + + static CNTest[] tests = { + //URL, QUERY, Accept header, pattern for response Content-Type, pattern for body, description + new CNTest(constants.servlet, constants.query, "none", ".*", ".*","Test to see if a basic request works") + }; + + + public static void main(String[] argv){ + + if( argv.length != 3 ){ + doHelp(); + System.exit(2); + } + + String baseUrl = argv[0]; + String email = argv[1]; + String pw = argv[2]; + + List errors = new ArrayList(); + + for( CNTest test : tests ){ + String msg = test.doTest( baseUrl, email, pw); + if( msg != null ) + errors.add( msg ); + } + + if( errors.isEmpty() ){ + System.out.println("testContentNegotiation: Content negotiation tests passed.\n"); + System.exit(0); + }else{ + doErrors( errors ); + System.exit(1); + } + } + + private static void doErrors( List errors){ + System.out.println("ERROR testContentNegotiation: There were " + errors.size() + " errors."); + for( String err : errors){ + System.out.println( err ); + } + } + + private static void doHelp(){ + System.out.println( + "Utility to test content negotiation of some features \n" + + "of a running vivo instance. \n" + + "usage: \n" + + "java -cp $YOUR_CP edu.cornell.mannlib.vitro.testContentNegotiation VIVOURL email password\n"); + } + + protected static class CNTest{ + String request; + String acceptHeader; + String query; + Pattern expectedResponseContentType; + Pattern expectedBody; + String description; + + public CNTest(String request, String query, String acceptHeader, + String expectedResponseContentType, String expectedBody, + String description){ + this.request = request; + this.acceptHeader = acceptHeader; + this.query = query; + this.expectedResponseContentType = Pattern.compile( expectedResponseContentType ); + this.expectedBody = Pattern.compile( expectedBody ); + this.description = description; + } + + /** + * Returns a non-null string on failure. + * Returns null on success. + */ + String doTest(String baseUrl, String email, String pw) { + HttpClient httpClient = new DefaultHttpClient(); + HttpPost httpPost = new HttpPost( baseUrl + request ); + httpPost.addHeader("Accept", acceptHeader); + List nvps = new ArrayList (); + nvps.add(new BasicNameValuePair("email", "vip")); + nvps.add(new BasicNameValuePair("password", "secret")); + nvps.add(new BasicNameValuePair("query", query)); + try { + httpPost.setEntity(new UrlEncodedFormEntity(nvps)); + } catch (UnsupportedEncodingException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + + HttpResponse resp; + try { + resp = httpClient.execute(httpPost); + } catch (Exception e){ + return "Failed, exception, " + e.getMessage() ; + } + + //Check response content type + try{ + Header[] contentType = resp.getHeaders("Content-Type"); + if( contentType == null || contentType.length == 0 ){ + return "Failed, Content-Type was empty be expected " + expectedResponseContentType; + } + + boolean foundMatch = false; + for( Header header : contentType){ + Matcher m = expectedResponseContentType.matcher( header.getValue() ); + if( m.matches() ){ + foundMatch = true; + break; + } + } + + if( !foundMatch ){ + return "Failed to match expected Content-Type " + + expectedResponseContentType.toString() + + " to value " + resp.getHeaders("Content-Type") ; + } + }finally{ + httpPost.releaseConnection(); + } + + //TODO: Check body + return null; + } + } + + + protected static class constants{ + + static String servlet = "/admin/sparqlquery"; + + static String query = + "PREFIX rdf: \n" + + "PREFIX rdfs: \n" + + "PREFIX xsd: \n" + + "PREFIX owl: \n" + + "PREFIX swrl: \n" + + "PREFIX swrlb: \n" + + "PREFIX vitro: \n" + + "PREFIX p.1: \n" + + "PREFIX p.2: \n" + + "PREFIX bibo: \n" + + "PREFIX c4o: \n" + + "PREFIX p.3: \n" + + "PREFIX p.4: \n" + + "PREFIX p.5: \n" + + "PREFIX p.6: \n" + + "PREFIX p.7: \n" + + "PREFIX p.8: \n" + + "PREFIX p.9: \n" + + "PREFIX dcelem: \n" + + "PREFIX dcterms: \n" + + "PREFIX p.10: \n" + + "PREFIX p.11: \n" + + "PREFIX event: \n" + + "PREFIX foaf: \n" + + "PREFIX fabio: \n" + + "PREFIX geo: \n" + + "PREFIX p.12: \n" + + "PREFIX p.13: \n" + + "PREFIX p.14: \n" + + "PREFIX p.15: \n" + + "PREFIX p.16: \n" + + "PREFIX p.17: \n" + + "PREFIX p.18: \n" + + "PREFIX pvs: \n" + + "PREFIX p.19: \n" + + "PREFIX p.20: \n" + + "PREFIX p.21: \n" + + "PREFIX p.22: \n" + + "PREFIX p.23: \n" + + "PREFIX ero: \n" + + "PREFIX p.24: \n" + + "PREFIX scires: \n" + + "PREFIX p.25: \n" + + "PREFIX skos: \n" + + "PREFIX p.26: \n" + + "PREFIX p.27: \n" + + "PREFIX p.28: \n" + + "PREFIX vitro-public: \n" + + "PREFIX p.29: \n" + + "PREFIX vivo: \n" + + "\n" + + "#\n" + + "# This example query gets 20 geographic locations\n" + + "# and (if available) their labels\n" + + "#\n" + + "SELECT ?geoLocation ?label\n" + + "WHERE\n" + + "{\n" + + " ?geoLocation rdf:type vivo:GeographicLocation\n" + + " OPTIONAL { ?geoLocation rdfs:label ?label } \n" + + "}\n" + + "LIMIT 20"; + + + } +} From 1658d7784afe6071b3cfd5b4932e42a5b5ccbb07 Mon Sep 17 00:00:00 2001 From: Brian Caruso Date: Fri, 27 Sep 2013 16:04:06 -0400 Subject: [PATCH 2/3] Adding email/pw auth to sparql query page --- .../webapp/controller/SparqlQueryServlet.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/SparqlQueryServlet.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/SparqlQueryServlet.java index db668fb85..bde67c1b5 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/SparqlQueryServlet.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/SparqlQueryServlet.java @@ -41,8 +41,8 @@ import com.hp.hpl.jena.vocabulary.XSD; import edu.cornell.mannlib.vedit.controller.BaseEditController; import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission; +import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper; import edu.cornell.mannlib.vitro.webapp.beans.Ontology; -import edu.cornell.mannlib.vitro.webapp.controller.individual.IndividualController; import edu.cornell.mannlib.vitro.webapp.dao.OntologyDao; import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService.ModelSerializationFormat; @@ -92,12 +92,20 @@ public class SparqlQueryServlet extends BaseEditController { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - if (!isAuthorizedToDisplayPage(request, response, - SimplePermission.USE_SPARQL_QUERY_PAGE.ACTIONS)) { - return; - } - VitroRequest vreq = new VitroRequest(request); + + //first check if the email and password are just in the request + String email = vreq.getParameter("email"); + String password = vreq.getParameter("password"); + boolean isAuth = PolicyHelper.isAuthorizedForActions(vreq, + email, password, SimplePermission.USE_SPARQL_QUERY_PAGE.ACTIONS); + + //otherwise use the normal auth mechanism + if( ! isAuth && + !isAuthorizedToDisplayPage(request, response, + SimplePermission.USE_SPARQL_QUERY_PAGE.ACTIONS)) { + return; + } Model model = vreq.getJenaOntModel(); if( model == null ){ From 26927d8ff4a1b3b5bb55f7f0fd0e972ae5b9a32e Mon Sep 17 00:00:00 2001 From: Brian Caruso Date: Mon, 14 Oct 2013 10:09:53 -0400 Subject: [PATCH 3/3] Line ending for example file. --- webapp/config/example.runtime.properties | 372 +++++++++++------------ 1 file changed, 186 insertions(+), 186 deletions(-) diff --git a/webapp/config/example.runtime.properties b/webapp/config/example.runtime.properties index c91188ae3..d72d632d7 100644 --- a/webapp/config/example.runtime.properties +++ b/webapp/config/example.runtime.properties @@ -1,186 +1,186 @@ -# ----------------------------------------------------------------------------- -# -# Vitro runtime properties -# -# This file is provided as example.runtime.properties. -# -# Save a copy of this file as runtime.properties in your Vitro home directory, -# and edit the properties as needed for your installation. -# -# ----------------------------------------------------------------------------- - -# -# This namespace will be used when generating URIs for objects created in the -# editor. In order to serve linked data, the default namespace must be composed -# as follows (optional elements in parentheses): -# -# scheme + server_name (+ port) (+ servlet_context) + "/individual/" -# -# For example, Cornell's default namespace is: -# -# http://vivo.cornell.edu/individual/ -# -Vitro.defaultNamespace = http://vivo.mydomain.edu/individual/ - -# -# URL of Solr context used in local Vitro search. This will usually consist of: -# scheme + server_name + port + vitro_webapp_name + "solr" -# In the standard installation, the Solr context will be on the same server as Vitro, -# and in the same Tomcat instance. The path will be the Vitro webapp.name (specified -# above) + "solr" -# Example: -# vitro.local.solr.url = http://localhost:8080/vitrosolr -vitro.local.solr.url = http://localhost:8080/vitrosolr - -# -# Email parameters which VIVO can use to send mail. If these are left empty, -# the "Contact Us" form will be disabled and users will not be notified of -# changes to their accounts. -# -email.smtpHost = smtp.my.domain.edu -email.replyTo = vivoAdmin@my.domain.edu - -# -# The basic parameters for a MySQL database connection. Change the end of the -# URL to reflect your database name (if it is not "vitro"). Change the username -# and password to match the authorized user you created in MySQL. -# -VitroConnection.DataSource.url = jdbc:mysql://localhost/vitro -VitroConnection.DataSource.username = vitroweb -VitroConnection.DataSource.password = vitrovitro - -# -# The maximum number of active connections in the database connection pool. -# Increase this value to support a greater number of concurrent page requests. -# -VitroConnection.DataSource.pool.maxActive = 40 - -# -# The maximum number of database connections that will be allowed -# to remain idle in the connection pool. Default is 25% -# of the maximum number of active connections. -# -VitroConnection.DataSource.pool.maxIdle = 10 - -# -# Parameters to change in order to use VIVO with a database other than -# MySQL. -# -VitroConnection.DataSource.dbtype = MySQL -VitroConnection.DataSource.driver = com.mysql.jdbc.Driver -VitroConnection.DataSource.validationQuery = SELECT 1 - -# -# Optional URI of a SPARQL endpoint from which VIVO should display data. -# If set, VIVO will use this endpoint as its triple store instead of the -# SDB database. -# -#VitroConnection.DataSource.endpointURI = - -# -# Optional URI to use for modifying the above endpoint via SPARQL UPDATE. -# This setting is only necessary if the endpoint does not support updates via -# its main URI. (This may be done for access control purposes.) -# If the endpointURI above is not set, this setting has no effect. -# -#VitroConnection.DataSource.updateEndpointURI = - -# -# The email address of the root user for the VIVO application. The password -# for this user is initially set to "rootPassword", but you will be asked to -# change the password the first time you log in. -# -rootUser.emailAddress = root@myDomain.com - -# -# How is a logged-in user associated with a particular Individual? One way is -# for the Individual to have a property whose value is the username of the user. -# This is the name of that property. -# -selfEditing.idMatchingProperty = http://vitro.mydomain.edu/ns#networkId - -# -# If an external authentication system like Shibboleth or CUWebAuth is to be -# used, these properties say how the login button should be labeled, and which -# HTTP header will contain the user ID from the authentication system. If such -# as system is not to be used, leave these commented out. Consult the -# installation instructions for more details. -# -#externalAuth.buttonText = Log in using BearCat Shibboleth -#externalAuth.netIdHeaderName = remote_userID - -# -# Types of individual for which we can create proxy editors. -# If this is omitted, defaults to http://www.w3.org/2002/07/owl#Thing -proxy.eligibleTypeList = http://www.w3.org/2002/07/owl#Thing - -# -# Show only the most appropriate data values based on the Accept-Language -# header supplied by the browser. Default is true if not set. -# -RDFService.languageFilter = true - -# -# Tell VIVO to generate HTTP headers on its responses to facilitate caching the -# profile pages that it creates. -# -# For more information, see -# https://wiki.duraspace.org/display/VIVO/Use+HTTP+caching+to+improve+performance -# -# Developers will likely want to leave caching disabled, since a change to a -# Freemarker template or to a Java class would not cause the page to be -# considered stale. -# -# http.createCacheHeaders = true - -# -# Force VIVO to use a specific language or Locale instead of those -# specified by the browser. This affects RDF data retrieved from the model, -# if RDFService.languageFilter is true. This also affects the text of pages -# that have been modified to support multiple languages. -# -# languages.forceLocale = en_US - -# -# A list of supported languages or Locales that the user may choose to -# use instead of the one specified by the browser. Selection images must -# be available in the i18n/images directory of the theme. This affects -# RDF data retrieved from the model, if RDFService.languageFilter is true. -# This also affects the text of pages that have been modified to support -# multiple languages. -# -# This should not be used with languages.forceLocale, which will override it. -# -# languages.selectableLocales = en, es, fr - -# -# For developers only: Setting this option to "true" slows down Vitro performance. -# -# Defeat the Freemarker template cache, so each template is read from disk -# on each request. This permits developers to immediately see the effect of -# changes to the template. The default is false, which means -# that a cached copy of each template will be used for 60 seconds before -# the disk is checked for a new version. -# -# developer.defeatFreemarkerCache = true - -# -# For developers only: Setting this option to "true" slows down Vitro performance. -# -# Defeat the cache of language-specific text strings, so the language file -# is read from disk on each request. This permits developers to immediately -# see the effect of changes to the text strings. The default is -# false, which means that the language file is read when -# VIVO starts up, or when a new theme is selected. -# -# developer.defeatI18nCache = true - -# -# For developers only: Setting this option to "true" slows down Vitro performance. -# -# Add starting and ending delimiters to each Freemarker template, so you can see -# which template were invoked by viewing the generated HTML. The default is -# false. -# -# developer.insertFreemarkerDelimiters = true - +# ----------------------------------------------------------------------------- +# +# Vitro runtime properties +# +# This file is provided as example.runtime.properties. +# +# Save a copy of this file as runtime.properties in your Vitro home directory, +# and edit the properties as needed for your installation. +# +# ----------------------------------------------------------------------------- + +# +# This namespace will be used when generating URIs for objects created in the +# editor. In order to serve linked data, the default namespace must be composed +# as follows (optional elements in parentheses): +# +# scheme + server_name (+ port) (+ servlet_context) + "/individual/" +# +# For example, Cornell's default namespace is: +# +# http://vivo.cornell.edu/individual/ +# +Vitro.defaultNamespace = http://vivo.mydomain.edu/individual/ + +# +# URL of Solr context used in local Vitro search. This will usually consist of: +# scheme + server_name + port + vitro_webapp_name + "solr" +# In the standard installation, the Solr context will be on the same server as Vitro, +# and in the same Tomcat instance. The path will be the Vitro webapp.name (specified +# above) + "solr" +# Example: +# vitro.local.solr.url = http://localhost:8080/vitrosolr +vitro.local.solr.url = http://localhost:8080/vitrosolr + +# +# Email parameters which VIVO can use to send mail. If these are left empty, +# the "Contact Us" form will be disabled and users will not be notified of +# changes to their accounts. +# +email.smtpHost = smtp.my.domain.edu +email.replyTo = vivoAdmin@my.domain.edu + +# +# The basic parameters for a MySQL database connection. Change the end of the +# URL to reflect your database name (if it is not "vitro"). Change the username +# and password to match the authorized user you created in MySQL. +# +VitroConnection.DataSource.url = jdbc:mysql://localhost/vitro +VitroConnection.DataSource.username = vitroweb +VitroConnection.DataSource.password = vitrovitro + +# +# The maximum number of active connections in the database connection pool. +# Increase this value to support a greater number of concurrent page requests. +# +VitroConnection.DataSource.pool.maxActive = 40 + +# +# The maximum number of database connections that will be allowed +# to remain idle in the connection pool. Default is 25% +# of the maximum number of active connections. +# +VitroConnection.DataSource.pool.maxIdle = 10 + +# +# Parameters to change in order to use VIVO with a database other than +# MySQL. +# +VitroConnection.DataSource.dbtype = MySQL +VitroConnection.DataSource.driver = com.mysql.jdbc.Driver +VitroConnection.DataSource.validationQuery = SELECT 1 + +# +# Optional URI of a SPARQL endpoint from which VIVO should display data. +# If set, VIVO will use this endpoint as its triple store instead of the +# SDB database. +# +#VitroConnection.DataSource.endpointURI = + +# +# Optional URI to use for modifying the above endpoint via SPARQL UPDATE. +# This setting is only necessary if the endpoint does not support updates via +# its main URI. (This may be done for access control purposes.) +# If the endpointURI above is not set, this setting has no effect. +# +#VitroConnection.DataSource.updateEndpointURI = + +# +# The email address of the root user for the VIVO application. The password +# for this user is initially set to "rootPassword", but you will be asked to +# change the password the first time you log in. +# +rootUser.emailAddress = root@myDomain.com + +# +# How is a logged-in user associated with a particular Individual? One way is +# for the Individual to have a property whose value is the username of the user. +# This is the name of that property. +# +selfEditing.idMatchingProperty = http://vitro.mydomain.edu/ns#networkId + +# +# If an external authentication system like Shibboleth or CUWebAuth is to be +# used, these properties say how the login button should be labeled, and which +# HTTP header will contain the user ID from the authentication system. If such +# as system is not to be used, leave these commented out. Consult the +# installation instructions for more details. +# +#externalAuth.buttonText = Log in using BearCat Shibboleth +#externalAuth.netIdHeaderName = remote_userID + +# +# Types of individual for which we can create proxy editors. +# If this is omitted, defaults to http://www.w3.org/2002/07/owl#Thing +proxy.eligibleTypeList = http://www.w3.org/2002/07/owl#Thing + +# +# Show only the most appropriate data values based on the Accept-Language +# header supplied by the browser. Default is true if not set. +# +RDFService.languageFilter = true + +# +# Tell VIVO to generate HTTP headers on its responses to facilitate caching the +# profile pages that it creates. +# +# For more information, see +# https://wiki.duraspace.org/display/VIVO/Use+HTTP+caching+to+improve+performance +# +# Developers will likely want to leave caching disabled, since a change to a +# Freemarker template or to a Java class would not cause the page to be +# considered stale. +# +# http.createCacheHeaders = true + +# +# Force VIVO to use a specific language or Locale instead of those +# specified by the browser. This affects RDF data retrieved from the model, +# if RDFService.languageFilter is true. This also affects the text of pages +# that have been modified to support multiple languages. +# +# languages.forceLocale = en_US + +# +# A list of supported languages or Locales that the user may choose to +# use instead of the one specified by the browser. Selection images must +# be available in the i18n/images directory of the theme. This affects +# RDF data retrieved from the model, if RDFService.languageFilter is true. +# This also affects the text of pages that have been modified to support +# multiple languages. +# +# This should not be used with languages.forceLocale, which will override it. +# +# languages.selectableLocales = en, es, fr + +# +# For developers only: Setting this option to "true" slows down Vitro performance. +# +# Defeat the Freemarker template cache, so each template is read from disk +# on each request. This permits developers to immediately see the effect of +# changes to the template. The default is false, which means +# that a cached copy of each template will be used for 60 seconds before +# the disk is checked for a new version. +# +# developer.defeatFreemarkerCache = true + +# +# For developers only: Setting this option to "true" slows down Vitro performance. +# +# Defeat the cache of language-specific text strings, so the language file +# is read from disk on each request. This permits developers to immediately +# see the effect of changes to the text strings. The default is +# false, which means that the language file is read when +# VIVO starts up, or when a new theme is selected. +# +# developer.defeatI18nCache = true + +# +# For developers only: Setting this option to "true" slows down Vitro performance. +# +# Add starting and ending delimiters to each Freemarker template, so you can see +# which template were invoked by viewing the generated HTML. The default is +# false. +# +# developer.insertFreemarkerDelimiters = true +