NIHVIVO-3404 Restructure the SelfEditorRelationshipPolicy to use the model in the RequestedAction, instead of a model assigned at system startup time. Also, break out the logic into separate RelationshipChecker objects, for easier maintenance.
This commit is contained in:
parent
657e63f580
commit
d41c67b015
2 changed files with 173 additions and 149 deletions
|
@ -2,30 +2,17 @@
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.auth.policy.specialrelationships;
|
package edu.cornell.mannlib.vitro.webapp.auth.policy.specialrelationships;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import com.hp.hpl.jena.ontology.OntModel;
|
|
||||||
import com.hp.hpl.jena.rdf.model.Property;
|
|
||||||
import com.hp.hpl.jena.rdf.model.RDFNode;
|
|
||||||
import com.hp.hpl.jena.rdf.model.Resource;
|
|
||||||
import com.hp.hpl.jena.rdf.model.Selector;
|
|
||||||
import com.hp.hpl.jena.rdf.model.SimpleSelector;
|
|
||||||
import com.hp.hpl.jena.rdf.model.StmtIterator;
|
|
||||||
import com.hp.hpl.jena.shared.Lock;
|
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.BasicPolicyDecision;
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.BasicPolicyDecision;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionPolicyHelper;
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionPolicyHelper;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization;
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyDecision;
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyDecision;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyIface;
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyIface;
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean.RoleLevel;
|
import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean.RoleLevel;
|
||||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A collection of building-block methods so we can code a policy based on the
|
* A collection of building-block methods so we can code a policy based on the
|
||||||
|
@ -37,11 +24,9 @@ public abstract class AbstractRelationshipPolicy implements PolicyIface {
|
||||||
.getLog(AbstractRelationshipPolicy.class);
|
.getLog(AbstractRelationshipPolicy.class);
|
||||||
|
|
||||||
protected final ServletContext ctx;
|
protected final ServletContext ctx;
|
||||||
protected final OntModel model;
|
|
||||||
|
|
||||||
public AbstractRelationshipPolicy(ServletContext ctx, OntModel model) {
|
public AbstractRelationshipPolicy(ServletContext ctx) {
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
this.model = model;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean canModifyResource(String uri) {
|
protected boolean canModifyResource(String uri) {
|
||||||
|
@ -54,133 +39,6 @@ public abstract class AbstractRelationshipPolicy implements PolicyIface {
|
||||||
uri, RoleLevel.SELF);
|
uri, RoleLevel.SELF);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isResourceOfType(String resourceUri, String typeUri) {
|
|
||||||
Selector selector = createSelector(resourceUri,
|
|
||||||
VitroVocabulary.RDF_TYPE, typeUri);
|
|
||||||
|
|
||||||
StmtIterator stmts = null;
|
|
||||||
model.enterCriticalSection(Lock.READ);
|
|
||||||
try {
|
|
||||||
stmts = model.listStatements(selector);
|
|
||||||
if (stmts.hasNext()) {
|
|
||||||
log.debug("resource '" + resourceUri + "' is of type '"
|
|
||||||
+ typeUri + "'");
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
log.debug("resource '" + resourceUri + "' is not of type '"
|
|
||||||
+ typeUri + "'");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (stmts != null) {
|
|
||||||
stmts.close();
|
|
||||||
}
|
|
||||||
model.leaveCriticalSection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected List<String> getObjectsOfProperty(String resourceUri,
|
|
||||||
String propertyUri) {
|
|
||||||
List<String> list = new ArrayList<String>();
|
|
||||||
|
|
||||||
Selector selector = createSelector(resourceUri, propertyUri, null);
|
|
||||||
|
|
||||||
StmtIterator stmts = null;
|
|
||||||
model.enterCriticalSection(Lock.READ);
|
|
||||||
try {
|
|
||||||
stmts = model.listStatements(selector);
|
|
||||||
while (stmts.hasNext()) {
|
|
||||||
list.add(stmts.next().getObject().toString());
|
|
||||||
}
|
|
||||||
log.debug("Objects of property '" + propertyUri + "' on resource '"
|
|
||||||
+ resourceUri + "': " + list);
|
|
||||||
return list;
|
|
||||||
} finally {
|
|
||||||
if (stmts != null) {
|
|
||||||
stmts.close();
|
|
||||||
}
|
|
||||||
model.leaveCriticalSection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected List<String> getObjectsOfLinkedProperty(String resourceUri,
|
|
||||||
String linkUri, String propertyUri) {
|
|
||||||
List<String> list = new ArrayList<String>();
|
|
||||||
|
|
||||||
Selector selector = createSelector(resourceUri, linkUri, null);
|
|
||||||
|
|
||||||
StmtIterator stmts = null;
|
|
||||||
|
|
||||||
model.enterCriticalSection(Lock.READ);
|
|
||||||
try {
|
|
||||||
stmts = model.listStatements(selector);
|
|
||||||
while (stmts.hasNext()) {
|
|
||||||
RDFNode objectNode = stmts.next().getObject();
|
|
||||||
if (objectNode.isResource()) {
|
|
||||||
log.debug("found authorship for '" + resourceUri + "': "
|
|
||||||
+ objectNode);
|
|
||||||
list.addAll(getUrisOfAuthors(objectNode.asResource(),
|
|
||||||
propertyUri));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.debug("Objects of linked properties '" + linkUri + "' ==> '"
|
|
||||||
+ propertyUri + "' on '" + resourceUri + "': " + list);
|
|
||||||
return list;
|
|
||||||
} finally {
|
|
||||||
if (stmts != null) {
|
|
||||||
stmts.close();
|
|
||||||
}
|
|
||||||
model.leaveCriticalSection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Note that we must already be in a critical section! */
|
|
||||||
private List<String> getUrisOfAuthors(Resource authorship,
|
|
||||||
String propertyUri) {
|
|
||||||
List<String> list = new ArrayList<String>();
|
|
||||||
|
|
||||||
Selector selector = createSelector(authorship, propertyUri, null);
|
|
||||||
|
|
||||||
StmtIterator stmts = null;
|
|
||||||
try {
|
|
||||||
stmts = model.listStatements(selector);
|
|
||||||
while (stmts.hasNext()) {
|
|
||||||
list.add(stmts.next().getObject().toString());
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
} finally {
|
|
||||||
if (stmts != null) {
|
|
||||||
stmts.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Selector createSelector(String subjectUri, String predicateUri,
|
|
||||||
String objectUri) {
|
|
||||||
Resource subject = (subjectUri == null) ? null : model
|
|
||||||
.getResource(subjectUri);
|
|
||||||
return createSelector(subject, predicateUri, objectUri);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Selector createSelector(Resource subject, String predicateUri,
|
|
||||||
String objectUri) {
|
|
||||||
Property predicate = (predicateUri == null) ? null : model
|
|
||||||
.getProperty(predicateUri);
|
|
||||||
RDFNode object = (objectUri == null) ? null : model
|
|
||||||
.getResource(objectUri);
|
|
||||||
return new SimpleSelector(subject, predicate, object);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean anyUrisInCommon(List<String> userUris,
|
|
||||||
List<String> editorsOrAuthors) {
|
|
||||||
for (String userUri : userUris) {
|
|
||||||
if (editorsOrAuthors.contains(userUri)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected PolicyDecision cantModifyResource(String uri) {
|
protected PolicyDecision cantModifyResource(String uri) {
|
||||||
return inconclusiveDecision("No access to admin resources; cannot modify "
|
return inconclusiveDecision("No access to admin resources; cannot modify "
|
||||||
+ uri);
|
+ uri);
|
||||||
|
@ -201,10 +59,4 @@ public abstract class AbstractRelationshipPolicy implements PolicyIface {
|
||||||
.getSimpleName() + ": " + message);
|
.getSimpleName() + ": " + message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An AUTHORIZED decision with a message like "PolicyClass: message". */
|
|
||||||
protected PolicyDecision authorizedDecision(String message) {
|
|
||||||
return new BasicPolicyDecision(Authorization.AUTHORIZED, getClass()
|
|
||||||
.getSimpleName() + ": " + message);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.auth.policy.specialrelationships;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import com.hp.hpl.jena.ontology.OntModel;
|
||||||
|
import com.hp.hpl.jena.rdf.model.Property;
|
||||||
|
import com.hp.hpl.jena.rdf.model.RDFNode;
|
||||||
|
import com.hp.hpl.jena.rdf.model.Resource;
|
||||||
|
import com.hp.hpl.jena.rdf.model.Selector;
|
||||||
|
import com.hp.hpl.jena.rdf.model.SimpleSelector;
|
||||||
|
import com.hp.hpl.jena.rdf.model.StmtIterator;
|
||||||
|
import com.hp.hpl.jena.shared.Lock;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.BasicPolicyDecision;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyDecision;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look for relationships within an OntModel. Types of resources, links between
|
||||||
|
* resources, and links between resources via a context node.
|
||||||
|
*
|
||||||
|
* Also provides some convenience methods for test lists of URIs and for
|
||||||
|
* creating PolicyDecisions.
|
||||||
|
*/
|
||||||
|
public class RelationshipChecker {
|
||||||
|
private static final Log log = LogFactory.getLog(RelationshipChecker.class);
|
||||||
|
|
||||||
|
private final OntModel ontModel;
|
||||||
|
|
||||||
|
public RelationshipChecker(OntModel ontModel) {
|
||||||
|
this.ontModel = ontModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Are there any URIs that appear in both of these lists?
|
||||||
|
*/
|
||||||
|
public boolean anyUrisInCommon(List<String> list1, List<String> list2) {
|
||||||
|
List<String> urisInCommon = new ArrayList<String>(list1);
|
||||||
|
urisInCommon.retainAll(list2);
|
||||||
|
return !urisInCommon.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this resource a member of this type? That is, is there an statement of
|
||||||
|
* the form: <resourceUri> rdfs:type <typeUri>
|
||||||
|
*/
|
||||||
|
public boolean isResourceOfType(String resourceUri, String typeUri) {
|
||||||
|
Selector selector = createSelector(resourceUri,
|
||||||
|
VitroVocabulary.RDF_TYPE, typeUri);
|
||||||
|
|
||||||
|
StmtIterator stmts = null;
|
||||||
|
ontModel.enterCriticalSection(Lock.READ);
|
||||||
|
try {
|
||||||
|
stmts = ontModel.listStatements(selector);
|
||||||
|
if (stmts.hasNext()) {
|
||||||
|
log.debug("resource '" + resourceUri + "' is of type '"
|
||||||
|
+ typeUri + "'");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
log.debug("resource '" + resourceUri + "' is not of type '"
|
||||||
|
+ typeUri + "'");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (stmts != null) {
|
||||||
|
stmts.close();
|
||||||
|
}
|
||||||
|
ontModel.leaveCriticalSection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of the object URIs that satisfy this statement:
|
||||||
|
*
|
||||||
|
* <resourceUri> <propertyUri> <objectUri>
|
||||||
|
*
|
||||||
|
* May return an empty list, but never returns null.
|
||||||
|
*/
|
||||||
|
public List<String> getObjectsOfProperty(String resourceUri,
|
||||||
|
String propertyUri) {
|
||||||
|
List<String> list = new ArrayList<String>();
|
||||||
|
|
||||||
|
Selector selector = createSelector(resourceUri, propertyUri, null);
|
||||||
|
|
||||||
|
StmtIterator stmts = null;
|
||||||
|
ontModel.enterCriticalSection(Lock.READ);
|
||||||
|
try {
|
||||||
|
stmts = ontModel.listStatements(selector);
|
||||||
|
while (stmts.hasNext()) {
|
||||||
|
list.add(stmts.next().getObject().toString());
|
||||||
|
}
|
||||||
|
log.debug("Objects of property '" + propertyUri + "' on resource '"
|
||||||
|
+ resourceUri + "': " + list);
|
||||||
|
return list;
|
||||||
|
} finally {
|
||||||
|
if (stmts != null) {
|
||||||
|
stmts.close();
|
||||||
|
}
|
||||||
|
ontModel.leaveCriticalSection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of the object URIs that satisfy these statements:
|
||||||
|
*
|
||||||
|
* <resourceUri> <linkUri> <contextNodeUri>
|
||||||
|
*
|
||||||
|
* <contextNodeUri> <propertyUri> <objectUri>
|
||||||
|
*
|
||||||
|
* May return an empty list, but never returns null.
|
||||||
|
*/
|
||||||
|
public List<String> getObjectsOfLinkedProperty(String resourceUri,
|
||||||
|
String linkUri, String propertyUri) {
|
||||||
|
List<String> list = new ArrayList<String>();
|
||||||
|
|
||||||
|
Selector selector = createSelector(resourceUri, linkUri, null);
|
||||||
|
|
||||||
|
StmtIterator stmts = null;
|
||||||
|
|
||||||
|
ontModel.enterCriticalSection(Lock.READ);
|
||||||
|
try {
|
||||||
|
stmts = ontModel.listStatements(selector);
|
||||||
|
while (stmts.hasNext()) {
|
||||||
|
RDFNode contextNode = stmts.next().getObject();
|
||||||
|
if (contextNode.isResource()) {
|
||||||
|
log.debug("found context node for '" + resourceUri + "': "
|
||||||
|
+ contextNode);
|
||||||
|
list.addAll(getObjectsOfProperty(contextNode.asResource()
|
||||||
|
.getURI(), propertyUri));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.debug("Objects of linked properties '" + linkUri + "' ==> '"
|
||||||
|
+ propertyUri + "' on '" + resourceUri + "': " + list);
|
||||||
|
return list;
|
||||||
|
} finally {
|
||||||
|
if (stmts != null) {
|
||||||
|
stmts.close();
|
||||||
|
}
|
||||||
|
ontModel.leaveCriticalSection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Selector createSelector(String subjectUri, String predicateUri,
|
||||||
|
String objectUri) {
|
||||||
|
Resource subject = (subjectUri == null) ? null : ontModel
|
||||||
|
.getResource(subjectUri);
|
||||||
|
return createSelector(subject, predicateUri, objectUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Selector createSelector(Resource subject, String predicateUri,
|
||||||
|
String objectUri) {
|
||||||
|
Property predicate = (predicateUri == null) ? null : ontModel
|
||||||
|
.getProperty(predicateUri);
|
||||||
|
RDFNode object = (objectUri == null) ? null : ontModel
|
||||||
|
.getResource(objectUri);
|
||||||
|
return new SimpleSelector(subject, predicate, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** An AUTHORIZED decision with a message like "PolicyClass: message". */
|
||||||
|
protected PolicyDecision authorizedDecision(String message) {
|
||||||
|
return new BasicPolicyDecision(Authorization.AUTHORIZED, getClass()
|
||||||
|
.getSimpleName() + ": " + message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue