/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jena.permissions.model;
import java.net.URL ;
import java.security.Principal ;
import java.util.Set ;
import org.apache.http.auth.BasicUserPrincipal ;
import org.apache.jena.graph.Node ;
import org.apache.jena.graph.Triple ;
import org.apache.jena.permissions.Factory ;
import org.apache.jena.permissions.SecurityEvaluator ;
import org.apache.jena.rdf.model.* ;
import org.apache.jena.vocabulary.RDF ;
import org.junit.Assert ;
import org.junit.Before ;
import org.junit.Test ;
/**
* Tests secured model functions against graph where only partial data is
* available to the user.
*
*/
public class SecuredModelDetailTest {
private static String NS_FMT = "http://example.com/%s";
private Model baseModel;
private SecuredModel securedModel;
private DetailEvaluator secEval;
private Property pTo = ResourceFactory
.createProperty("http://example.com/to");
private Property pFrom = ResourceFactory
.createProperty("http://example.com/from");
@Before
public void setup() {
baseModel = ModelFactory.createDefaultModel();
baseModel.removeAll();
URL url = SecuredModelDetailTest.class.getClassLoader().getResource(
"org/apache/jena/permissions/model/detail.ttl");
baseModel.read(url.toExternalForm());
secEval = new DetailEvaluator(baseModel);
securedModel = Factory.getInstance(secEval,
"http://example.com/detailModelTest", baseModel);
}
@Test
public void testContains() {
secEval.setPrincipal("darla");
/*
* darla can only add values to msg4 ex:msg4 rdf:type ex:msg; ex:to
* "darla" ; ex:from "bob" ; ex:subj "bob to darla 1"
*/
Resource s = ResourceFactory.createResource(String.format(NS_FMT,
"msg3"));
Assert.assertTrue("should contain msg3", baseModel.contains(s, null));
Assert.assertFalse("should not see msg3",
securedModel.contains(s, null));
Assert.assertTrue("Sould contain a resource msg3",
baseModel.containsResource(s));
Assert.assertFalse("Should not contain a resource msg3'",
securedModel.containsResource(s));
s = ResourceFactory.createResource(String.format(NS_FMT, "msg4"));
Assert.assertTrue("should contain msg4", baseModel.contains(s, null));
Assert.assertTrue("should see msg4", securedModel.contains(s, null));
Assert.assertTrue("Sould contain a resource msg4",
baseModel.containsResource(s));
Assert.assertTrue("Should contain a resource msg4'",
securedModel.containsResource(s));
Assert.assertTrue("Sould contain a to 'bob'",
baseModel.contains(null, pTo, "bob"));
Assert.assertFalse("Should not see to 'bob'",
securedModel.contains(null, pTo, "bob"));
Assert.assertTrue("Sould contain a from 'bob'",
baseModel.contains(null, pFrom, "bob"));
Assert.assertTrue("Should see from 'bob'",
securedModel.contains(null, pFrom, "bob"));
}
@Test
public void testListObjects() {
secEval.setPrincipal("darla");
/*
* darla can only add values to msg4 ex:msg4 rdf:type ex:msg; ex:to
* "darla" ; ex:from "bob" ; ex:subj "bob to darla 1"
*/
Assert.assertTrue(baseModel.listObjects().toList().size() > 4);
Assert.assertEquals(4, securedModel.listObjects().toList().size());
Assert.assertTrue(baseModel.listObjectsOfProperty(pFrom).toList()
.size() > 1);
Assert.assertEquals(1, securedModel.listObjectsOfProperty(pFrom)
.toList().size());
Resource s = ResourceFactory.createResource(String.format(NS_FMT,
"msg3"));
Assert.assertEquals(1, baseModel.listObjectsOfProperty(s, pFrom)
.toList().size());
Assert.assertEquals(0, securedModel.listObjectsOfProperty(s, pFrom)
.toList().size());
s = ResourceFactory.createResource(String.format(NS_FMT, "msg4"));
Assert.assertEquals(1, baseModel.listObjectsOfProperty(s, pFrom)
.toList().size());
Assert.assertEquals(1, securedModel.listObjectsOfProperty(s, pFrom)
.toList().size());
}
@Test
public void testListResources() {
secEval.setPrincipal("darla");
/*
* darla can only add values to msg4 ex:msg4 rdf:type ex:msg; ex:to
* "darla" ; ex:from "bob" ; ex:subj "bob to darla 1"
*/
Assert.assertEquals(5, baseModel.listResourcesWithProperty(pFrom)
.toList().size());
Assert.assertEquals(1, securedModel.listResourcesWithProperty(pFrom)
.toList().size());
RDFNode o = ResourceFactory.createPlainLiteral("bob");
Assert.assertEquals(3, baseModel.listResourcesWithProperty(pFrom, o)
.toList().size());
Assert.assertEquals(1, securedModel.listResourcesWithProperty(pFrom, o)
.toList().size());
Assert.assertEquals(1, baseModel.listResourcesWithProperty(pTo, o)
.toList().size());
Assert.assertEquals(0, securedModel.listResourcesWithProperty(pTo, o)
.toList().size());
Assert.assertEquals(4, baseModel.listResourcesWithProperty(null, o)
.toList().size());
Assert.assertEquals(1, securedModel.listResourcesWithProperty(null, o)
.toList().size());
o = ResourceFactory.createPlainLiteral("alice");
Assert.assertEquals(4, baseModel.listResourcesWithProperty(null, o)
.toList().size());
Assert.assertEquals(0, securedModel.listResourcesWithProperty(null, o)
.toList().size());
}
@Test
public void testListStatements() {
secEval.setPrincipal("darla");
/*
* darla can only add values to msg4 ex:msg4 rdf:type ex:msg; ex:to
* "darla" ; ex:from "bob" ; ex:subj "bob to darla 1"
*/
Assert.assertEquals(20, baseModel.listStatements().toList().size());
Assert.assertEquals(4, securedModel.listStatements().toList().size());
RDFNode o = ResourceFactory.createPlainLiteral("bob");
Assert.assertEquals(1, baseModel.listStatements(null, pTo, o).toList()
.size());
Assert.assertEquals(0, securedModel.listStatements(null, pTo, o)
.toList().size());
Assert.assertEquals(3, baseModel.listStatements(null, pFrom, o)
.toList().size());
Assert.assertEquals(1, securedModel.listStatements(null, pFrom, o)
.toList().size());
Resource s = ResourceFactory.createResource(String.format(NS_FMT,
"msg3"));
Assert.assertEquals(4, baseModel
.listStatements(s, null, (RDFNode) null).toList().size());
Assert.assertEquals(0,
securedModel.listStatements(s, null, (RDFNode) null).toList()
.size());
Assert.assertEquals(1, baseModel.listStatements(s, pTo, (RDFNode) null)
.toList().size());
Assert.assertEquals(0,
securedModel.listStatements(s, pTo, (RDFNode) null).toList()
.size());
Assert.assertEquals(0, baseModel.listStatements(s, pTo, o).toList()
.size());
Assert.assertEquals(0, securedModel.listStatements(s, pTo, o).toList()
.size());
o = ResourceFactory.createPlainLiteral("chuck");
Assert.assertEquals(1, baseModel.listStatements(s, pTo, o).toList()
.size());
Assert.assertEquals(0, securedModel.listStatements(s, pTo, o).toList()
.size());
s = ResourceFactory.createResource(String.format(NS_FMT, "msg4"));
Assert.assertEquals(4, baseModel
.listStatements(s, null, (RDFNode) null).toList().size());
Assert.assertEquals(4,
securedModel.listStatements(s, null, (RDFNode) null).toList()
.size());
Assert.assertEquals(1, baseModel.listStatements(s, pTo, (RDFNode) null)
.toList().size());
Assert.assertEquals(1,
securedModel.listStatements(s, pTo, (RDFNode) null).toList()
.size());
Assert.assertEquals(0, baseModel.listStatements(s, pTo, o).toList()
.size());
Assert.assertEquals(0, securedModel.listStatements(s, pTo, o).toList()
.size());
o = ResourceFactory.createPlainLiteral("darla");
Assert.assertEquals(1, baseModel.listStatements(s, pTo, o).toList()
.size());
Assert.assertEquals(1, securedModel.listStatements(s, pTo, o).toList()
.size());
}
@Test
public void testListSubjects() {
secEval.setPrincipal("darla");
/*
* darla can only add values to msg4 ex:msg4 rdf:type ex:msg; ex:to
* "darla" ; ex:from "bob" ; ex:subj "bob to darla 1"
*/
Assert.assertEquals(5, baseModel.listSubjects().toList().size());
Assert.assertEquals(1, securedModel.listSubjects().toList().size());
Assert.assertEquals(5, baseModel.listSubjectsWithProperty(pTo).toList()
.size());
Assert.assertEquals(1, securedModel.listSubjectsWithProperty(pTo)
.toList().size());
RDFNode o = ResourceFactory.createPlainLiteral("darla");
Assert.assertEquals(1, baseModel.listSubjectsWithProperty(pTo, o)
.toList().size());
Assert.assertEquals(1, securedModel.listSubjectsWithProperty(pTo, o)
.toList().size());
o = ResourceFactory.createPlainLiteral("bob");
Assert.assertEquals(1, baseModel.listSubjectsWithProperty(pTo, o)
.toList().size());
Assert.assertEquals(0, securedModel.listSubjectsWithProperty(pTo, o)
.toList().size());
Assert.assertEquals(4, baseModel.listSubjectsWithProperty(null, o)
.toList().size());
Assert.assertEquals(1, securedModel.listSubjectsWithProperty(null, o)
.toList().size());
}
/**
* An example evaluator that only provides access ot messages in the graph
* that are from or to the principal.
*
*/
private class DetailEvaluator implements SecurityEvaluator {
private Principal principal;
private Model model;
private RDFNode msgType = ResourceFactory
.createResource("http://example.com/msg");
private Property pTo = ResourceFactory
.createProperty("http://example.com/to");
private Property pFrom = ResourceFactory
.createProperty("http://example.com/from");
/**
*
* @param model
* The graph we are going to evaluate against.
*/
public DetailEvaluator(Model model) {
this.model = model;
}
@Override
public boolean evaluate(Object principal, Action action,
Node graphIRI) {
// we allow any action on a graph.
return true;
}
private boolean evaluate(Resource r) {
// a message is only available to sender or recipient
if (r.hasProperty(RDF.type, msgType)) {
return r.hasProperty(pTo, principal.getName())
|| r.hasProperty(pFrom,
principal.getName());
}
return true;
}
private boolean evaluate( Node node )
{
if (node.equals( Node.ANY )) {
return false; // all wild cards are false
}
if (node.isURI() || node.isBlank()) {
Resource r = model.getRDFNode( node ).asResource();
return evaluate( r );
} else {
return true;
}
}
private boolean evaluate(Triple triple) {
return evaluate(triple.getSubject())
&& evaluate(triple.getObject())
&& evaluate(triple.getPredicate());
}
@Override
public boolean evaluate(Object principal, Action action,
Node graphIRI, Triple triple) {
return evaluate(triple);
}
@Override
public boolean evaluate(Object principal, Set<Action> actions,
Node graphIRI) {
return true;
}
@Override
public boolean evaluate(Object principal, Set<Action> actions,
Node graphIRI, Triple triple) {
return evaluate(triple);
}
@Override
public boolean evaluateAny(Object principal, Set<Action> actions,
Node graphIRI) {
return true;
}
@Override
public boolean evaluateAny(Object principal, Set<Action> actions,
Node graphIRI, Triple triple) {
return evaluate(triple);
}
@Override
public boolean evaluateUpdate(Object principal, Node graphIRI,
Triple from, Triple to) {
return evaluate(from) && evaluate(to);
}
public void setPrincipal(String userName) {
if (userName == null) {
principal = null;
}
principal = new BasicUserPrincipal(userName);
}
@Override
public Principal getPrincipal() {
return principal;
}
@Override
public boolean isPrincipalAuthenticated(Object principal) {
return principal != null;
}
}
}