diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/InformationResourceEditingPolicy.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/InformationResourceEditingPolicy.java new file mode 100644 index 000000000..696cd34ed --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/InformationResourceEditingPolicy.java @@ -0,0 +1,319 @@ +/* $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 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.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 final OntModel model; + private final AdministrativeUriRestrictor restrictor; + + public InformationResourceEditingPolicy(OntModel model, + AdministrativeUriRestrictor restrictor) { + this.model = model; + this.restrictor = restrictor; + } + + @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 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. + */ + private PolicyDecision isAuthorizedForDataPropertyAction( + List userUris, AbstractDataPropertyAction action) { + String subject = action.getSubjectUri(); + String predicate = action.getPredicateUri(); + + if (!restrictor.canModifyResource(subject)) { + return cantModifyResource(subject); + } + if (!restrictor.canModifyPredicate(predicate)) { + return cantModifyPredicate(predicate); + } + + if (isInformationResource(subject)) { + if (anyUrisInCommon(userUris, getUrisOfEditors(subject))) { + return authorizedSubjectEditor(); + } + if (anyUrisInCommon(userUris, getUrisOfAuthors(subject))) { + return authorizedSubjectAuthor(); + } + } + + 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. + */ + private PolicyDecision isAuthorizedForObjectPropertyAction( + List userUris, AbstractObjectPropertyAction action) { + String subject = action.getUriOfSubject(); + String predicate = action.getUriOfPredicate(); + String object = action.getUriOfObject(); + + if (!restrictor.canModifyResource(subject)) { + return cantModifyResource(subject); + } + if (!restrictor.canModifyPredicate(predicate)) { + return cantModifyPredicate(predicate); + } + if (!restrictor.canModifyResource(object)) { + return cantModifyResource(object); + } + + if (isInformationResource(subject)) { + if (anyUrisInCommon(userUris, getUrisOfEditors(subject))) { + return authorizedSubjectEditor(); + } + if (anyUrisInCommon(userUris, getUrisOfAuthors(subject))) { + return authorizedSubjectAuthor(); + } + } + + if (isInformationResource(object)) { + if (anyUrisInCommon(userUris, getUrisOfEditors(object))) { + return authorizedObjectEditor(); + } + if (anyUrisInCommon(userUris, getUrisOfAuthors(object))) { + return authorizedObjectAuthor(); + } + } + + 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 getUrisOfEditors(String infoResourceUri) { + List list = new ArrayList(); + + 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 getUrisOfAuthors(String infoResourceUri) { + List list = new ArrayList(); + + 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(); + } + } + + /** Note that we must already be in a critical section! */ + private List getUrisOfAuthors(Resource authorship) { + List list = new ArrayList(); + + 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 userUris, + List 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"); + } + + /** + * TODO + * + *
+	 * We don't need to do resource operations.
+	 * 
+	 * We can do data or object property operations 
+	 *    if not restricted
+	 *    if the subject or object is an information resource
+	 *    if that information resource has an author or editor who is an active self-editor.
+	 * 
+ */ + + /** + * TODO + * + *
+	 * If the request is an object property operation
+	 * 
+	 * Check restrictions. If restricted, we are done.
+	 * Get the URIs of self-editors identifiers. If none, we are done.
+	 * Get the list of editors and authors for this document. Is 
+	 * Get the list of information resources that these self-editors author or edit.
+	 * If subject or object is in that set, approve.
+	 * 
+	 * If the request is a data property operations, same except there is no object.
+	 * 
+ */ + +} diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/auth/policy/InformationResourceEditingPolicyTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/auth/policy/InformationResourceEditingPolicyTest.java new file mode 100644 index 000000000..c7a8c0368 --- /dev/null +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/auth/policy/InformationResourceEditingPolicyTest.java @@ -0,0 +1,377 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.auth.policy; + +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 org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.ontology.OntModelSpec; +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.ModelFactory; +import com.hp.hpl.jena.rdf.model.Statement; +import com.hp.hpl.jena.rdf.model.StmtIterator; + +import edu.cornell.mannlib.vitro.testing.AbstractTestClass; +import edu.cornell.mannlib.vitro.webapp.auth.identifier.ArrayIdentifierBundle; +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.ifaces.Authorization; +import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyDecision; +import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.admin.ServerStatus; +import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction; +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.resource.AddResource; +import edu.cornell.mannlib.vitro.webapp.beans.IndividualImpl; +import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; + +/** + * TODO + */ +public class InformationResourceEditingPolicyTest extends AbstractTestClass { + private static final Log log = LogFactory + .getLog(InformationResourceEditingPolicyTest.class); + + /** Can edit properties or resources in this namespace. */ + private static final String NS_PERMITTED = "http://vivo.mydomain.edu/individual/"; + + /** Can't edit properties or resources in this namespace. */ + private static final String NS_RESTRICTED = VitroVocabulary.vitroURI; + + /** The resource type is not checked by the admin restrictor. */ + private static final String RESOURCE_TYPE = NS_RESTRICTED + "funkyType"; + + private static final String URI_PERMITTED_RESOURCE = NS_PERMITTED + + "permittedResource"; + private static final String URI_RESTRICTED_RESOURCE = NS_RESTRICTED + + "restrictedResource"; + + private static final String URI_PERMITTED_PREDICATE = NS_PERMITTED + + "permittedPredicate"; + private static final String URI_RESTRICTED_PREDICATE = NS_RESTRICTED + + "restrictedPredicate"; + + /** + * Where the model statements are stored for this test. + */ + private static final String N3_DATA_FILENAME = "resources/InformationResourceEditingPolicyTest.n3"; + + /** + * These URIs must match the data in the N3 file. + */ + private static final String URI_BOZO = NS_PERMITTED + "bozo"; + private static final String URI_JOE = NS_PERMITTED + "joe"; + private static final String URI_NOBODY_WROTE_IT = NS_PERMITTED + + "nobodyWroteIt"; + private static final String URI_BOZO_WROTE_IT = NS_PERMITTED + + "bozoWroteIt"; + private static final String URI_BOZO_EDITED_IT = NS_PERMITTED + + "bozoEditedIt"; + private static final String URI_JOE_WROTE_IT = NS_PERMITTED + "joeWroteIt"; + private static final String URI_JOE_EDITED_IT = NS_PERMITTED + + "joeEditedIt"; + + private static OntModel ontModel; + + @BeforeClass + public static void setupModel() throws IOException { + InputStream stream = InformationResourceEditingPolicyTest.class + .getResourceAsStream(N3_DATA_FILENAME); + Model model = ModelFactory.createDefaultModel(); + model.read(stream, null, "N3"); + stream.close(); + + ontModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_DL_MEM, + model); + ontModel.prepare(); + dumpModel(); + } + + private InformationResourceEditingPolicy policy; + private RequestedAction action; + + @Before + public void setupPolicy() { + AdministrativeUriRestrictor restrictor = new AdministrativeUriRestrictor( + null, null, null, null); + policy = new InformationResourceEditingPolicy(ontModel, restrictor); + } + + private IdentifierBundle idNobody; + private IdentifierBundle idBozo; + private IdentifierBundle idJoe; + private IdentifierBundle idBozoAndJoe; + + @Before + public void setupIdBundles() { + idNobody = new ArrayIdentifierBundle(); + + idBozo = new ArrayIdentifierBundle(); + idBozo.add(makeSelfEditingId(URI_BOZO)); + + idJoe = new ArrayIdentifierBundle(); + idJoe.add(makeSelfEditingId(URI_JOE)); + + idBozoAndJoe = new ArrayIdentifierBundle(); + idBozoAndJoe.add(makeSelfEditingId(URI_BOZO)); + idBozoAndJoe.add(makeSelfEditingId(URI_JOE)); + } + + @Before + public void setLogging() { + // setLoggerLevel(this.getClass(), Level.DEBUG); + // setLoggerLevel(InformationResourceEditingPolicy.class, Level.DEBUG); + } + + // ---------------------------------------------------------------------- + // the tests + // ---------------------------------------------------------------------- + + @Test + public void whoIsNull() { + action = new AddResource(RESOURCE_TYPE, URI_PERMITTED_RESOURCE); + assertDecision(INCONCLUSIVE, policy.isAuthorized(null, action)); + } + + @Test + public void whatIsNull() { + assertDecision(INCONCLUSIVE, policy.isAuthorized(idJoe, null)); + } + + @Test + public void notSelfEditing() { + action = new AddResource(RESOURCE_TYPE, URI_PERMITTED_RESOURCE); + assertDecision(INCONCLUSIVE, policy.isAuthorized(idNobody, action)); + } + + @Test + public void requestedActionOutOfScope() { + action = new ServerStatus(); + assertDecision(INCONCLUSIVE, policy.isAuthorized(idJoe, action)); + } + + @Test + public void dataPropSubjectIsRestricted() { + action = new AddDataPropStmt(URI_RESTRICTED_RESOURCE, + URI_PERMITTED_PREDICATE, "junk", null, null); + assertDecision(INCONCLUSIVE, policy.isAuthorized(idJoe, action)); + } + + @Test + public void dataPropPredicateIsRestricted() { + action = new AddDataPropStmt(URI_JOE_EDITED_IT, + URI_RESTRICTED_PREDICATE, "junk", null, null); + assertDecision(INCONCLUSIVE, policy.isAuthorized(idJoe, action)); + } + + @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 dataPropSubjectIsInfoResourceButNobodyIsSelfEditing() { + action = new AddDataPropStmt(URI_JOE_WROTE_IT, URI_PERMITTED_PREDICATE, + "junk", null, null); + assertDecision(INCONCLUSIVE, policy.isAuthorized(idNobody, action)); + } + + @Test + public void dataPropSubjectIsInfoResourceButNoAuthorsOrEditors() { + action = new AddDataPropStmt(URI_NOBODY_WROTE_IT, + URI_PERMITTED_PREDICATE, "junk", null, null); + assertDecision(INCONCLUSIVE, policy.isAuthorized(idJoe, action)); + assertDecision(INCONCLUSIVE, policy.isAuthorized(idBozoAndJoe, action)); + } + + @Test + public void dataPropSubjectIsInfoResourceButWrongAuthor() { + action = new AddDataPropStmt(URI_BOZO_WROTE_IT, + URI_PERMITTED_PREDICATE, "junk", null, null); + assertDecision(INCONCLUSIVE, policy.isAuthorized(idJoe, action)); + } + + @Test + public void dataPropSubjectIsInfoResourceButWrongEditor() { + action = new AddDataPropStmt(URI_BOZO_EDITED_IT, + URI_PERMITTED_PREDICATE, "junk", null, null); + assertDecision(INCONCLUSIVE, policy.isAuthorized(idJoe, action)); + } + + @Test + public void dataPropSubjectIsInfoResourceWithSelfEditingAuthor() { + action = new AddDataPropStmt(URI_JOE_WROTE_IT, URI_PERMITTED_PREDICATE, + "junk", null, null); + assertDecision(AUTHORIZED, policy.isAuthorized(idJoe, action)); + assertDecision(AUTHORIZED, policy.isAuthorized(idBozoAndJoe, action)); + } + + @Test + public void dataPropSubjectIsInfoResourceWithSelfEditingEditor() { + action = new AddDataPropStmt(URI_JOE_EDITED_IT, + URI_PERMITTED_PREDICATE, "junk", null, null); + assertDecision(AUTHORIZED, policy.isAuthorized(idJoe, 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 + public void objectPropSubjectIsInfoResourceButNobodyIsSelfEditing() { + action = new AddObjectPropStmt(URI_JOE_EDITED_IT, + URI_PERMITTED_PREDICATE, URI_PERMITTED_RESOURCE); + assertDecision(INCONCLUSIVE, policy.isAuthorized(idNobody, action)); + } + + @Test + public void objectPropSubjectIsInfoResourceButNoAuthorsOrEditors() { + action = new AddObjectPropStmt(URI_NOBODY_WROTE_IT, + URI_PERMITTED_PREDICATE, URI_PERMITTED_RESOURCE); + assertDecision(INCONCLUSIVE, policy.isAuthorized(idJoe, action)); + assertDecision(INCONCLUSIVE, policy.isAuthorized(idBozoAndJoe, action)); + } + + @Test + public void objectPropSubjectIsInfoResourceButWrongAuthor() { + action = new AddObjectPropStmt(URI_BOZO_WROTE_IT, + URI_PERMITTED_PREDICATE, URI_PERMITTED_RESOURCE); + assertDecision(INCONCLUSIVE, policy.isAuthorized(idJoe, action)); + } + + @Test + public void objectPropSubjectIsInfoResourceButWrongEditor() { + action = new AddObjectPropStmt(URI_BOZO_EDITED_IT, + URI_PERMITTED_PREDICATE, URI_PERMITTED_RESOURCE); + assertDecision(INCONCLUSIVE, policy.isAuthorized(idJoe, action)); + } + + @Test + public void objectPropSubjectIsInfoResourceWithSelfEditingAuthor() { + action = new AddObjectPropStmt(URI_JOE_WROTE_IT, + URI_PERMITTED_PREDICATE, URI_PERMITTED_RESOURCE); + assertDecision(AUTHORIZED, policy.isAuthorized(idJoe, action)); + assertDecision(AUTHORIZED, policy.isAuthorized(idBozoAndJoe, action)); + } + + @Test + public void objectPropSubjectIsInfoResourceWithSelfEditingEditor() { + action = new AddObjectPropStmt(URI_JOE_EDITED_IT, + URI_PERMITTED_PREDICATE, URI_PERMITTED_RESOURCE); + assertDecision(AUTHORIZED, policy.isAuthorized(idJoe, action)); + assertDecision(AUTHORIZED, policy.isAuthorized(idBozoAndJoe, action)); + } + + @Test + public void objectPropObjectIsInfoResourcebutNobodyIsSelfEditing() { + action = new AddObjectPropStmt(URI_PERMITTED_RESOURCE, + URI_PERMITTED_PREDICATE, URI_JOE_EDITED_IT); + assertDecision(INCONCLUSIVE, policy.isAuthorized(idNobody, action)); + } + + @Test + public void objectPropObjectIsInfoResourceButNoAuthorsOrEditors() { + action = new AddObjectPropStmt(URI_PERMITTED_RESOURCE, + URI_PERMITTED_PREDICATE, URI_NOBODY_WROTE_IT); + assertDecision(INCONCLUSIVE, policy.isAuthorized(idJoe, action)); + assertDecision(INCONCLUSIVE, policy.isAuthorized(idBozoAndJoe, action)); + } + + @Test + public void objectPropObjectIsInfoResourceButWrongAuthor() { + action = new AddObjectPropStmt(URI_PERMITTED_RESOURCE, + URI_PERMITTED_PREDICATE, URI_BOZO_WROTE_IT); + assertDecision(INCONCLUSIVE, policy.isAuthorized(idJoe, action)); + } + + @Test + public void objectPropObjectIsInfoResourceButWrongEditor() { + action = new AddObjectPropStmt(URI_PERMITTED_RESOURCE, + URI_PERMITTED_PREDICATE, URI_BOZO_EDITED_IT); + assertDecision(INCONCLUSIVE, policy.isAuthorized(idJoe, action)); + } + + @Test + public void objectPropObjectIsInfoResourceWithSelfEditingAuthor() { + action = new AddObjectPropStmt(URI_PERMITTED_RESOURCE, + URI_PERMITTED_PREDICATE, URI_JOE_WROTE_IT); + assertDecision(AUTHORIZED, policy.isAuthorized(idJoe, action)); + assertDecision(AUTHORIZED, policy.isAuthorized(idBozoAndJoe, action)); + } + + @Test + public void objectPropObjectIsInfoResourceWithSelfEditingEditor() { + action = new AddObjectPropStmt(URI_PERMITTED_RESOURCE, + URI_PERMITTED_PREDICATE, URI_JOE_EDITED_IT); + assertDecision(AUTHORIZED, policy.isAuthorized(idJoe, action)); + assertDecision(AUTHORIZED, policy.isAuthorized(idBozoAndJoe, action)); + } + + // ---------------------------------------------------------------------- + // helper methods + // ---------------------------------------------------------------------- + + private SelfEditing makeSelfEditingId(String uri) { + IndividualImpl ind = new IndividualImpl(); + ind.setURI(uri); + SelfEditing selfEditing = new SelfEditing(ind, + SelfEditingIdentifierFactory.NOT_BLACKLISTED); + return selfEditing; + } + + private void assertDecision(Authorization expected, PolicyDecision decision) { + log.debug("Decision is: " + decision); + assertNotNull("decision exists", decision); + assertEquals("authorization", expected, decision.getAuthorized()); + } + + private static void dumpModel() { + if (log.isDebugEnabled()) { + StmtIterator stmtIt = ontModel.listStatements(); + while (stmtIt.hasNext()) { + Statement stmt = stmtIt.next(); + log.debug("stmt: " + stmt); + } + } + } +} diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/auth/policy/resources/InformationResourceEditingPolicyTest.n3 b/webapp/test/edu/cornell/mannlib/vitro/webapp/auth/policy/resources/InformationResourceEditingPolicyTest.n3 new file mode 100644 index 000000000..b08ae21d0 --- /dev/null +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/auth/policy/resources/InformationResourceEditingPolicyTest.n3 @@ -0,0 +1,121 @@ +# $This file is distributed under the terms of the license in /doc/license.txt$ + +@prefix rdf: . +@prefix rdfs: . +@prefix owl: . +@prefix foaf: . +@prefix bib: . +@prefix core: . +@prefix mydomain: . + +### This file is for the test InformationResourceEditingPolicyTest.java. + +# +# Bozo +# +mydomain:bozo + a foaf:Agent ; + a foaf:Person ; + a owl:Thing ; + a core:EmeritusProfessor ; + rdfs:label "Person, Bozo" ; + foaf:firstName "Bozo" ; + foaf:lastName "Person" ; + core:editorOf mydomain:bozoEditedIt ; + core:authorInAuthorship mydomain:authorshipBozo ; + . + +# +# Joe +# +mydomain:joe + a foaf:Agent ; + a foaf:Person ; + a owl:Thing ; + a core:EmeritusProfessor ; + rdfs:label "Person, Joe" ; + foaf:firstName "Joe" ; + foaf:lastName "Person" ; + core:editorOf mydomain:joeEditedIt ; + core:authorInAuthorship mydomain:authorshipJoe ; + . + +# +# info resource with no author or editor +# +mydomain:nobodyWroteIt + a core:BlogPosting ; + a core:InformationResource ; + a bib:Article ; + a bib:Document ; + a owl:Thing ; + rdfs:label "No author or editor" ; + . + +# +# info resource with Bozo as author +# +mydomain:bozoWroteIt + a core:BlogPosting ; + a core:InformationResource ; + a bib:Article ; + a bib:Document ; + a owl:Thing ; + rdfs:label "Bozo is author" ; + core:informationResourceInAuthorship mydomain:authorshipBozo ; + . + +mydomain:authorshipBozo + a core:Authorship ; + a core:Relationship ; + a owl:Thing ; + core:linkedInformationResource mydomain:bozoWroteIt ; + core:linkedAuthor mydomain:bozo ; + . + +# +# info resource with Bozo as editor +# +mydomain:bozoEditedIt + a core:BlogPosting ; + a core:InformationResource ; + a bib:Article ; + a bib:Document ; + a owl:Thing ; + rdfs:label "Bozo is editor" ; + bib:editor mydomain:bozo ; + . + +# +# info resource with Joe as author +# +mydomain:joeWroteIt + a core:BlogPosting ; + a core:InformationResource ; + a bib:Article ; + a bib:Document ; + a owl:Thing ; + rdfs:label "Joe is author" ; + core:informationResourceInAuthorship mydomain:authorshipJoe ; + . + +mydomain:authorshipJoe + a core:Authorship ; + a core:Relationship ; + a owl:Thing ; + core:linkedInformationResource mydomain:joeWroteIt ; + core:linkedAuthor mydomain:joe ; + . + +# +# info resource with Joe as editor +# +mydomain:joeEditedIt + a core:BlogPosting ; + a core:InformationResource ; + a bib:Article ; + a bib:Document ; + a owl:Thing ; + rdfs:label "Joe is editor" ; + bib:editor mydomain:joe ; + .