/* * 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; } } }