Updated fuseki example files
added documentation to example code.

Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/beb73c4a
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/beb73c4a
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/beb73c4a

Branch: refs/heads/eliminate-assignments
Commit: beb73c4a777c69dceb3317900476710399aa6bf0
Parents: e0e8dba
Author: Claude Warren <[email protected]>
Authored: Sun Feb 15 16:52:52 2015 +0000
Committer: Claude Warren <[email protected]>
Committed: Sun Feb 15 16:52:52 2015 +0000

----------------------------------------------------------------------
 .../security/example/ShiroExampleEvaluator.java | 86 +++++++++++++++++++-
 .../jena/security/example/fuseki/config.ttl     | 68 ++++++++++------
 .../jena/security/example/fuseki/shiro.ini      |  2 +-
 3 files changed, 127 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/beb73c4a/jena-security/src/example/java/org/apache/jena/security/example/ShiroExampleEvaluator.java
----------------------------------------------------------------------
diff --git 
a/jena-security/src/example/java/org/apache/jena/security/example/ShiroExampleEvaluator.java
 
b/jena-security/src/example/java/org/apache/jena/security/example/ShiroExampleEvaluator.java
index 87fca4e..1df5678 100644
--- 
a/jena-security/src/example/java/org/apache/jena/security/example/ShiroExampleEvaluator.java
+++ 
b/jena-security/src/example/java/org/apache/jena/security/example/ShiroExampleEvaluator.java
@@ -36,12 +36,15 @@ import com.hp.hpl.jena.vocabulary.RDF;
 
 /**
  * Class to use Shiro to provide credentials.
- * Used for same example as ExampleEvaluator
+ * 
+ * An example evaluator that only provides access to messages in the graph 
that 
+ * are from or to the principal.
  *
  */
 public class ShiroExampleEvaluator implements SecurityEvaluator {
 
        private static final Logger LOG = 
LoggerFactory.getLogger(ShiroExampleEvaluator.class);
+       // the model that contains the messages.
        private Model model;
        private RDFNode msgType = ResourceFactory.createResource( 
"http://example.com/msg"; );
        private Property pTo = ResourceFactory.createProperty( 
"http://example.com/to"; );
@@ -56,14 +59,29 @@ public class ShiroExampleEvaluator implements 
SecurityEvaluator {
                this.model = model;
        }
        
+       /**
+        * We allow any action on the graph itself, so this is always true.
+        */
        @Override
        public boolean evaluate(Object principal, Action action, SecNode 
graphIRI) {
                // we allow any action on a graph.
                return true;
        }
 
+       /**
+        * This is our internal check to see if the user may access the 
resource.
+        * This method is called from the evauate(Object,SecNode) method.
+        * A user may only access the resource if they are authenticated, and 
are either the
+        * sender or the recipient.
+        * Additionally the admin can always see the messages.
+        * @param principalObj
+        * @param r
+        * @return
+        */
        private boolean evaluate( Object principalObj, Resource r )
        {
+               // cast to the Subject because we know that it comes from Shiro 
and that
+               // our getPrincipal() method returns a Subject.
                Subject subject = (Subject)principalObj;
                if (! subject.isAuthenticated())
                {
@@ -73,32 +91,49 @@ public class ShiroExampleEvaluator implements 
SecurityEvaluator {
                // a message is only available to sender or recipient
                LOG.debug( "checking {}", subject.getPrincipal());
                Object principal = subject.getPrincipal();
+               
+               // We put the admin check here but it could have been done much 
earlier.
                if ("admin".equals(principal.toString()))
                {
                        return true;
                }
+               // if we are looking at a message object then check the 
restrictions.
                if (r.hasProperty( RDF.type, msgType ))
                {
                        return r.hasProperty( pTo, 
subject.getPrincipal().toString() ) ||
                                        r.hasProperty( pFrom, 
subject.getPrincipal().toString());
                }
+               // otherwise user can see the object.
                return true;    
        }
        
+       /**
+        * Check that the user can see a specific node.
+        * @param principal
+        * @param node
+        * @return
+        */
        private boolean evaluate( Object principal, SecNode node )
        {
+               // Access to wild card is false -- this forces checks to the 
acutal nodes
+               // to be returned.
+               // we could have checked for admin access here and returned 
true since the admin
+               // can see any node.
                if (node.equals( SecNode.ANY )) {
-                       return false;  // all wild cards are false
+                       return false;  
                }
                
+               // URI nodes are retrieved from the model and evaluated
                if (node.getType().equals( SecNode.Type.URI)) {
                        Resource r = model.createResource( node.getValue() );
                        return evaluate( principal, r );
                }
+               // anonymous nodes have to be retrieved from the model as 
anonymous nodes.
                else if (node.getType().equals( SecNode.Type.Anonymous)) {
                        Resource r = model.getRDFNode( NodeFactory.createAnon( 
new AnonId( node.getValue()) ) ).asResource();
                        return evaluate( principal, r );
                }
+               // anything else (literals) can be seen.
                else
                {
                        return true;
@@ -106,44 +141,91 @@ public class ShiroExampleEvaluator implements 
SecurityEvaluator {
 
        }
        
+       /**
+        * Evaluate if the user can see the triple.
+        * @param principal
+        * @param triple
+        * @return
+        */
        private boolean evaluate( Object principal, SecTriple triple ) {
+               // we could have checked here to see if the principal was the 
admin and 
+               // just returned true since the admin can perform any operation 
on any triple.
                return evaluate( principal, triple.getSubject()) &&
                                evaluate( principal, triple.getObject()) &&
                                evaluate( principal, triple.getPredicate());
        }
        
+       /**
+        * As per our design, users can do anything with triples they have 
access to, so we just
+        * ignore the action parameter.  If we were to implement rules 
restricted access based 
+        * upon action this method would sort those out appropriately.
+        */
        @Override
        public boolean evaluate(Object principal, Action action, SecNode 
graphIRI, SecTriple triple) {
+               // we could have checked here to see if the principal was the 
admin and 
+               // just returned true since the admin can perform any operation 
on any triple.
                return evaluate( principal, triple );
        }
 
+       /**
+        * As per our design, users can access any graph.  If we were to 
implement rules that 
+        * restricted user access to specific graphs, those checks would be 
here and we would 
+        * return <code>false</code> if they were not allowed to access the 
graph.  Note that this
+        * method is checking to see that the user may perform ALL the actions 
in the set on the
+        * graph.
+        */
        @Override
        public boolean evaluate(Object principal, Set<Action> actions, SecNode 
graphIRI) {
                return true;
        }
 
+       /**
+        * As per our design, users can access any triple from a message that 
is from or to them.  
+        * Since we don't have restrictions on actions this is no different 
then checking access
+        * for a single action.
+        */
        @Override
        public boolean evaluate(Object principal, Set<Action> actions, SecNode 
graphIRI,
                        SecTriple triple) {
                return evaluate( principal, triple );
        }
 
+       /**
+        * As per our design, users can access any graph.  If we were to 
implement rules that 
+        * restricted user access to specific graphs, those checks would be 
here and we would 
+        * return <code>false</code> if they were not allowed to access the 
graph.  Note that this
+        * method is checking to see that the user may perform ANY of the 
actions in the set on the
+        * graph.
+        */
        @Override
        public boolean evaluateAny(Object principal, Set<Action> actions, 
SecNode graphIRI) {
                return true;
        }
 
+       /**
+        * As per our design, users can access any triple from a message that 
is from or to them.  
+        * Since we don't have restrictions on actions this is no different 
then checking access
+        * for a single action.
+        */
        @Override
        public boolean evaluateAny(Object principal, Set<Action> actions, 
SecNode graphIRI,
                        SecTriple triple) {
                return evaluate( principal, triple );
        }
 
+       /**
+        * As per our design, users can access any triple from a message that 
is from or to them.  
+        * So for an update they can only change triples they have access to 
into other triples 
+        * they have access to. (e.g. they can not remvoe themself from the 
messsage). 
+        */
        @Override
        public boolean evaluateUpdate(Object principal, SecNode graphIRI, 
SecTriple from, SecTriple to) {
                return evaluate( principal, from ) && evaluate( principal, to );
        }
 
+       /**
+        * Return the Shiro subject.  This is the subject that Shiro currently 
has logged in.
+        */
        @Override
        public Object getPrincipal() {
                return SecurityUtils.getSubject();

http://git-wip-us.apache.org/repos/asf/jena/blob/beb73c4a/jena-security/src/example/resources/org/apache/jena/security/example/fuseki/config.ttl
----------------------------------------------------------------------
diff --git 
a/jena-security/src/example/resources/org/apache/jena/security/example/fuseki/config.ttl
 
b/jena-security/src/example/resources/org/apache/jena/security/example/fuseki/config.ttl
index 6f4a3af..a748f01 100644
--- 
a/jena-security/src/example/resources/org/apache/jena/security/example/fuseki/config.ttl
+++ 
b/jena-security/src/example/resources/org/apache/jena/security/example/fuseki/config.ttl
@@ -14,62 +14,77 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+##
+## Define all the prefixes 
+##
+
 @prefix fuseki:  <http://jena.apache.org/fuseki#> .
-@prefix tdb:     <http://jena.hpl.hp.com/2008/tdb#> .
 @prefix rdf:     <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
 @prefix rdfs:    <http://www.w3.org/2000/01/rdf-schema#> .
 @prefix ja:      <http://jena.hpl.hp.com/2005/11/Assembler#> .
 @prefix sec:    <http://apache.org/jena/security/Assembler#> .
 @prefix my:     <http://example.org/#> .
 
-#[] ja:loadClass "com.hp.hpl.jena.tdb.TDB" .
+##
+## Load the SecuredAssembler class from the security library and define 
+## the sec:Model as a subclass of ja:NamedModel.
+##
 [] ja:loadClass    "org.apache.jena.security.SecuredAssembler" .
-
-tdb:DatasetTDB  rdfs:subClassOf  ja:RDFDataset .
-tdb:GraphTDB    rdfs:subClassOf  ja:Model .
 sec:Model       rdfs:subClassOf  ja:NamedModel .
 
-my:dataset rdf:type tdb:DatasetTDB;
-    tdb:location "/tmp/myApp" ;
-    tdb:unionDefaultGraph true ;
-    .
-
-my:baseModel rdf:type tdb:GraphTDB ;
-    tdb:dataset my:dataset .   
+##
+## Define the base model that contains the unsecured data.
+##
+my:baseModel rdf:type ja:MemoryModel;
+    ja:content [ja:externalContent <file:./example.ttl>] 
+    .   
 
+##
+## Define the secured model.  This is where permissions is applied to the 
+## my:baseModel to create a model that has permission restrictions.  Note 
+## that it is using the security evaluator implementation (sec:evaluatorImpl) 
+## called my:secEvaluator which we will define next.
+##
 my:securedModel rdf:type sec:Model ;
     sec:baseModel my:baseModel ;
     ja:modelName "https://example.org/securedModel"; ;
     sec:evaluatorImpl my:secEvaluator .
   
+##
+## Define the security evaluator.  This is where we use the example 
+## ShiroExampleEvaluator.  For your production environment you will replace 
+## "org.apache.jena.security.example.ShiroExampleEvaluator"  with your 
+## SecurityEvaluator implementation.  Note that  ShiroExampleEvaluator 
constructor 
+## takes a Model argument.  We pass in the unsecured baseModel so that the 
evaluator 
+## can read it unencumbered.  Your implementation of SecurityEvaluator may 
have different 
+## parameters to meet your specific needs.
+##  
 my:secEvaluator rdf:type sec:Evaluator ;
     sec:args [  
         rdf:_1 my:baseModel ;
     ] ;
     sec:evaluatorClass 
"org.apache.jena.security.example.ShiroExampleEvaluator" .
 
+##
+## Define the dataset that we will use for in the server.
+##
 my:securedDataset rdf:type ja:RDFDataset ;
    ja:defaultGraph my:securedModel .
 
-my:fuseki rdf:type fuseki:Server ;
-   # Server-wide context parameters can be given here.
-   # For example, to set query timeouts: on a server-wide basis:
-   # Format 1: "1000" -- 1 second timeout
-   # Format 2: "10000,60000" -- 10s timeout to first result, then 60s timeout 
to for rest of query.
-   # See java doc for ARQ.queryTimeout
-   # ja:context [ ja:cxtName "arq:queryTimeout" ;  ja:cxtValue "10000" ] ;
-
-   # Load custom code (rarely needed)
-   # ja:loadClass "your.code.Class" ;
-
-   # Services available.  Only explicitly listed services are configured.
-   #  If there is a service description not linked from this list, it is 
ignored.
+##
+## Define the fuseki:Server.
+##
+my:fuskei rdf:type fuseki:Server ;
    fuseki:services (
      my:service1
    ) .
 
-    
+##
+## Define the service for the fuseki:Service.  Note that the fuseki:dataset 
served by 
+## this server is the secured dataset defined above.    
+##
 my:service1 rdf:type fuseki:Service ;
+    rdfs:label                        "My Secured Data Service" ;
     fuseki:name                       "myAppFuseki" ;       # 
http://host:port/myAppFuseki
     fuseki:serviceQuery               "query" ;    # SPARQL query service
     fuseki:serviceQuery               "sparql" ;   # SPARQL query service
@@ -80,3 +95,4 @@ my:service1 rdf:type fuseki:Service ;
     fuseki:serviceReadGraphStore      "get" ;      # SPARQL Graph store 
protocol (read only)
     fuseki:dataset                   my:securedDataset ;
     .
+    

http://git-wip-us.apache.org/repos/asf/jena/blob/beb73c4a/jena-security/src/example/resources/org/apache/jena/security/example/fuseki/shiro.ini
----------------------------------------------------------------------
diff --git 
a/jena-security/src/example/resources/org/apache/jena/security/example/fuseki/shiro.ini
 
b/jena-security/src/example/resources/org/apache/jena/security/example/fuseki/shiro.ini
index d0ce2c3..a9fbf71 100644
--- 
a/jena-security/src/example/resources/org/apache/jena/security/example/fuseki/shiro.ini
+++ 
b/jena-security/src/example/resources/org/apache/jena/security/example/fuseki/shiro.ini
@@ -40,7 +40,7 @@ darla=darla
 /$/ping   = anon
 
 ## restrict access.  Must log in with above.
-/$/** = authcBasic,user[admin]
+/$/** = authcBasic,user
 
 
 # Everything else

Reply via email to