NIHVIVO-2509 Replace InformationResourceEditingPolicy with SelfEditorRelationshipPolicy, which is better structured and handles more special relationships.
This commit is contained in:
parent
1ef114ff45
commit
ac55760a5a
7 changed files with 668 additions and 448 deletions
|
@ -149,11 +149,6 @@
|
||||||
</listener-class>
|
</listener-class>
|
||||||
</listener> -->
|
</listener> -->
|
||||||
|
|
||||||
<!--
|
|
||||||
<listener>
|
|
||||||
<listener-class> edu.cornell.mannlib.vitro.webapp.auth.policy.setup.InformationResourceEditingPolicySetup</listener-class>
|
|
||||||
</listener> -->
|
|
||||||
|
|
||||||
<listener>
|
<listener>
|
||||||
<listener-class>
|
<listener-class>
|
||||||
edu.cornell.mannlib.vitro.webapp.auth.identifier.UserToIndIdentifierFactorySetup
|
edu.cornell.mannlib.vitro.webapp.auth.identifier.UserToIndIdentifierFactorySetup
|
||||||
|
|
|
@ -1,332 +0,0 @@
|
||||||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.auth.policy;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
|
|
||||||
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.identifier.IdentifierBundle;
|
|
||||||
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.requestedAction.ifaces.RequestedAction;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.AbstractDataPropertyAction;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.AbstractObjectPropertyAction;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean.RoleLevel;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows a self-editor to edit properties on any InformationResource of which
|
|
||||||
* he is an author or an editor.
|
|
||||||
*/
|
|
||||||
public class InformationResourceEditingPolicy extends BaseSelfEditingPolicy
|
|
||||||
implements PolicyIface {
|
|
||||||
private static final Log log = LogFactory
|
|
||||||
.getLog(InformationResourceEditingPolicy.class);
|
|
||||||
|
|
||||||
private static final String NS_CORE = "http://vivoweb.org/ontology/core#";
|
|
||||||
private static final String URI_INFORMATION_RESOURCE_TYPE = NS_CORE
|
|
||||||
+ "InformationResource";
|
|
||||||
private static final String URI_EDITOR_PROPERTY = "http://purl.org/ontology/bibo/editor";
|
|
||||||
private static final String URI_IN_AUTHORSHIP_PROPERTY = NS_CORE
|
|
||||||
+ "informationResourceInAuthorship";
|
|
||||||
private static final String URI_LINKED_AUTHOR_PROPERTY = NS_CORE
|
|
||||||
+ "linkedAuthor";
|
|
||||||
private static final String URI_FEATURES_PROPERTY = NS_CORE + "features";
|
|
||||||
|
|
||||||
private final OntModel model;
|
|
||||||
|
|
||||||
public InformationResourceEditingPolicy(ServletContext ctx, OntModel model) {
|
|
||||||
super(ctx, RoleLevel.SELF);
|
|
||||||
this.model = model;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PolicyDecision isAuthorized(IdentifierBundle whoToAuth,
|
|
||||||
RequestedAction whatToAuth) {
|
|
||||||
if (whoToAuth == null) {
|
|
||||||
return inconclusiveDecision("whoToAuth was null");
|
|
||||||
}
|
|
||||||
if (whatToAuth == null) {
|
|
||||||
return inconclusiveDecision("whatToAuth was null");
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> userUris = getUrisOfSelfEditor(whoToAuth);
|
|
||||||
|
|
||||||
if (userUris.isEmpty()) {
|
|
||||||
return inconclusiveDecision("Not self-editing.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (whatToAuth instanceof AbstractObjectPropertyAction) {
|
|
||||||
return isAuthorizedForObjectPropertyAction(userUris,
|
|
||||||
(AbstractObjectPropertyAction) whatToAuth);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (whatToAuth instanceof AbstractDataPropertyAction) {
|
|
||||||
return isAuthorizedForDataPropertyAction(userUris,
|
|
||||||
(AbstractDataPropertyAction) whatToAuth);
|
|
||||||
}
|
|
||||||
|
|
||||||
return inconclusiveDecision("Does not authorize "
|
|
||||||
+ whatToAuth.getClass().getSimpleName() + " actions");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The user can edit a data property if it is not restricted and if it is
|
|
||||||
* about an information resource which he authored or edited, or in which he
|
|
||||||
* is featured.
|
|
||||||
*/
|
|
||||||
private PolicyDecision isAuthorizedForDataPropertyAction(
|
|
||||||
List<String> userUris, AbstractDataPropertyAction action) {
|
|
||||||
String subject = action.getSubjectUri();
|
|
||||||
String predicate = action.getPredicateUri();
|
|
||||||
|
|
||||||
if (!canModifyResource(subject)) {
|
|
||||||
return cantModifyResource(subject);
|
|
||||||
}
|
|
||||||
if (!canModifyPredicate(predicate)) {
|
|
||||||
return cantModifyPredicate(predicate);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isInformationResource(subject)) {
|
|
||||||
if (anyUrisInCommon(userUris, getUrisOfEditors(subject))) {
|
|
||||||
return authorizedSubjectEditor();
|
|
||||||
}
|
|
||||||
if (anyUrisInCommon(userUris, getUrisOfAuthors(subject))) {
|
|
||||||
return authorizedSubjectAuthor();
|
|
||||||
}
|
|
||||||
if (anyUrisInCommon(userUris, getUrisOfFeatured(subject))) {
|
|
||||||
return authorizedSubjectFeatured();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return userNotAuthorizedToStatement();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The user can edit an object property if it is not restricted and if it is
|
|
||||||
* about an information resource which he authored or edited, or in which he
|
|
||||||
* is featured.
|
|
||||||
*/
|
|
||||||
private PolicyDecision isAuthorizedForObjectPropertyAction(
|
|
||||||
List<String> userUris, AbstractObjectPropertyAction action) {
|
|
||||||
String subject = action.getUriOfSubject();
|
|
||||||
String predicate = action.getUriOfPredicate();
|
|
||||||
String object = action.getUriOfObject();
|
|
||||||
|
|
||||||
if (!canModifyResource(subject)) {
|
|
||||||
return cantModifyResource(subject);
|
|
||||||
}
|
|
||||||
if (!canModifyPredicate(predicate)) {
|
|
||||||
return cantModifyPredicate(predicate);
|
|
||||||
}
|
|
||||||
if (!canModifyResource(object)) {
|
|
||||||
return cantModifyResource(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isInformationResource(subject)) {
|
|
||||||
if (anyUrisInCommon(userUris, getUrisOfEditors(subject))) {
|
|
||||||
return authorizedSubjectEditor();
|
|
||||||
}
|
|
||||||
if (anyUrisInCommon(userUris, getUrisOfAuthors(subject))) {
|
|
||||||
return authorizedSubjectAuthor();
|
|
||||||
}
|
|
||||||
if (anyUrisInCommon(userUris, getUrisOfFeatured(subject))) {
|
|
||||||
return authorizedSubjectFeatured();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isInformationResource(object)) {
|
|
||||||
if (anyUrisInCommon(userUris, getUrisOfEditors(object))) {
|
|
||||||
return authorizedObjectEditor();
|
|
||||||
}
|
|
||||||
if (anyUrisInCommon(userUris, getUrisOfAuthors(object))) {
|
|
||||||
return authorizedObjectAuthor();
|
|
||||||
}
|
|
||||||
if (anyUrisInCommon(userUris, getUrisOfFeatured(object))) {
|
|
||||||
return authorizedObjectFeatured();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return userNotAuthorizedToStatement();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isInformationResource(String uri) {
|
|
||||||
Selector selector = createSelector(uri, VitroVocabulary.RDF_TYPE,
|
|
||||||
URI_INFORMATION_RESOURCE_TYPE);
|
|
||||||
|
|
||||||
StmtIterator stmts = null;
|
|
||||||
model.enterCriticalSection(Lock.READ);
|
|
||||||
try {
|
|
||||||
stmts = model.listStatements(selector);
|
|
||||||
if (stmts.hasNext()) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (stmts != null) {
|
|
||||||
stmts.close();
|
|
||||||
}
|
|
||||||
model.leaveCriticalSection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> getUrisOfEditors(String infoResourceUri) {
|
|
||||||
List<String> list = new ArrayList<String>();
|
|
||||||
|
|
||||||
Selector selector = createSelector(infoResourceUri,
|
|
||||||
URI_EDITOR_PROPERTY, null);
|
|
||||||
|
|
||||||
StmtIterator stmts = null;
|
|
||||||
model.enterCriticalSection(Lock.READ);
|
|
||||||
try {
|
|
||||||
stmts = model.listStatements(selector);
|
|
||||||
while (stmts.hasNext()) {
|
|
||||||
list.add(stmts.next().getObject().toString());
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
} finally {
|
|
||||||
if (stmts != null) {
|
|
||||||
stmts.close();
|
|
||||||
}
|
|
||||||
model.leaveCriticalSection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> getUrisOfAuthors(String infoResourceUri) {
|
|
||||||
List<String> list = new ArrayList<String>();
|
|
||||||
|
|
||||||
Selector selector = createSelector(infoResourceUri,
|
|
||||||
URI_IN_AUTHORSHIP_PROPERTY, 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 '" + infoResourceUri
|
|
||||||
+ "': " + objectNode);
|
|
||||||
list.addAll(getUrisOfAuthors(objectNode.asResource()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.debug("uris of authors for '" + infoResourceUri + "': " + list);
|
|
||||||
return list;
|
|
||||||
} finally {
|
|
||||||
if (stmts != null) {
|
|
||||||
stmts.close();
|
|
||||||
}
|
|
||||||
model.leaveCriticalSection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> getUrisOfFeatured(String infoResourceUri) {
|
|
||||||
List<String> list = new ArrayList<String>();
|
|
||||||
|
|
||||||
Selector selector = createSelector(infoResourceUri,
|
|
||||||
URI_FEATURES_PROPERTY, null);
|
|
||||||
|
|
||||||
StmtIterator stmts = null;
|
|
||||||
model.enterCriticalSection(Lock.READ);
|
|
||||||
try {
|
|
||||||
stmts = model.listStatements(selector);
|
|
||||||
while (stmts.hasNext()) {
|
|
||||||
list.add(stmts.next().getObject().toString());
|
|
||||||
}
|
|
||||||
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) {
|
|
||||||
List<String> list = new ArrayList<String>();
|
|
||||||
|
|
||||||
Selector selector = createSelector(authorship,
|
|
||||||
URI_LINKED_AUTHOR_PROPERTY, 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Selector createSelector(String subjectUri, String predicateUri,
|
|
||||||
String objectUri) {
|
|
||||||
Resource subject = (subjectUri == null) ? null : model
|
|
||||||
.getResource(subjectUri);
|
|
||||||
return createSelector(subject, predicateUri, objectUri);
|
|
||||||
}
|
|
||||||
|
|
||||||
private 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean anyUrisInCommon(List<String> userUris,
|
|
||||||
List<String> editorsOrAuthors) {
|
|
||||||
for (String userUri : userUris) {
|
|
||||||
if (editorsOrAuthors.contains(userUri)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private PolicyDecision authorizedSubjectEditor() {
|
|
||||||
return authorizedDecision("User is editor of the subject of the statement");
|
|
||||||
}
|
|
||||||
|
|
||||||
private PolicyDecision authorizedObjectEditor() {
|
|
||||||
return authorizedDecision("User is editor of the object of the statement");
|
|
||||||
}
|
|
||||||
|
|
||||||
private PolicyDecision authorizedSubjectAuthor() {
|
|
||||||
return authorizedDecision("User is author of the subject of the statement");
|
|
||||||
}
|
|
||||||
|
|
||||||
private PolicyDecision authorizedObjectAuthor() {
|
|
||||||
return authorizedDecision("User is author of the object of the statement");
|
|
||||||
}
|
|
||||||
|
|
||||||
private PolicyDecision authorizedSubjectFeatured() {
|
|
||||||
return authorizedDecision("User is featured in the subject of the statement");
|
|
||||||
}
|
|
||||||
|
|
||||||
private PolicyDecision authorizedObjectFeatured() {
|
|
||||||
return authorizedDecision("User is featured in the object of the statement");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,62 +0,0 @@
|
||||||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.auth.policy.setup;
|
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
import javax.servlet.ServletContextEvent;
|
|
||||||
import javax.servlet.ServletContextListener;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
|
|
||||||
import com.hp.hpl.jena.ontology.OntModel;
|
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.InformationResourceEditingPolicy;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.ServletPolicyList;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.servlet.setup.AbortStartup;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set up the InformationResourceEditingPolicy. This is tied to the SelfEditor
|
|
||||||
* identifier, but has enough of its own logic to merit its own policy class.
|
|
||||||
*/
|
|
||||||
public class InformationResourceEditingPolicySetup implements
|
|
||||||
ServletContextListener {
|
|
||||||
private static final Log log = LogFactory
|
|
||||||
.getLog(InformationResourceEditingPolicySetup.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void contextInitialized(ServletContextEvent sce) {
|
|
||||||
ServletContext ctx = sce.getServletContext();
|
|
||||||
|
|
||||||
if (AbortStartup.isStartupAborted(ctx)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
log.debug("Setting up InformationResourceEditingPolicy");
|
|
||||||
|
|
||||||
// need to make a policy and add it to the ServletContext
|
|
||||||
OntModel model = (OntModel) sce.getServletContext().getAttribute(
|
|
||||||
"jenaOntModel");
|
|
||||||
InformationResourceEditingPolicy irep = new InformationResourceEditingPolicy(
|
|
||||||
ctx, model);
|
|
||||||
ServletPolicyList.addPolicy(ctx, irep);
|
|
||||||
|
|
||||||
// don't need an IdentifierFactory if the SelfEditingPolicy is
|
|
||||||
// providing it.
|
|
||||||
|
|
||||||
log.debug("Finished setting up InformationResourceEditingPolicy: "
|
|
||||||
+ irep);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("could not run InformationResourceEditingPolicySetup: "
|
|
||||||
+ e);
|
|
||||||
AbortStartup.abortStartup(ctx);
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void contextDestroyed(ServletContextEvent sce) {
|
|
||||||
// Nothing to do.
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,231 @@
|
||||||
|
/* $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 javax.servlet.ServletContext;
|
||||||
|
|
||||||
|
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.identifier.HasAssociatedIndividual;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.identifier.Identifier;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle;
|
||||||
|
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.ifaces.Authorization;
|
||||||
|
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.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
|
||||||
|
* relationship of the object being edited to the identity of the user doing the
|
||||||
|
* editing.
|
||||||
|
*/
|
||||||
|
public abstract class AbstractRelationshipPolicy implements PolicyIface {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(AbstractRelationshipPolicy.class);
|
||||||
|
|
||||||
|
protected final ServletContext ctx;
|
||||||
|
protected final OntModel model;
|
||||||
|
|
||||||
|
public AbstractRelationshipPolicy(ServletContext ctx, OntModel model) {
|
||||||
|
this.ctx = ctx;
|
||||||
|
this.model = model;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check to see whether we are self-editing, and for which Individuals.
|
||||||
|
*/
|
||||||
|
protected List<String> getUrisOfSelfEditor(IdentifierBundle ids) {
|
||||||
|
List<String> uris = new ArrayList<String>();
|
||||||
|
if (ids != null) {
|
||||||
|
for (Identifier id : ids) {
|
||||||
|
if (id instanceof HasAssociatedIndividual) {
|
||||||
|
HasAssociatedIndividual selfEditId = (HasAssociatedIndividual) id;
|
||||||
|
if (!selfEditId.isBlacklisted()) {
|
||||||
|
uris.add(selfEditId.getAssociatedIndividualUri());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return uris;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean canModifyResource(String uri) {
|
||||||
|
return PropertyRestrictionPolicyHelper.getBean(ctx).canModifyResource(
|
||||||
|
uri, RoleLevel.SELF);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean canModifyPredicate(String uri) {
|
||||||
|
return PropertyRestrictionPolicyHelper.getBean(ctx).canModifyPredicate(
|
||||||
|
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) {
|
||||||
|
return inconclusiveDecision("No access to admin resources; cannot modify "
|
||||||
|
+ uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PolicyDecision cantModifyPredicate(String uri) {
|
||||||
|
return inconclusiveDecision("No access to admin predicates; cannot modify "
|
||||||
|
+ uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PolicyDecision userNotAuthorizedToStatement() {
|
||||||
|
return inconclusiveDecision("User has no access to this statement.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** An INCONCLUSIVE decision with a message like "PolicyClass: message". */
|
||||||
|
protected PolicyDecision inconclusiveDecision(String message) {
|
||||||
|
return new BasicPolicyDecision(Authorization.INCONCLUSIVE, getClass()
|
||||||
|
.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,380 @@
|
||||||
|
/* $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.List;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
import javax.servlet.ServletContextEvent;
|
||||||
|
import javax.servlet.ServletContextListener;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import com.hp.hpl.jena.ontology.OntModel;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.ServletPolicyList;
|
||||||
|
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.requestedAction.ifaces.RequestedAction;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.AbstractDataPropertyAction;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.AbstractObjectPropertyAction;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.servlet.setup.AbortStartup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permit self-editors to edit the properties of classes with which they share a
|
||||||
|
* special relationship. So for example:
|
||||||
|
*
|
||||||
|
* A self-editor may edit properties of an InformationResource for which he is
|
||||||
|
* an author, an editor, or in which he is featured.
|
||||||
|
*
|
||||||
|
* A self-editor may edit properties of a Project in which he plays a clinical
|
||||||
|
* role.
|
||||||
|
*
|
||||||
|
* Etc.
|
||||||
|
*
|
||||||
|
* NOTE: properties or resources which are restricted by namespace or by access
|
||||||
|
* setting will still not be editable, even if this special relationship
|
||||||
|
* applies.
|
||||||
|
*
|
||||||
|
* NOTE: This could be further generalized by building a list of authorizing
|
||||||
|
* relationships, where each relationship may specify a type of object, a
|
||||||
|
* relating property (or chain of properties), and a text message describing the
|
||||||
|
* relationship (to be used in the decision). We could go even farther and drive
|
||||||
|
* this from an XML config file, so site administrators could configure it
|
||||||
|
* themselves. A great tool for this is the one used to process the Tomcat
|
||||||
|
* server.xml file, see http://commons.apache.org/digester/
|
||||||
|
*/
|
||||||
|
public class SelfEditorRelationshipPolicy extends AbstractRelationshipPolicy
|
||||||
|
implements PolicyIface {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(SelfEditorRelationshipPolicy.class);
|
||||||
|
|
||||||
|
private static final String NS_CORE = "http://vivoweb.org/ontology/core#";
|
||||||
|
private static final String URI_INFORMATION_RESOURCE_TYPE = NS_CORE
|
||||||
|
+ "InformationResource";
|
||||||
|
private static final String URI_EDITOR_PROPERTY = "http://purl.org/ontology/bibo/editor";
|
||||||
|
private static final String URI_FEATURES_PROPERTY = NS_CORE + "features";
|
||||||
|
private static final String URI_IN_AUTHORSHIP_PROPERTY = NS_CORE
|
||||||
|
+ "informationResourceInAuthorship";
|
||||||
|
private static final String URI_LINKED_AUTHOR_PROPERTY = NS_CORE
|
||||||
|
+ "linkedAuthor";
|
||||||
|
|
||||||
|
private static final String URI_GRANT_TYPE = NS_CORE + "Grant";
|
||||||
|
private static final String URI_RELATED_ROLE_PROPERTY = NS_CORE
|
||||||
|
+ "relatedRole";
|
||||||
|
private static final String URI_PRINCIPAL_INVESTIGATOR_OF_PROPERTY = NS_CORE
|
||||||
|
+ "principalInvestigatorRoleOf";
|
||||||
|
private static final String URI_CO_PRINCIPAL_INVESTIGATOR_OF_PROPERTY = NS_CORE
|
||||||
|
+ "co-PrincipalInvestigatorRoleOf";
|
||||||
|
|
||||||
|
private static final String URI_PROJECT_TYPE = NS_CORE + "Project";
|
||||||
|
private static final String URI_SERVICE_TYPE = NS_CORE + "Service";
|
||||||
|
private static final String URI_CLINICAL_ROLE_OF_PROPERTY = NS_CORE
|
||||||
|
+ "clinicalRoleOf";
|
||||||
|
|
||||||
|
private static final String URI_PRESENTATION_TYPE = NS_CORE
|
||||||
|
+ "Presentation";
|
||||||
|
private static final String URI_PRESENTER_ROLE_OF_PROPERTY = NS_CORE
|
||||||
|
+ "presenterRoleOf";
|
||||||
|
|
||||||
|
private static final String URI_COURSE_TYPE = NS_CORE + "Course";
|
||||||
|
private static final String URI_TEACHER_ROLE_OF_PROPERTY = NS_CORE
|
||||||
|
+ "teacherRoleOf";
|
||||||
|
|
||||||
|
private static final String URI_ADVISING_RELATIONSHIP_TYPE = NS_CORE
|
||||||
|
+ "AdvisingRelationship";
|
||||||
|
private static final String URI_ADVISOR_PROPERTY = NS_CORE + "advisor";
|
||||||
|
|
||||||
|
public SelfEditorRelationshipPolicy(ServletContext ctx, OntModel model) {
|
||||||
|
super(ctx, model);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PolicyDecision isAuthorized(IdentifierBundle whoToAuth,
|
||||||
|
RequestedAction whatToAuth) {
|
||||||
|
PolicyDecision decision = null;
|
||||||
|
|
||||||
|
if (whatToAuth == null) {
|
||||||
|
decision = inconclusiveDecision("whatToAuth was null");
|
||||||
|
} else if (whatToAuth instanceof AbstractDataPropertyAction) {
|
||||||
|
decision = isAuthorized(whoToAuth,
|
||||||
|
distill((AbstractDataPropertyAction) whatToAuth));
|
||||||
|
} else if (whatToAuth instanceof AbstractObjectPropertyAction) {
|
||||||
|
decision = isAuthorized(whoToAuth,
|
||||||
|
distill((AbstractObjectPropertyAction) whatToAuth));
|
||||||
|
} else {
|
||||||
|
decision = inconclusiveDecision("Does not authorize "
|
||||||
|
+ whatToAuth.getClass().getSimpleName() + " actions");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decision == null) {
|
||||||
|
return userNotAuthorizedToStatement();
|
||||||
|
} else {
|
||||||
|
return decision;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private DistilledAction distill(AbstractDataPropertyAction action) {
|
||||||
|
return new DistilledAction(action.getPredicateUri(),
|
||||||
|
action.getSubjectUri());
|
||||||
|
}
|
||||||
|
|
||||||
|
private DistilledAction distill(AbstractObjectPropertyAction action) {
|
||||||
|
return new DistilledAction(action.uriOfPredicate, action.uriOfSubject,
|
||||||
|
action.uriOfObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PolicyDecision isAuthorized(IdentifierBundle ids,
|
||||||
|
DistilledAction action) {
|
||||||
|
List<String> userUris = getUrisOfSelfEditor(ids);
|
||||||
|
|
||||||
|
if (userUris.isEmpty()) {
|
||||||
|
return inconclusiveDecision("Not self-editing.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!canModifyPredicate(action.predicateUri)) {
|
||||||
|
return cantModifyPredicate(action.predicateUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String resourceUri : action.resourceUris) {
|
||||||
|
if (!canModifyResource(resourceUri)) {
|
||||||
|
return cantModifyResource(resourceUri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String resourceUri : action.resourceUris) {
|
||||||
|
if (isInformationResource(resourceUri)) {
|
||||||
|
if (anyUrisInCommon(userUris, getUrisOfEditors(resourceUri))) {
|
||||||
|
return authorizedEditor(resourceUri);
|
||||||
|
}
|
||||||
|
if (anyUrisInCommon(userUris, getUrisOfAuthors(resourceUri))) {
|
||||||
|
return authorizedAuthor(resourceUri);
|
||||||
|
}
|
||||||
|
if (anyUrisInCommon(userUris, getUrisOfFeatured(resourceUri))) {
|
||||||
|
return authorizedFeatured(resourceUri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isGrant(resourceUri)) {
|
||||||
|
if (anyUrisInCommon(userUris,
|
||||||
|
getUrisOfPrincipalInvestigators(resourceUri))) {
|
||||||
|
return authorizedPI(resourceUri);
|
||||||
|
}
|
||||||
|
if (anyUrisInCommon(userUris,
|
||||||
|
getUrisOfCoPrincipalInvestigators(resourceUri))) {
|
||||||
|
return authorizedCoPI(resourceUri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isProject(resourceUri) || isService(resourceUri)) {
|
||||||
|
if (anyUrisInCommon(userUris,
|
||||||
|
getUrisOfClinicalAgents(resourceUri))) {
|
||||||
|
return authorizedClinicalAgent(resourceUri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isPresentation(resourceUri)) {
|
||||||
|
if (anyUrisInCommon(userUris, getUrisOfPresenters(resourceUri))) {
|
||||||
|
return authorizedPresenter(resourceUri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isCourse(resourceUri)) {
|
||||||
|
if (anyUrisInCommon(userUris, getUrisOfTeachers(resourceUri))) {
|
||||||
|
return authorizedTeacher(resourceUri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isAdvisingRelationship(resourceUri)) {
|
||||||
|
if (anyUrisInCommon(userUris, getUrisOfAdvisors(resourceUri))) {
|
||||||
|
return authorizedAdvisor(resourceUri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return userNotAuthorizedToStatement();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// methods for InformationResource
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
private boolean isInformationResource(String resourceUri) {
|
||||||
|
return isResourceOfType(resourceUri, URI_INFORMATION_RESOURCE_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getUrisOfEditors(String resourceUri) {
|
||||||
|
return getObjectsOfProperty(resourceUri, URI_EDITOR_PROPERTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getUrisOfFeatured(String resourceUri) {
|
||||||
|
return getObjectsOfProperty(resourceUri, URI_FEATURES_PROPERTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getUrisOfAuthors(String resourceUri) {
|
||||||
|
return getObjectsOfLinkedProperty(resourceUri,
|
||||||
|
URI_IN_AUTHORSHIP_PROPERTY, URI_LINKED_AUTHOR_PROPERTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PolicyDecision authorizedEditor(String uri) {
|
||||||
|
return authorizedDecision("User is an editor of " + uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PolicyDecision authorizedAuthor(String uri) {
|
||||||
|
return authorizedDecision("User is author of " + uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PolicyDecision authorizedFeatured(String uri) {
|
||||||
|
return authorizedDecision("User is featured in " + uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// methods for Grant
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
private boolean isGrant(String resourceUri) {
|
||||||
|
return isResourceOfType(resourceUri, URI_GRANT_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getUrisOfPrincipalInvestigators(String resourceUri) {
|
||||||
|
return getObjectsOfLinkedProperty(resourceUri,
|
||||||
|
URI_RELATED_ROLE_PROPERTY,
|
||||||
|
URI_PRINCIPAL_INVESTIGATOR_OF_PROPERTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getUrisOfCoPrincipalInvestigators(String resourceUri) {
|
||||||
|
return getObjectsOfLinkedProperty(resourceUri,
|
||||||
|
URI_RELATED_ROLE_PROPERTY,
|
||||||
|
URI_CO_PRINCIPAL_INVESTIGATOR_OF_PROPERTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PolicyDecision authorizedPI(String resourceUri) {
|
||||||
|
return authorizedDecision("User is Principal Investigator of "
|
||||||
|
+ resourceUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PolicyDecision authorizedCoPI(String resourceUri) {
|
||||||
|
return authorizedDecision("User is Co-Principal Investigator of "
|
||||||
|
+ resourceUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// methods for Project or Service
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
private boolean isProject(String resourceUri) {
|
||||||
|
return isResourceOfType(resourceUri, URI_PROJECT_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isService(String resourceUri) {
|
||||||
|
return isResourceOfType(resourceUri, URI_SERVICE_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getUrisOfClinicalAgents(String resourceUri) {
|
||||||
|
return getObjectsOfLinkedProperty(resourceUri,
|
||||||
|
URI_RELATED_ROLE_PROPERTY, URI_CLINICAL_ROLE_OF_PROPERTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PolicyDecision authorizedClinicalAgent(String resourceUri) {
|
||||||
|
return authorizedDecision("User has a Clinical Role on " + resourceUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// methods for Presentation
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
private boolean isPresentation(String resourceUri) {
|
||||||
|
return isResourceOfType(resourceUri, URI_PRESENTATION_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getUrisOfPresenters(String resourceUri) {
|
||||||
|
return getObjectsOfLinkedProperty(resourceUri,
|
||||||
|
URI_RELATED_ROLE_PROPERTY, URI_PRESENTER_ROLE_OF_PROPERTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PolicyDecision authorizedPresenter(String resourceUri) {
|
||||||
|
return authorizedDecision("User is a Presenter of " + resourceUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// methods for Course
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
private boolean isCourse(String resourceUri) {
|
||||||
|
return isResourceOfType(resourceUri, URI_COURSE_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getUrisOfTeachers(String resourceUri) {
|
||||||
|
return getObjectsOfLinkedProperty(resourceUri,
|
||||||
|
URI_RELATED_ROLE_PROPERTY, URI_TEACHER_ROLE_OF_PROPERTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PolicyDecision authorizedTeacher(String resourceUri) {
|
||||||
|
return authorizedDecision("User is a Teacher of " + resourceUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// methods for AdvisingRelationship
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
private boolean isAdvisingRelationship(String resourceUri) {
|
||||||
|
return isResourceOfType(resourceUri, URI_ADVISING_RELATIONSHIP_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getUrisOfAdvisors(String resourceUri) {
|
||||||
|
return getObjectsOfProperty(resourceUri, URI_ADVISOR_PROPERTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PolicyDecision authorizedAdvisor(String resourceUri) {
|
||||||
|
return authorizedDecision("User is an Advisor of " + resourceUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// helper classes
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This allows us to treat data properties and object properties the same.
|
||||||
|
* It's just that object properties have more resourceUris.
|
||||||
|
*/
|
||||||
|
static class DistilledAction {
|
||||||
|
final String[] resourceUris;
|
||||||
|
final String predicateUri;
|
||||||
|
|
||||||
|
public DistilledAction(String predicateUri, String... resourceUris) {
|
||||||
|
this.resourceUris = resourceUris;
|
||||||
|
this.predicateUri = predicateUri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When the system starts up, install the policy. This class must be a
|
||||||
|
* listener in web.xml
|
||||||
|
*
|
||||||
|
* The CommonIdentifierBundleFactory already creates the IDs we need.
|
||||||
|
*/
|
||||||
|
public static class Setup implements ServletContextListener {
|
||||||
|
@Override
|
||||||
|
public void contextInitialized(ServletContextEvent sce) {
|
||||||
|
ServletContext ctx = sce.getServletContext();
|
||||||
|
|
||||||
|
if (AbortStartup.isStartupAborted(ctx)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
OntModel ontModel = (OntModel) sce.getServletContext()
|
||||||
|
.getAttribute("jenaOntModel");
|
||||||
|
|
||||||
|
ServletPolicyList.addPolicy(ctx,
|
||||||
|
new SelfEditorRelationshipPolicy(ctx, ontModel));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("could not run " + this.getClass().getSimpleName()
|
||||||
|
+ ": " + e);
|
||||||
|
AbortStartup.abortStartup(ctx);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contextDestroyed(ServletContextEvent sce) { /* nothing */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.auth.policy;
|
package edu.cornell.mannlib.vitro.webapp.auth.policy.specialrelationships;
|
||||||
|
|
||||||
import static edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization.AUTHORIZED;
|
import static edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization.AUTHORIZED;
|
||||||
import static edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization.INCONCLUSIVE;
|
import static edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization.INCONCLUSIVE;
|
||||||
|
@ -28,9 +28,8 @@ import com.hp.hpl.jena.rdf.model.StmtIterator;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
|
import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.identifier.ArrayIdentifierBundle;
|
import edu.cornell.mannlib.vitro.webapp.auth.identifier.ArrayIdentifierBundle;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.identifier.HasAssociatedIndividual;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle;
|
import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.identifier.SelfEditingIdentifierFactory;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.identifier.SelfEditingIdentifierFactory.SelfEditing;
|
|
||||||
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;
|
||||||
|
@ -39,15 +38,19 @@ import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAct
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.AddDataPropStmt;
|
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.AddDataPropStmt;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.AddObjectPropStmt;
|
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.AddObjectPropStmt;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.resource.AddResource;
|
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.resource.AddResource;
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.IndividualImpl;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* Check the relationships in the SelfEditorRelationshipPolicy.
|
||||||
|
*
|
||||||
|
* This only checks the relationships that deal with InformationResources.
|
||||||
|
* Testing the others seems too redundant. If we generalize this to use
|
||||||
|
* configurable relationships, then we'll be able to make more general tests as
|
||||||
|
* well.
|
||||||
*/
|
*/
|
||||||
public class InformationResourceEditingPolicyTest extends AbstractTestClass {
|
public class SelfEditorRelationshipPolicyTest extends AbstractTestClass {
|
||||||
private static final Log log = LogFactory
|
private static final Log log = LogFactory
|
||||||
.getLog(InformationResourceEditingPolicyTest.class);
|
.getLog(SelfEditorRelationshipPolicyTest.class);
|
||||||
|
|
||||||
/** Can edit properties or resources in this namespace. */
|
/** Can edit properties or resources in this namespace. */
|
||||||
private static final String NS_PERMITTED = "http://vivo.mydomain.edu/individual/";
|
private static final String NS_PERMITTED = "http://vivo.mydomain.edu/individual/";
|
||||||
|
@ -71,7 +74,8 @@ public class InformationResourceEditingPolicyTest extends AbstractTestClass {
|
||||||
/**
|
/**
|
||||||
* Where the model statements are stored for this test.
|
* Where the model statements are stored for this test.
|
||||||
*/
|
*/
|
||||||
private static final String N3_DATA_FILENAME = "resources/InformationResourceEditingPolicyTest.n3";
|
private static final String N3_DATA_FILENAME = "SelfEditorRelationship"
|
||||||
|
+ "PolicyTest.n3";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* These URIs must match the data in the N3 file.
|
* These URIs must match the data in the N3 file.
|
||||||
|
@ -96,7 +100,7 @@ public class InformationResourceEditingPolicyTest extends AbstractTestClass {
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void setupModel() throws IOException {
|
public static void setupModel() throws IOException {
|
||||||
InputStream stream = InformationResourceEditingPolicyTest.class
|
InputStream stream = SelfEditorRelationshipPolicyTest.class
|
||||||
.getResourceAsStream(N3_DATA_FILENAME);
|
.getResourceAsStream(N3_DATA_FILENAME);
|
||||||
Model model = ModelFactory.createDefaultModel();
|
Model model = ModelFactory.createDefaultModel();
|
||||||
model.read(stream, null, "N3");
|
model.read(stream, null, "N3");
|
||||||
|
@ -108,7 +112,7 @@ public class InformationResourceEditingPolicyTest extends AbstractTestClass {
|
||||||
dumpModel();
|
dumpModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
private InformationResourceEditingPolicy policy;
|
private SelfEditorRelationshipPolicy policy;
|
||||||
private RequestedAction action;
|
private RequestedAction action;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
@ -118,7 +122,7 @@ public class InformationResourceEditingPolicyTest extends AbstractTestClass {
|
||||||
.getInstance(new String[] { NS_RESTRICTED });
|
.getInstance(new String[] { NS_RESTRICTED });
|
||||||
PropertyRestrictionPolicyHelper.setBean(ctx, prph);
|
PropertyRestrictionPolicyHelper.setBean(ctx, prph);
|
||||||
|
|
||||||
policy = new InformationResourceEditingPolicy(ctx, ontModel);
|
policy = new SelfEditorRelationshipPolicy(ctx, ontModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IdentifierBundle idNobody;
|
private IdentifierBundle idNobody;
|
||||||
|
@ -148,7 +152,7 @@ public class InformationResourceEditingPolicyTest extends AbstractTestClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
// the tests
|
// boilerplate tests
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -189,12 +193,30 @@ public class InformationResourceEditingPolicyTest extends AbstractTestClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void dataPropSubjectIsNotInfoResource() {
|
public void objectPropSubjectIsRestricted() {
|
||||||
action = new AddDataPropStmt(URI_PERMITTED_RESOURCE,
|
action = new AddObjectPropStmt(URI_RESTRICTED_RESOURCE,
|
||||||
URI_PERMITTED_PREDICATE, "junk", null, null);
|
URI_PERMITTED_PREDICATE, URI_JOE_EDITED_IT);
|
||||||
assertDecision(INCONCLUSIVE, policy.isAuthorized(idJoe, action));
|
assertDecision(INCONCLUSIVE, policy.isAuthorized(idJoe, action));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void objectPropPredicateIsRestricted() {
|
||||||
|
action = new AddObjectPropStmt(URI_PERMITTED_RESOURCE,
|
||||||
|
URI_RESTRICTED_PREDICATE, URI_JOE_EDITED_IT);
|
||||||
|
assertDecision(INCONCLUSIVE, policy.isAuthorized(idJoe, action));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void objectPropObjectIsRestricted() {
|
||||||
|
action = new AddObjectPropStmt(URI_JOE_EDITED_IT,
|
||||||
|
URI_PERMITTED_PREDICATE, URI_RESTRICTED_RESOURCE);
|
||||||
|
assertDecision(INCONCLUSIVE, policy.isAuthorized(idJoe, action));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// InformationResource tests
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void dataPropSubjectIsInfoResourceButNobodyIsSelfEditing() {
|
public void dataPropSubjectIsInfoResourceButNobodyIsSelfEditing() {
|
||||||
action = new AddDataPropStmt(URI_JOE_WROTE_IT, URI_PERMITTED_PREDICATE,
|
action = new AddDataPropStmt(URI_JOE_WROTE_IT, URI_PERMITTED_PREDICATE,
|
||||||
|
@ -255,34 +277,6 @@ public class InformationResourceEditingPolicyTest extends AbstractTestClass {
|
||||||
assertDecision(AUTHORIZED, policy.isAuthorized(idBozoAndJoe, action));
|
assertDecision(AUTHORIZED, policy.isAuthorized(idBozoAndJoe, action));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void objectPropSubjectIsRestricted() {
|
|
||||||
action = new AddObjectPropStmt(URI_RESTRICTED_RESOURCE,
|
|
||||||
URI_PERMITTED_PREDICATE, URI_JOE_EDITED_IT);
|
|
||||||
assertDecision(INCONCLUSIVE, policy.isAuthorized(idJoe, action));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void objectPropPredicateIsRestricted() {
|
|
||||||
action = new AddObjectPropStmt(URI_PERMITTED_RESOURCE,
|
|
||||||
URI_RESTRICTED_PREDICATE, URI_JOE_EDITED_IT);
|
|
||||||
assertDecision(INCONCLUSIVE, policy.isAuthorized(idJoe, action));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void objectPropObjectIsRestricted() {
|
|
||||||
action = new AddObjectPropStmt(URI_JOE_EDITED_IT,
|
|
||||||
URI_PERMITTED_PREDICATE, URI_RESTRICTED_RESOURCE);
|
|
||||||
assertDecision(INCONCLUSIVE, policy.isAuthorized(idJoe, action));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void objectPropNeitherSubjectOrObjectIsInfoResource() {
|
|
||||||
action = new AddObjectPropStmt(URI_PERMITTED_RESOURCE,
|
|
||||||
URI_PERMITTED_PREDICATE, URI_PERMITTED_RESOURCE);
|
|
||||||
assertDecision(INCONCLUSIVE, policy.isAuthorized(idJoe, action));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void objectPropSubjectIsInfoResourceButNobodyIsSelfEditing() {
|
public void objectPropSubjectIsInfoResourceButNobodyIsSelfEditing() {
|
||||||
action = new AddObjectPropStmt(URI_JOE_EDITED_IT,
|
action = new AddObjectPropStmt(URI_JOE_EDITED_IT,
|
||||||
|
@ -403,16 +397,30 @@ public class InformationResourceEditingPolicyTest extends AbstractTestClass {
|
||||||
assertDecision(AUTHORIZED, policy.isAuthorized(idBozoAndJoe, action));
|
assertDecision(AUTHORIZED, policy.isAuthorized(idBozoAndJoe, action));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Other tests
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void dataPropSubjectIsNotInfoResource() {
|
||||||
|
action = new AddDataPropStmt(URI_PERMITTED_RESOURCE,
|
||||||
|
URI_PERMITTED_PREDICATE, "junk", null, null);
|
||||||
|
assertDecision(INCONCLUSIVE, policy.isAuthorized(idJoe, action));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void objectPropNeitherSubjectOrObjectIsInfoResource() {
|
||||||
|
action = new AddObjectPropStmt(URI_PERMITTED_RESOURCE,
|
||||||
|
URI_PERMITTED_PREDICATE, URI_PERMITTED_RESOURCE);
|
||||||
|
assertDecision(INCONCLUSIVE, policy.isAuthorized(idJoe, action));
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
// helper methods
|
// helper methods
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
private SelfEditing makeSelfEditingId(String uri) {
|
private HasAssociatedIndividual makeSelfEditingId(String uri) {
|
||||||
IndividualImpl ind = new IndividualImpl();
|
return new HasAssociatedIndividual(uri, null);
|
||||||
ind.setURI(uri);
|
|
||||||
SelfEditing selfEditing = new SelfEditing(ind,
|
|
||||||
SelfEditingIdentifierFactory.NOT_BLACKLISTED);
|
|
||||||
return selfEditing;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertDecision(Authorization expected, PolicyDecision decision) {
|
private void assertDecision(Authorization expected, PolicyDecision decision) {
|
Loading…
Add table
Add a link
Reference in a new issue