Adding authorization to SparqlUpdate, changing name of SparqlUpdateTestDataGetter to SparqlUpdate. Adding AND to Actions

This commit is contained in:
Brian Caruso 2013-08-21 13:01:13 -04:00
parent 63da01ed7b
commit 7a431478cb
5 changed files with 177 additions and 26 deletions

View file

@ -39,15 +39,39 @@ public class Actions {
return (actions == null) ? AUTHORIZED : actions;
}
private final List<Set<RequestedAction>> clauseList;
/**
* This is a list of clauses that get ORed together.
* If all of the RequestedAction objects from any of the
* Sets are authorized, then the Actions object should
* be considered authorized.
*/
private List<Set<RequestedAction>> clauseList;
public Actions(){
clauseList= new ArrayList<Set<RequestedAction>>();
}
public Actions(RequestedAction... actions) {
this(Arrays.asList(actions));
}
public Actions(Actions... actions){
Set<RequestedAction> accumActs = new HashSet<RequestedAction>();
for( Actions actionToAnd : actions){
if( actionToAnd != null ){
for( Set<RequestedAction> ras : actionToAnd.clauseList){
accumActs.addAll( ras );
}
}
}
clauseList= new ArrayList<Set<RequestedAction>>();
clauseList.add( accumActs );
}
public Actions(Collection<RequestedAction> actions) {
this(Collections.<Set<RequestedAction>> emptyList(), actions);
}
private Actions(List<Set<RequestedAction>> oldList,
Collection<RequestedAction> newActions) {
@ -61,7 +85,19 @@ public class Actions {
}
this.clauseList = Collections.unmodifiableList(newList);
}
public Actions and(RequestedAction... newActions){
return and(Arrays.asList( newActions));
}
public Actions and(Collection<RequestedAction> newActions){
return new Actions( this.clauseList, newActions);
}
public void and( Actions otherAct ) throws Exception{
andWithAction(otherAct);
}
public Actions or(RequestedAction... newActions) {
return or(Arrays.asList(newActions));
}
@ -143,6 +179,42 @@ public class Actions {
return sb.toString();
}
/**
* AND for Actions.
* ANDing with an Action with multiple disjoint clauses is not supported.
*
* To do the AND, we take each ORed clause, and add all of the RequestedActions
* so now in each of the alternative clauses, all of the singleClauseToAnd
* RequestedActions are required.
*
* @throws Exception when multiple disjoint clauses are present on both Actions.
*/
private void andWithAction( Actions otherAct ) throws Exception{
Set<RequestedAction> singleClauseToAnd;
List<Set<RequestedAction>> clauses;
if( otherAct.singleAndClause() ){
clauses = this.clauseList;
singleClauseToAnd = otherAct.clauseList.get(0);
}else if( this.singleAndClause() ){
clauses = new ArrayList<Set<RequestedAction>>( otherAct.clauseList );
singleClauseToAnd = this.clauseList.get(0);
}else{
//both have multiple ORed clauses, give up
throw new Exception("ANDing with an Action with multiple disjoint clauses is not supported.");
}
//
for( Set<RequestedAction> clause : clauses){
clause.addAll( singleClauseToAnd );
}
this.clauseList = clauses;
}
private boolean singleAndClause(){
return clauseList.size() == 1;
}
/**
* Nobody knows about this action class, so only the root user should be
* authorized for it.

View file

@ -3,6 +3,7 @@
package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -17,6 +18,8 @@ import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequiresActions;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
@ -41,6 +44,42 @@ public class PageController extends FreemarkerHttpServlet{
protected static final String DATA_GETTER_MAP = "pageTypeToDataGetterMap";
/**
* Get the required actions for all the data getters then
* AND them together.
*/
@Override
protected Actions requiredActions(VitroRequest vreq) {
try {
Actions actAcc = null;
List<DataGetter> dgList =
DataGetterUtils.getDataGettersForPage(vreq, vreq.getDisplayModel(), getPageUri(vreq));
for( DataGetter dg : dgList){
if( dg instanceof RequiresActions ){
RequiresActions ra = (RequiresActions) dg;
Actions acts = ra.requiredActions(vreq);
if( acts != null ){
if( actAcc != null ){
actAcc.and( acts );
}else{
actAcc = acts;
}
}
}
}
if( actAcc == null )
return Actions.AUTHORIZED;
else
return actAcc;
} catch (Exception e) {
// TODO Auto-generated catch block
log.debug(e);
return Actions.UNAUTHORIZED;
}
}
@Override
protected ResponseValues processRequest(VitroRequest vreq) throws Exception {

View file

@ -55,7 +55,12 @@ import edu.cornell.mannlib.vitro.webapp.dao.jena.VClassGroupCache;
public class DataGetterUtils {
final static Log log = LogFactory.getLog(DataGetterUtils.class);
/**
* Attribute name in request for DataGetters
*/
public final static String DATA_GETTERS_FOR_PAGE = "data_getters_for_page";
/**
* Get a list of DataGetter objects that are associated with a page.
* This should not return PageDataGetters and should not throw an
@ -63,10 +68,16 @@ public class DataGetterUtils {
*/
public static List<DataGetter> getDataGettersForPage(VitroRequest vreq, Model displayModel, String pageURI)
throws InstantiationException, IllegalAccessException, ClassNotFoundException, IllegalArgumentException, SecurityException, InvocationTargetException, NoSuchMethodException {
List<String> dgUris = getDataGetterURIsForAssociatedURI(displayModel, pageURI);
List<DataGetter> dgList = dataGettersForURIs(vreq, displayModel, dgUris);
log.debug("getDataGettersForPage: " + dgList);
return dgList;
if( vreq.getAttribute(DATA_GETTERS_FOR_PAGE) != null){
return (List<DataGetter>) vreq.getAttribute(DATA_GETTERS_FOR_PAGE);
}else{
List<String> dgUris = getDataGetterURIsForAssociatedURI(displayModel, pageURI);
List<DataGetter> dgList = dataGettersForURIs(vreq, displayModel, dgUris);
log.debug("getDataGettersForPage: " + dgList);
vreq.setAttribute( DATA_GETTERS_FOR_PAGE , dgList );
return dgList;
}
}
/**

View file

@ -11,28 +11,35 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.hp.hpl.jena.query.Dataset;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.update.GraphStore;
import com.hp.hpl.jena.update.GraphStoreFactory;
import com.hp.hpl.jena.update.UpdateAction;
import edu.cornell.mannlib.vitro.webapp.search.indexing.IndexBuilder;
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequiresActions;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.dao.jena.RDFServiceDataset;
import edu.cornell.mannlib.vitro.webapp.search.indexing.IndexBuilder;
/**
* Test to experiment with Jena ARQ SPARQL update and the RDFServiceDataset.
* Handle a SPARQL Update request. This uses Jena ARQ and the RDFServiceDataset to
* evaluate a SPARQL Update with the RDFService.
*
* The reason to make this a DataGettere was to allow configuration in RDF of this
* service.
*/
public class SparqlUpdateTestDataGetter implements DataGetter{
private static final Log log = LogFactory.getLog(SparqlUpdateTestDataGetter.class);
public class SparqlUpdate implements DataGetter, RequiresActions{
private static final Log log = LogFactory.getLog(SparqlUpdate.class);
VitroRequest vreq;
ServletContext context;
/**
* Constructor with display model and data getter URI that will be called by reflection.
*/
public SparqlUpdateTestDataGetter(VitroRequest vreq ){
public SparqlUpdate(
VitroRequest vreq, Model displayModel, String dataGetterURI ) {
if( vreq == null )
throw new IllegalArgumentException("VitroRequest may not be null.");
this.vreq = vreq;
@ -40,6 +47,10 @@ public class SparqlUpdateTestDataGetter implements DataGetter{
}
/**
* Gets the update from the request and then executes it on
* the RDFService.
*/
@Override
public Map<String,Object> getData( Map<String, Object> valueMap ) {
HashMap<String, Object> data = new HashMap<String,Object>();
@ -61,6 +72,25 @@ public class SparqlUpdateTestDataGetter implements DataGetter{
data.put("bodyTemplate", "page-sparqlUpdateTest.ftl");
return data;
}
/**
* Check if this request is authorized by the email/password.
* If not do normal authorization.
*/
@Override
public Actions requiredActions(VitroRequest vreq) {
String email = vreq.getParameter("email");
String password = vreq.getParameter("password");
boolean isAuth = PolicyHelper.isAuthorizedForActions(vreq,
email, password, SimplePermission.MANAGE_SEARCH_INDEX.ACTIONS);
if( isAuth )
return Actions.AUTHORIZED;
else
return SimplePermission.MANAGE_SEARCH_INDEX.ACTIONS;
}
}

View file

@ -5,18 +5,17 @@
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
### Test page for SPARQL UPDATE ###
### Not For Production ###
display:SparqlTestMenuItem
### page for SPARQL UPDATE ###
display:SparqlUpdateMenuItem
a display:NavigationElement ;
display:linkText "SPARQL Update Test";
display:toPage display:SparqlUpdateTestPage .
display:linkText "SPARQL Update";
display:toPage display:SparqlUpdatePage .
display:SparqlUpdateTestPage
display:SparqlUpdatePage
a display:Page ;
display:title "SPARQL Update Test" ;
display:urlMapping "/sparqlUpdateTest" ;
display:title "SPARQL Update" ;
display:urlMapping "/sparql" ;
display:hasDataGetter display:sparqlUpdateDataGetter .
display:sparqlUpdateDataGetter
a <java:edu.cornell.mannlib.vitro.webapp.utils.dataGetter.SparqlUpdateTestDataGetter> .
a <java:edu.cornell.mannlib.vitro.webapp.utils.dataGetter.SparqlUpdate> .