changeset 14:629e15b345aa

permissions mostly work. need more server-side checking.
author casties
date Fri, 13 Jul 2012 20:41:02 +0200
parents abe25edf2178
children 58357a4b86de
files src/main/java/de/mpiwg/itgroup/annotations/Actor.java src/main/java/de/mpiwg/itgroup/annotations/Annotation.java src/main/java/de/mpiwg/itgroup/annotations/neo4j/AnnotationStore.java src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorAnnotations.java src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorResourceImpl.java src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorSearch.java
diffstat 6 files changed, 585 insertions(+), 528 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/de/mpiwg/itgroup/annotations/Actor.java	Fri Jul 13 17:22:05 2012 +0200
+++ b/src/main/java/de/mpiwg/itgroup/annotations/Actor.java	Fri Jul 13 20:41:02 2012 +0200
@@ -7,19 +7,37 @@
 
 /**
  * @author casties
- *
+ * 
  */
 public abstract class Actor {
 
     public String uri;
     public String name;
     public String id;
-    
+
     /**
      * @return if this Actor is a Group
      */
     public abstract boolean isGroup();
-    
+
+    /**
+     * Returns if this Actor is equivalent to an Actor with this id. If this is
+     * a Group returns true when the Person is in the Group.
+     * 
+     * @param userId
+     * @return
+     */
+    public boolean isEquivalentWith(String userId) {
+        if (userId == null) return false;
+        if (userId.equals(getIdString())) {
+            return true;
+        }
+        if (isGroup()) {
+            // TODO: check if person in group
+        }
+        return false;
+    }
+
     /**
      * @return the uri
      */
@@ -33,26 +51,30 @@
      * @return the uri
      */
     public String getUriString() {
-    	if (uri == null) {
-    		return getUriFromId(id, isGroup());
-    	}
+        if (uri == null) {
+            return getUriFromId(id, isGroup());
+        }
         return uri;
     }
 
     /**
-     * @param uri the uri to set
+     * @param uri
+     *            the uri to set
      */
     public void setUri(String uri) {
         this.uri = uri;
     }
+
     /**
      * @return the name
      */
     public String getName() {
         return name;
     }
+
     /**
-     * @param name the name to set
+     * @param name
+     *            the name to set
      */
     public void setName(String name) {
         this.name = name;
@@ -64,21 +86,22 @@
     public String getId() {
         return id;
     }
-    
+
     /**
      * Returns id as a String starting with "group:" for groups.
      * 
      * @return
      */
     public abstract String getIdString();
-    
+
     /**
-     * @param id the id to set
+     * @param id
+     *            the id to set
      */
     public void setId(String id) {
         this.id = id;
     }
-    
+
     /**
      * Returns a short id from an uri.
      * 
@@ -109,8 +132,8 @@
         if (isGroup) {
             prefix = NS.MPIWG_GROUPS_URL;
         }
-        if (id != null && ! id.startsWith("http://")) {
-            uri = prefix + id; 
+        if (id != null && !id.startsWith("http://")) {
+            uri = prefix + id;
         }
         return uri;
     }
--- a/src/main/java/de/mpiwg/itgroup/annotations/Annotation.java	Fri Jul 13 17:22:05 2012 +0200
+++ b/src/main/java/de/mpiwg/itgroup/annotations/Annotation.java	Fri Jul 13 20:41:02 2012 +0200
@@ -80,6 +80,53 @@
      */
     protected Actor readPermission;
     
+    
+    /**
+     * Returns if the requested action is allowed on this annotation.
+     * 
+     * @param action
+     * @param userId
+     * @return
+     */
+    public boolean isActionAllowed(String action, String userId) {
+        if (action.equals("read")) {
+            Actor reader = getReadPermission();
+            if (reader == null) {
+                return true;
+            } else {
+                return reader.isEquivalentWith(userId);
+            }
+        } else if (action.equals("update")) {
+            // require at least an authenticated user
+            if (userId == null) return false;
+            Actor updater = getUpdatePermission();
+            if (updater == null) {
+                return true;
+            } else {
+                return updater.isEquivalentWith(userId);
+            }
+        } else if (action.equals("delete")) {
+            // require at least an authenticated user
+            if (userId == null) return false;
+            Actor updater = getUpdatePermission();
+            if (updater == null) {
+                return true;
+            } else {
+                return updater.isEquivalentWith(userId);
+            }
+        } else if (action.equals("admin")) {
+            // require at least an authenticated user
+            if (userId == null) return false;
+            Actor admin = getAdminPermission();
+            if (admin == null) {
+                return true;
+            } else {
+                return admin.isEquivalentWith(userId);
+            }
+        }
+        return false;
+    }
+    
     /**
      * @return the uri
      */
--- a/src/main/java/de/mpiwg/itgroup/annotations/neo4j/AnnotationStore.java	Fri Jul 13 17:22:05 2012 +0200
+++ b/src/main/java/de/mpiwg/itgroup/annotations/neo4j/AnnotationStore.java	Fri Jul 13 20:41:02 2012 +0200
@@ -29,496 +29,467 @@
  */
 public class AnnotationStore {
 
-	protected static Logger logger = Logger.getLogger(AnnotationStore.class);
+    protected static Logger logger = Logger.getLogger(AnnotationStore.class);
+
+    protected GraphDatabaseService graphDb;
 
-	protected GraphDatabaseService graphDb;
+    public static enum NodeTypes {
+        ANNOTATION, PERSON, TARGET
+    }
 
-	public static enum NodeTypes {
-		ANNOTATION, PERSON, TARGET
-	}
+    protected List<Index<Node>> nodeIndexes;
+
+    public static enum RelationTypes implements RelationshipType {
+        ANNOTATES, CREATED, PERMITS_ADMIN, PERMITS_DELETE, PERMITS_UPDATE, PERMITS_READ
+    }
+
+    public static String ANNOTATION_URI_BASE = "http://entities.mpiwg-berlin.mpg.de/annotations/";
 
-	protected List<Index<Node>> nodeIndexes;
+    public AnnotationStore(GraphDatabaseService graphDb) {
+        super();
+        this.graphDb = graphDb;
+        nodeIndexes = new ArrayList<Index<Node>>(3);
+        // List.set(enum.ordinal(), val) seems not to work.
+        nodeIndexes.add(NodeTypes.ANNOTATION.ordinal(), graphDb.index().forNodes("annotations"));
+        nodeIndexes.add(NodeTypes.PERSON.ordinal(), graphDb.index().forNodes("persons"));
+        nodeIndexes.add(NodeTypes.TARGET.ordinal(), graphDb.index().forNodes("targets"));
+    }
 
-	public static enum RelationTypes implements RelationshipType {
-		ANNOTATES, CREATED, PERMITS_ADMIN, PERMITS_DELETE, PERMITS_UPDATE, PERMITS_READ
-	}
+    protected Index<Node> getNodeIndex(NodeTypes type) {
+        return nodeIndexes.get(type.ordinal());
+    }
 
-	public static String ANNOTATION_URI_BASE = "http://entities.mpiwg-berlin.mpg.de/annotations/";
+    /**
+     * Returns the Annotation with the given id.
+     * 
+     * @param id
+     * @return
+     */
+    public Annotation getAnnotationById(String id) {
+        Node annotNode = getNodeIndex(NodeTypes.ANNOTATION).get("id", id).getSingle();
+        Annotation annot = createAnnotationFromNode(annotNode);
+        return annot;
+    }
 
-	public AnnotationStore(GraphDatabaseService graphDb) {
-		super();
-		this.graphDb = graphDb;
-		nodeIndexes = new ArrayList<Index<Node>>(3);
-		// List.set(enum.ordinal(), val) seems not to work.
-		nodeIndexes.add(NodeTypes.ANNOTATION.ordinal(), graphDb.index()
-				.forNodes("annotations"));
-		nodeIndexes.add(NodeTypes.PERSON.ordinal(),
-				graphDb.index().forNodes("persons"));
-		nodeIndexes.add(NodeTypes.TARGET.ordinal(),
-				graphDb.index().forNodes("targets"));
-	}
-
-	protected Index<Node> getNodeIndex(NodeTypes type) {
-		return nodeIndexes.get(type.ordinal());
-	}
-
-	/**
-	 * Returns the Annotation with the given id.
-	 * 
-	 * @param id
-	 * @return
-	 */
-	public Annotation getAnnotationById(String id) {
-		Node annotNode = getNodeIndex(NodeTypes.ANNOTATION).get("id", id)
-				.getSingle();
-		Annotation annot = createAnnotationFromNode(annotNode);
-		return annot;
-	}
+    /**
+     * Returns an Annotation object from an annotation-Node.
+     * 
+     * @param annotNode
+     * @return
+     */
+    public Annotation createAnnotationFromNode(Node annotNode) {
+        Annotation annot = new Annotation();
+        annot.setUri((String) annotNode.getProperty("id", null));
+        annot.setBodyText((String) annotNode.getProperty("bodyText", null));
+        annot.setBodyUri((String) annotNode.getProperty("bodyUri", null));
+        // get annotation target from relation
+        Relationship targetRel = getRelation(annotNode, RelationTypes.ANNOTATES, null);
+        if (targetRel != null) {
+            Node target = targetRel.getEndNode();
+            annot.setTargetBaseUri((String) target.getProperty("uri", null));
+        } else {
+            logger.error("annotation " + annotNode + " has no target node!");
+        }
+        annot.setTargetFragment((String) annotNode.getProperty("targetFragment", null));
+        String ft = (String) annotNode.getProperty("fragmentType", null);
+        if (ft != null) {
+            annot.setFragmentType(FragmentTypes.valueOf(ft));
+        }
+        // get creator from relation
+        Relationship creatorRel = getRelation(annotNode, RelationTypes.CREATED, null);
+        if (creatorRel != null) {
+            Node creatorNode = creatorRel.getStartNode();
+            Actor creator = createActorFromNode(creatorNode);
+            annot.setCreator(creator);
+        } else {
+            logger.error("annotation " + annotNode + " has no creator node!");
+        }
+        // get creation date
+        annot.setCreated((String) annotNode.getProperty("created", null));
+        // get permissions
+        Relationship adminRel = getRelation(annotNode, RelationTypes.PERMITS_ADMIN, null);
+        if (adminRel != null) {
+            Node adminNode = adminRel.getEndNode();
+            Actor admin = createActorFromNode(adminNode);
+            annot.setAdminPermission(admin);
+        }
+        Relationship deleteRel = getRelation(annotNode, RelationTypes.PERMITS_DELETE, null);
+        if (deleteRel != null) {
+            Node deleteNode = deleteRel.getEndNode();
+            Actor delete = createActorFromNode(deleteNode);
+            annot.setDeletePermission(delete);
+        }
+        Relationship updateRel = getRelation(annotNode, RelationTypes.PERMITS_UPDATE, null);
+        if (updateRel != null) {
+            Node updateNode = updateRel.getEndNode();
+            Actor update = createActorFromNode(updateNode);
+            annot.setUpdatePermission(update);
+        }
+        Relationship readRel = getRelation(annotNode, RelationTypes.PERMITS_READ, null);
+        if (readRel != null) {
+            Node readNode = readRel.getEndNode();
+            Actor read = createActorFromNode(readNode);
+            annot.setReadPermission(read);
+        }
 
-	/**
-	 * Returns an Annotation object from an annotation-Node.
-	 * 
-	 * @param annotNode
-	 * @return
-	 */
-	public Annotation createAnnotationFromNode(Node annotNode) {
-		Annotation annot = new Annotation();
-		annot.setUri((String) annotNode.getProperty("id", null));
-		annot.setBodyText((String) annotNode.getProperty("bodyText", null));
-		annot.setBodyUri((String) annotNode.getProperty("bodyUri", null));
-		// get annotation target from relation
-		Relationship targetRel = getRelation(annotNode,
-				RelationTypes.ANNOTATES, null);
-		if (targetRel != null) {
-			Node target = targetRel.getEndNode();
-			annot.setTargetBaseUri((String) target.getProperty("uri", null));
-		} else {
-			logger.error("annotation " + annotNode + " has no target node!");
-		}
-		annot.setTargetFragment((String) annotNode.getProperty(
-				"targetFragment", null));
-		String ft = (String) annotNode.getProperty("fragmentType", null);
-		if (ft != null) {
-			annot.setFragmentType(FragmentTypes.valueOf(ft));
-		}
-		// get creator from relation
-		Relationship creatorRel = getRelation(annotNode, RelationTypes.CREATED,
-				null);
-		if (creatorRel != null) {
-			Node creatorNode = creatorRel.getStartNode();
-			Actor creator = createActorFromNode(creatorNode);
-			annot.setCreator(creator);
-		} else {
-			logger.error("annotation " + annotNode + " has no creator node!");
-		}
-		// get creation date
-		annot.setCreated((String) annotNode.getProperty("created", null));
-		// get permissions
-		Relationship adminRel = getRelation(annotNode,
-				RelationTypes.PERMITS_ADMIN, null);
-		if (adminRel != null) {
-			Node adminNode = adminRel.getEndNode();
-			Actor admin = createActorFromNode(adminNode);
-			annot.setAdminPermission(admin);
-		}
-		Relationship deleteRel = getRelation(annotNode,
-				RelationTypes.PERMITS_DELETE, null);
-		if (deleteRel != null) {
-			Node deleteNode = deleteRel.getEndNode();
-			Actor delete = createActorFromNode(deleteNode);
-			annot.setDeletePermission(delete);
-		}
-		Relationship updateRel = getRelation(annotNode,
-				RelationTypes.PERMITS_UPDATE, null);
-		if (updateRel != null) {
-			Node updateNode = updateRel.getEndNode();
-			Actor update = createActorFromNode(updateNode);
-			annot.setUpdatePermission(update);
-		}
-		Relationship readRel = getRelation(annotNode,
-				RelationTypes.PERMITS_READ, null);
-		if (readRel != null) {
-			Node readNode = readRel.getEndNode();
-			Actor read = createActorFromNode(readNode);
-			annot.setReadPermission(read);
-		}
+        return annot;
+    }
+
+    /**
+     * Returns an Actor object from a node.
+     * 
+     * @param actorNode
+     * @return
+     */
+    protected Actor createActorFromNode(Node actorNode) {
+        String uri = (String) actorNode.getProperty("uri", null);
+        String name = (String) actorNode.getProperty("name", null);
+        String type = (String) actorNode.getProperty("TYPE", null);
+        if (type != null && type.equals("PERSON")) {
+            return new Person(uri, name);
+        } else if (type != null && type.equals("GROUP")) {
+            return new Group(uri, name);
+        }
+        return null;
+    }
 
-		return annot;
-	}
+    /**
+     * Store a new annotation in the store or update an existing one. Returns
+     * the stored annotation.
+     * 
+     * @param annot
+     * @return
+     */
+    public Annotation storeAnnotation(Annotation annot) {
+        Node annotNode = null;
+        Transaction tx = graphDb.beginTx();
+        try {
+            /*
+             * create or get the annotation
+             */
+            String id = annot.getUri();
+            if (id == null) {
+                id = createRessourceURI("annot:");
+            }
+            annotNode = getOrCreateAnnotationNode(id);
 
-	/**
-	 * Returns an Actor object from a node.
-	 * 
-	 * @param actorNode
-	 * @return
-	 */
-	protected Actor createActorFromNode(Node actorNode) {
-		String uri = (String) actorNode.getProperty("uri", null);
-		String name = (String) actorNode.getProperty("name", null);
-		String type = (String) actorNode.getProperty("TYPE", null);
-		if (type != null && type.equals("PERSON")) {
-			return new Person(uri, name);
-		} else if (type != null && type.equals("GROUP")) {
-			return new Group(uri, name);
-		}
-		return null;
-	}
+            /*
+             * the annotation body
+             */
+            String bodyText = annot.getBodyText();
+            if (bodyText != null) {
+                annotNode.setProperty("bodyText", bodyText);
+            }
+            String bodyUri = annot.getBodyUri();
+            if (bodyUri != null) {
+                annotNode.setProperty("bodyUri", bodyUri);
+            }
 
-	/**
-	 * Store a new annotation in the store or update an existing one. Returns
-	 * the stored annotation.
-	 * 
-	 * @param annot
-	 * @return
-	 */
-	public Annotation storeAnnotation(Annotation annot) {
-		Node annotNode = null;
-		Transaction tx = graphDb.beginTx();
-		try {
-			/*
-			 * create or get the annotation
-			 */
-			String id = annot.getUri();
-			if (id == null) {
-				id = createRessourceURI("annot:");
-			}
-			annotNode = getOrCreateAnnotationNode(id);
+            /*
+             * the annotation target
+             */
+            String targetBaseUri = annot.getTargetBaseUri();
+            if (targetBaseUri != null) {
+                Node target = getOrCreateTargetNode(targetBaseUri);
+                getOrCreateRelation(annotNode, RelationTypes.ANNOTATES, target);
+            }
 
-			/*
-			 * the annotation body
-			 */
-			String bodyText = annot.getBodyText();
-			if (bodyText != null) {
-				annotNode.setProperty("bodyText", bodyText);
-			}
-			String bodyUri = annot.getBodyUri();
-			if (bodyUri != null) {
-				annotNode.setProperty("bodyUri", bodyUri);
-			}
-
-			/*
-			 * the annotation target
-			 */
-			String targetBaseUri = annot.getTargetBaseUri();
-			if (targetBaseUri != null) {
-				Node target = getOrCreateTargetNode(targetBaseUri);
-				getOrCreateRelation(annotNode, RelationTypes.ANNOTATES, target);
-			}
+            /*
+             * The fragment part of the annotation target.
+             */
+            String targetFragment = annot.getTargetFragment();
+            FragmentTypes fragmentType = annot.getFragmentType();
+            if (targetFragment != null) {
+                annotNode.setProperty("targetFragment", targetFragment);
+                annotNode.setProperty("fragmentType", fragmentType.name());
+            }
 
-			/*
-			 * The fragment part of the annotation target.
-			 */
-			String targetFragment = annot.getTargetFragment();
-			FragmentTypes fragmentType = annot.getFragmentType();
-			if (targetFragment != null) {
-				annotNode.setProperty("targetFragment", targetFragment);
-				annotNode.setProperty("fragmentType", fragmentType.name());
-			}
+            /*
+             * The creator of this annotation.
+             */
+            Actor creator = annot.getCreator();
+            if (creator != null) {
+                Node creatorNode = getOrCreatePersonNode(creator);
+                getOrCreateRelation(creatorNode, RelationTypes.CREATED, annotNode);
+            }
 
-			/*
-			 * The creator of this annotation.
-			 */
-			Actor creator = annot.getCreator();
-			if (creator != null) {
-				Node creatorNode = getOrCreatePersonNode(creator);
-				getOrCreateRelation(creatorNode, RelationTypes.CREATED,
-						annotNode);
-			}
+            /*
+             * The creation date of this annotation.
+             */
+            String created = annot.getCreated();
+            if (created != null) {
+                annotNode.setProperty("created", created);
+            }
 
-			/*
-			 * The creation date of this annotation.
-			 */
-			String created = annot.getCreated();
-			if (created != null) {
-				annotNode.setProperty("created", created);
-			}
+            /*
+             * Permissions for this annotation.
+             */
+            setPermissionRelation(annotNode, RelationTypes.PERMITS_ADMIN, annot.getAdminPermission());
+            setPermissionRelation(annotNode, RelationTypes.PERMITS_DELETE, annot.getDeletePermission());
+            setPermissionRelation(annotNode, RelationTypes.PERMITS_UPDATE, annot.getUpdatePermission());
+            setPermissionRelation(annotNode, RelationTypes.PERMITS_READ, annot.getReadPermission());
 
-			/*
-			 * Permissions for this annotation.
-			 */
-			setPermissionRelation(annotNode, RelationTypes.PERMITS_ADMIN,
-					annot.getAdminPermission());
-			setPermissionRelation(annotNode, RelationTypes.PERMITS_DELETE,
-					annot.getDeletePermission());
-			setPermissionRelation(annotNode, RelationTypes.PERMITS_UPDATE,
-					annot.getUpdatePermission());
-			setPermissionRelation(annotNode, RelationTypes.PERMITS_READ,
-					annot.getReadPermission());
+            tx.success();
+        } finally {
+            tx.finish();
+        }
 
-			tx.success();
-		} finally {
-			tx.finish();
-		}
-
-		// re-read and return annotation
-		Annotation storedAnnot = createAnnotationFromNode(annotNode);
-		return storedAnnot;
-	}
+        // re-read and return annotation
+        Annotation storedAnnot = createAnnotationFromNode(annotNode);
+        return storedAnnot;
+    }
 
-	/**
-	 * Deletes the annotation with the given id.
-	 * 
-	 * @param id
-	 */
-	public void deleteById(String id) {
-		Node annotNode = getNodeIndex(NodeTypes.ANNOTATION).get("id", id)
-				.getSingle();
-		if (annotNode != null) {
-			// delete related objects
-			Transaction tx = graphDb.beginTx();
-			try {
-				for (Relationship rel : annotNode.getRelationships()) {
-					// delete relation and the related node if it has no other
-					// relations
-					Node other = rel.getOtherNode(annotNode);
-					rel.delete();
-					if (!other.hasRelationship()) {
-						deleteNode(other);
-					}
-				}
-				if (!annotNode.hasRelationship()) {
-					deleteNode(annotNode);
-				} else {
-					logger.error("deleteById: unable to delete: Node still has relations.");
-				}
-				tx.success();
-			} finally {
-				tx.finish();
-			}
-		}
-	}
+    /**
+     * Deletes the annotation with the given id.
+     * 
+     * @param id
+     */
+    public void deleteById(String id) {
+        Node annotNode = getNodeIndex(NodeTypes.ANNOTATION).get("id", id).getSingle();
+        if (annotNode != null) {
+            // delete related objects
+            Transaction tx = graphDb.beginTx();
+            try {
+                for (Relationship rel : annotNode.getRelationships()) {
+                    // delete relation and the related node if it has no other
+                    // relations
+                    Node other = rel.getOtherNode(annotNode);
+                    rel.delete();
+                    if (!other.hasRelationship()) {
+                        deleteNode(other);
+                    }
+                }
+                if (!annotNode.hasRelationship()) {
+                    deleteNode(annotNode);
+                } else {
+                    logger.error("deleteById: unable to delete: Node still has relations.");
+                }
+                tx.success();
+            } finally {
+                tx.finish();
+            }
+        }
+    }
 
-	/**
-	 * Returns all annotations with the given uri and/or user.
-	 * 
-	 * @param uri
-	 * @param userUri
-	 * @param limit
-	 * @param offset
-	 * @return
-	 */
-	public List<Annotation> searchByUriUser(String targetUri, String userUri,
-			String limit, String offset) {
-		List<Annotation> annotations = new ArrayList<Annotation>();
-		if (targetUri != null) {
-			// there should be only one
-			Node target = getNodeIndex(NodeTypes.TARGET).get("uri", targetUri)
-					.getSingle();
-			if (target != null) {
-				Iterable<Relationship> relations = target
-						.getRelationships(RelationTypes.ANNOTATES);
-				for (Relationship relation : relations) {
-					Node ann = relation.getStartNode();
-					if (ann.getProperty("TYPE", "").equals("ANNOTATION")) {
-						Annotation annot = createAnnotationFromNode(ann);
-						annotations.add(annot);
-					} else {
-						logger.error("ANNOTATES relation does not start with ANNOTATION: "
-								+ ann);
-					}
-				}
-			}
-		}
-		if (userUri != null) {
-			// there should be only one
-			Node person = getNodeIndex(NodeTypes.PERSON).get("uri", userUri)
-					.getSingle();
-			if (person != null) {
-				Iterable<Relationship> relations = person
-						.getRelationships(RelationTypes.CREATED);
-				for (Relationship relation : relations) {
-					Node ann = relation.getEndNode();
-					if (ann.getProperty("TYPE", "").equals("ANNOTATION")) {
-						Annotation annot = createAnnotationFromNode(ann);
-						annotations.add(annot);
-					} else {
-						logger.error("CREATED relation does not end with ANNOTATION: "
-								+ ann);
-					}
-				}
-			}
-		}
-		return annotations;
-	}
+    /**
+     * Returns all annotations with the given uri and/or user.
+     * 
+     * @param uri
+     * @param userUri
+     * @param limit
+     * @param offset
+     * @return
+     */
+    public List<Annotation> searchByUriUser(String targetUri, String userUri, String limit, String offset) {
+        List<Annotation> annotations = new ArrayList<Annotation>();
+        if (targetUri != null) {
+            // there should be only one
+            Node target = getNodeIndex(NodeTypes.TARGET).get("uri", targetUri).getSingle();
+            if (target != null) {
+                Iterable<Relationship> relations = target.getRelationships(RelationTypes.ANNOTATES);
+                for (Relationship relation : relations) {
+                    Node ann = relation.getStartNode();
+                    if (ann.getProperty("TYPE", "").equals("ANNOTATION")) {
+                        Annotation annot = createAnnotationFromNode(ann);
+                        annotations.add(annot);
+                    } else {
+                        logger.error("ANNOTATES relation does not start with ANNOTATION: " + ann);
+                    }
+                }
+            }
+        }
+        if (userUri != null) {
+            // there should be only one
+            Node person = getNodeIndex(NodeTypes.PERSON).get("uri", userUri).getSingle();
+            if (person != null) {
+                Iterable<Relationship> relations = person.getRelationships(RelationTypes.CREATED);
+                for (Relationship relation : relations) {
+                    Node ann = relation.getEndNode();
+                    if (ann.getProperty("TYPE", "").equals("ANNOTATION")) {
+                        Annotation annot = createAnnotationFromNode(ann);
+                        annotations.add(annot);
+                    } else {
+                        logger.error("CREATED relation does not end with ANNOTATION: " + ann);
+                    }
+                }
+            }
+        }
+        return annotations;
+    }
 
-	protected Relationship getOrCreateRelation(Node start,
-			RelationshipType type, Node end) {
-		if (start.hasRelationship()) {
-			// there are relations
-			Iterable<Relationship> rels = start.getRelationships(type,
-					Direction.OUTGOING);
-			for (Relationship rel : rels) {
-				if (rel.getEndNode().equals(end)) {
-					// relation exists
-					return rel;
-				}
-			}
-		}
-		// create new one
-		Relationship rel;
-		Transaction tx = graphDb.beginTx();
-		try {
-			rel = start.createRelationshipTo(end, type);
-			tx.success();
-		} finally {
-			tx.finish();
-		}
-		return rel;
-	}
+    protected Relationship getOrCreateRelation(Node start, RelationshipType type, Node end) {
+        if (start.hasRelationship()) {
+            // there are relations
+            Iterable<Relationship> rels = start.getRelationships(type, Direction.OUTGOING);
+            for (Relationship rel : rels) {
+                if (rel.getEndNode().equals(end)) {
+                    // relation exists
+                    return rel;
+                }
+            }
+        }
+        // create new one
+        Relationship rel;
+        Transaction tx = graphDb.beginTx();
+        try {
+            rel = start.createRelationshipTo(end, type);
+            tx.success();
+        } finally {
+            tx.finish();
+        }
+        return rel;
+    }
 
-	protected Node getOrCreateAnnotationNode(String id) {
-		Index<Node> idx = getNodeIndex(NodeTypes.ANNOTATION);
-		IndexHits<Node> annotations = idx.get("id", id);
-		Node annotation = annotations.getSingle();
-		if (annotation == null) {
-			// does not exist yet
-			Transaction tx = graphDb.beginTx();
-			try {
-				annotation = graphDb.createNode();
-				annotation.setProperty("TYPE", NodeTypes.ANNOTATION.name());
-				annotation.setProperty("id", id);
-				idx.add(annotation, "id", id);
-				tx.success();
-			} finally {
-				tx.finish();
-			}
-		}
-		return annotation;
-	}
+    protected Node getOrCreateAnnotationNode(String id) {
+        Index<Node> idx = getNodeIndex(NodeTypes.ANNOTATION);
+        IndexHits<Node> annotations = idx.get("id", id);
+        Node annotation = annotations.getSingle();
+        if (annotation == null) {
+            // does not exist yet
+            Transaction tx = graphDb.beginTx();
+            try {
+                annotation = graphDb.createNode();
+                annotation.setProperty("TYPE", NodeTypes.ANNOTATION.name());
+                annotation.setProperty("id", id);
+                idx.add(annotation, "id", id);
+                tx.success();
+            } finally {
+                tx.finish();
+            }
+        }
+        return annotation;
+    }
 
-	protected Node getOrCreateTargetNode(String uri) {
-		Index<Node> idx = getNodeIndex(NodeTypes.TARGET);
-		IndexHits<Node> targets = idx.get("uri", uri);
-		Node target = targets.getSingle();
-		if (target == null) {
-			// does not exist yet
-			Transaction tx = graphDb.beginTx();
-			try {
-				target = graphDb.createNode();
-				target.setProperty("TYPE", NodeTypes.TARGET.name());
-				target.setProperty("uri", uri);
-				idx.add(target, "uri", uri);
-				tx.success();
-			} finally {
-				tx.finish();
-			}
-		}
-		return target;
-	}
+    protected Node getOrCreateTargetNode(String uri) {
+        Index<Node> idx = getNodeIndex(NodeTypes.TARGET);
+        IndexHits<Node> targets = idx.get("uri", uri);
+        Node target = targets.getSingle();
+        if (target == null) {
+            // does not exist yet
+            Transaction tx = graphDb.beginTx();
+            try {
+                target = graphDb.createNode();
+                target.setProperty("TYPE", NodeTypes.TARGET.name());
+                target.setProperty("uri", uri);
+                idx.add(target, "uri", uri);
+                tx.success();
+            } finally {
+                tx.finish();
+            }
+        }
+        return target;
+    }
 
-	protected Node getOrCreatePersonNode(Actor actor) {
-		// Person is identified by URI
-		String uri = actor.getUriString();
-		String name = actor.getName();
-		Index<Node> idx = getNodeIndex(NodeTypes.PERSON);
-		IndexHits<Node> persons = idx.get("uri", uri);
-		Node person = persons.getSingle();
-		if (person == null) {
-			// does not exist yet
-			Transaction tx = graphDb.beginTx();
-			try {
-				person = graphDb.createNode();
-				person.setProperty("TYPE", NodeTypes.PERSON.name());
-				person.setProperty("uri", uri);
-				idx.add(person, "uri", uri);
-				if (name != null) {
-					person.setProperty("name", name);
-				}
-				tx.success();
-			} finally {
-				tx.finish();
-			}
-		}
-		return person;
-	}
+    protected Node getOrCreatePersonNode(Actor actor) {
+        // Person is identified by URI
+        String uri = actor.getUriString();
+        String name = actor.getName();
+        Index<Node> idx = getNodeIndex(NodeTypes.PERSON);
+        IndexHits<Node> persons = idx.get("uri", uri);
+        Node person = persons.getSingle();
+        if (person == null) {
+            // does not exist yet
+            Transaction tx = graphDb.beginTx();
+            try {
+                person = graphDb.createNode();
+                person.setProperty("TYPE", NodeTypes.PERSON.name());
+                person.setProperty("uri", uri);
+                idx.add(person, "uri", uri);
+                if (name != null) {
+                    person.setProperty("name", name);
+                }
+                tx.success();
+            } finally {
+                tx.finish();
+            }
+        }
+        return person;
+    }
 
-	/**
-	 * Create or update permissions relations for an annotation.
-	 * 
-	 * @param annotNode
-	 * @param type
-	 * @param annot
-	 */
-	protected void setPermissionRelation(Node annotNode, RelationTypes type,
-			Actor actor) {
-		Node newActorNode = null;
-		if (actor != null) {
-			newActorNode = getOrCreatePersonNode(actor);
-		}
-		Relationship rel = getRelation(annotNode, type, null);
-		if (rel != null) {
-			// relation exists
-			Node oldActorNode = rel.getEndNode();
-			if (!oldActorNode.equals(newActorNode)) {
-				// new admin is different
-				rel.delete();
-				if (newActorNode != null) {
-					rel = getOrCreateRelation(annotNode, type, newActorNode);
-				}
-			}
-		} else {
-			// no relation yet
-			if (newActorNode != null) {
-				rel = getOrCreateRelation(annotNode, type, newActorNode);
-			}
-		}
-	}
+    /**
+     * Create or update permissions relations for an annotation.
+     * 
+     * @param annotNode
+     * @param type
+     * @param annot
+     */
+    protected void setPermissionRelation(Node annotNode, RelationTypes type, Actor actor) {
+        Node newActorNode = null;
+        if (actor != null) {
+            newActorNode = getOrCreatePersonNode(actor);
+        }
+        Relationship rel = getRelation(annotNode, type, null);
+        if (rel != null) {
+            // relation exists
+            Node oldActorNode = rel.getEndNode();
+            if (!oldActorNode.equals(newActorNode)) {
+                // new admin is different
+                rel.delete();
+                if (newActorNode != null) {
+                    rel = getOrCreateRelation(annotNode, type, newActorNode);
+                }
+            }
+        } else {
+            // no relation yet
+            if (newActorNode != null) {
+                rel = getOrCreateRelation(annotNode, type, newActorNode);
+            }
+        }
+    }
 
-	/**
-	 * Unindexes and deletes given Node if it has no relations.
-	 * 
-	 * @param node
-	 */
-	protected void deleteNode(Node node) {
-		Transaction tx = graphDb.beginTx();
-		try {
-			if (node.hasRelationship()) {
-				logger.error("deleteNode: unable to delete: Node still has relations.");
-			} else {
-				String ts = (String) node.getProperty("TYPE", null);
-				try {
-					NodeTypes type = NodeTypes.valueOf(ts);
-					getNodeIndex(type).remove(node);
-				} catch (Exception e) {
-					logger.error("deleteNode: unable to get TYPE of node: "
-							+ node);
-				}
-				node.delete();
-			}
-			tx.success();
-		} finally {
-			tx.finish();
-		}
-	}
+    /**
+     * Unindexes and deletes given Node if it has no relations.
+     * 
+     * @param node
+     */
+    protected void deleteNode(Node node) {
+        Transaction tx = graphDb.beginTx();
+        try {
+            if (node.hasRelationship()) {
+                logger.error("deleteNode: unable to delete: Node still has relations.");
+            } else {
+                String ts = (String) node.getProperty("TYPE", null);
+                try {
+                    NodeTypes type = NodeTypes.valueOf(ts);
+                    getNodeIndex(type).remove(node);
+                } catch (Exception e) {
+                    logger.error("deleteNode: unable to get TYPE of node: " + node);
+                }
+                node.delete();
+            }
+            tx.success();
+        } finally {
+            tx.finish();
+        }
+    }
 
-	protected Relationship getRelation(Node start, RelationTypes type,
-			Direction direction) {
-		Iterable<Relationship> rels;
-		if (direction == null) {
-			// ignore direction
-			rels = start.getRelationships(type);
-		} else {
-			rels = start.getRelationships(type, direction);
-		}
-		for (Relationship rel : rels) {
-			return rel;
-		}
-		return null;
-	}
+    protected Relationship getRelation(Node start, RelationTypes type, Direction direction) {
+        Iterable<Relationship> rels;
+        if (direction == null) {
+            // ignore direction
+            rels = start.getRelationships(type);
+        } else {
+            rels = start.getRelationships(type, direction);
+        }
+        for (Relationship rel : rels) {
+            return rel;
+        }
+        return null;
+    }
 
-	/**
-	 * Erzeuge eine urn aus der aktuellen Zeit in millis
-	 * 
-	 * @return
-	 */
-	private String createRessourceURI(String prefix) {
+    /**
+     * Erzeuge eine urn aus der aktuellen Zeit in millis
+     * 
+     * @return
+     */
+    private String createRessourceURI(String prefix) {
 
-		Calendar cal = Calendar.getInstance();
+        Calendar cal = Calendar.getInstance();
 
-		long time = cal.getTimeInMillis();
+        long time = cal.getTimeInMillis();
 
-		return String.format("%s%s%s", ANNOTATION_URI_BASE, prefix, time);
+        return String.format("%s%s%s", ANNOTATION_URI_BASE, prefix, time);
 
-	}
+    }
 
 }
--- a/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorAnnotations.java	Fri Jul 13 17:22:05 2012 +0200
+++ b/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorAnnotations.java	Fri Jul 13 20:41:02 2012 +0200
@@ -50,33 +50,30 @@
 
         // TODO: what to return without id - list of all annotations?
 
-        // TODO: what to do with authentication?
-        boolean authenticated = isAuthenticated(entity);
-        logger.debug("request authenticated=" + authenticated);
+        // do authentication
+        String authUser = this.checkAuthToken(entity);
+        logger.debug("request authenticated=" + authUser);
 
-        Annotation annots = getAnnotationStore().getAnnotationById(id);
-        if (annots != null) {
-            // there should be only one
-            JSONObject result = createAnnotatorJson(annots);
+        Annotation annot = getAnnotationStore().getAnnotationById(id);
+        if (annot != null) {
+            if (! annot.isActionAllowed("read", authUser)) {
+                setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Not Authorized!");
+                return null;
+            }
+            JSONObject result = createAnnotatorJson(annot, (authUser == null));
             logger.debug("sending:");
             logger.debug(result);
             return new JsonRepresentation(result);
         } else {
-            JSONArray results = new JSONArray();
-            // annotator read request returns a list of annotation objects
-            logger.debug("sending:");
-            logger.debug(results);
-            return new JsonRepresentation(results);
+            // not found
+            setStatus(Status.CLIENT_ERROR_NOT_FOUND);
+            return null;
         }
     }
 
     /**
      * POST with JSON content-type.
      * 
-     * json hash: username: name des users xpointer: xpointer auf den Ausschnitt
-     * (incl. der URL des Dokumentes) text: text der annotation annoturl: url
-     * auf eine Annotation falls extern
-     * 
      * @return
      */
     @Post("json")
@@ -84,6 +81,15 @@
         logger.debug("AnnotatorAnnotations doPostJSON!");
         // set headers
         setCorsHeaders();
+        
+        // do authentication TODO: who's allowed to create? 
+        String authUser = this.checkAuthToken(entity);
+        logger.debug("request authenticated=" + authUser);
+        if (authUser == null) {
+            setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Not Authorized!");
+            return null;
+        }
+
         Annotation annot = null;
         try {
             JsonRepresentation jrep = new JsonRepresentation(entity);
@@ -114,7 +120,7 @@
          * according to https://github.com/okfn/annotator/wiki/Storage we should
          * return 303: see other. For now we return the annotation.
          */
-        JSONObject jo = createAnnotatorJson(storedAnnot);
+        JSONObject jo = createAnnotatorJson(storedAnnot, (authUser == null));
         JsonRepresentation retRep = new JsonRepresentation(jo);
         return retRep;
     }
@@ -134,13 +140,9 @@
         String id = decodeJsonId(jsonId);
         logger.debug("annotation-id=" + id);
 
-        // TODO: what to do with authentication? we should check the owner
-        boolean authenticated = isAuthenticated(entity);
-        logger.debug("request authenticated=" + authenticated);
-        if (!authenticated) {
-            setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Not Authorized!");
-            return null;
-        }
+        // do authentication
+        String authUser = this.checkAuthToken(entity);
+        logger.debug("request authenticated=" + authUser);
 
         Annotation annot = null;
         AnnotationStore store = getAnnotationStore();
@@ -157,6 +159,10 @@
                 setStatus(Status.CLIENT_ERROR_NOT_FOUND);
                 return null;
             }
+            if (! storedAnnot.isActionAllowed("update", authUser)) {
+                setStatus(Status.CLIENT_ERROR_FORBIDDEN);
+                return null;
+            }
             // update from posted JSON
             annot = updateAnnotation(storedAnnot, jo, entity);
             // store Annotation
@@ -169,7 +175,7 @@
              * this.getResponse().setLocationRef(thisUrl);
              */
             // return new annotation
-            jo = createAnnotatorJson(storedAnnot);
+            jo = createAnnotatorJson(storedAnnot, (authUser == null));
             JsonRepresentation retRep = new JsonRepresentation(jo);
             return retRep;
         } catch (JSONException e) {
@@ -197,14 +203,17 @@
         String id = decodeJsonId(jsonId);
         logger.debug("annotation-id=" + id);
 
-        // TODO: what to do with authentication? we should check the owner
-        boolean authenticated = isAuthenticated(entity);
-        logger.debug("request authenticated=" + authenticated);
-        if (!authenticated) {
-            setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Not Authorized!");
-            return null;
+        // do authentication
+        String authUser = this.checkAuthToken(entity);
+        logger.debug("request authenticated=" + authUser);
+        Annotation annot = getAnnotationStore().getAnnotationById(id);
+        if (annot != null) {
+            if (! annot.isActionAllowed("delete", authUser)) {
+                setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Not Authorized!");
+                return null;
+            }
         }
-
+        
         // delete annotation
         getAnnotationStore().deleteById(id);
         setStatus(Status.SUCCESS_NO_CONTENT);
--- a/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorResourceImpl.java	Fri Jul 13 17:22:05 2012 +0200
+++ b/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorResourceImpl.java	Fri Jul 13 20:41:02 2012 +0200
@@ -140,6 +140,7 @@
     public String checkAuthToken(Representation entity) {
         Form requestHeaders = (Form) getRequest().getAttributes().get("org.restlet.http.headers");
         String authToken = requestHeaders.getFirstValue("x-annotator-auth-token", true);
+        if (authToken == null) return null;
         // decode token first to get consumer key
         JsonToken token = new JsonTokenParser(null, null).deserialize(authToken);
         String userId = token.getParamAsPrimitive("userId").getAsString();
@@ -177,9 +178,10 @@
      * creates Annotator-JSON from an Annotation object.
      * 
      * @param annot
+     * @param forAnonymous TODO
      * @return
      */
-    public JSONObject createAnnotatorJson(Annotation annot) {
+    public JSONObject createAnnotatorJson(Annotation annot, boolean forAnonymous) {
         // return user as a JSON object (otherwise just as string)
         boolean makeUserObject = true;
         JSONObject jo = new JSONObject();
@@ -232,6 +234,9 @@
             Actor adminPerm = annot.getAdminPermission();
             if (adminPerm != null) {
                 adminPerms.put(adminPerm.getIdString());
+            } else if (forAnonymous) {
+                // set something because its not allowed for anonymous
+                adminPerms.put("not-you");
             }
             // delete
             JSONArray deletePerms = new JSONArray();
@@ -239,6 +244,9 @@
             Actor deletePerm = annot.getDeletePermission();
             if (deletePerm != null) {
                 deletePerms.put(deletePerm.getIdString());
+            } else if (forAnonymous) {
+                // set something because its not allowed for anonymous
+                deletePerms.put("not-you");
             }
             // update
             JSONArray updatePerms = new JSONArray();
@@ -246,6 +254,9 @@
             Actor updatePerm = annot.getUpdatePermission();
             if (updatePerm != null) {
                 updatePerms.put(updatePerm.getIdString());
+            } else if (forAnonymous) {
+                // set something because its not allowed for anonymous
+                updatePerms.put("not-you");
             }
             // read
             JSONArray readPerms = new JSONArray();
--- a/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorSearch.java	Fri Jul 13 17:22:05 2012 +0200
+++ b/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorSearch.java	Fri Jul 13 20:41:02 2012 +0200
@@ -15,7 +15,6 @@
 import org.restlet.resource.Get;
 
 import de.mpiwg.itgroup.annotations.Annotation;
-import de.mpiwg.itgroup.annotations.neo4j.AnnotationStore;
 
 /**
  * Implements the "search" uri of the Annotator API. see
@@ -31,8 +30,8 @@
     }
 
     /**
-     * result for JSON content-type. optional search parameters: uri user limit
-     * offset
+     * result for JSON content-type. optional search parameters: uri, user, limit,
+     * offset.
      * 
      * @param entity
      * @return
@@ -41,40 +40,37 @@
     public Representation doGetJSON(Representation entity) {
         logger.debug("AnnotatorSearch doGetJSON!");
         setCorsHeaders();
-        // TODO: what to do with authentication?
-        boolean authenticated = isAuthenticated(entity);
-        logger.debug("request authenticated=" + authenticated);
+        // do authentication
+        String authUser = this.checkAuthToken(entity);
+        logger.debug("request authenticated=" + authUser);
 
         Form form = getRequest().getResourceRef().getQueryAsForm();
         String uri = form.getFirstValue("uri");
         String user = form.getFirstValue("user");
-
         String limit = form.getFirstValue("limit");
         String offset = form.getFirstValue("offset");
 
-        AnnotationStore searcher = getAnnotationStore();
-
-        JSONArray ja;
-
-        List<Annotation> annots = searcher.searchByUriUser(uri, user, limit, offset);
-
-        ja = new JSONArray();
+        JSONArray results = new JSONArray();
+        // do search
+        logger.debug(String.format("searching for uri=%s user=%s", uri, user));
+        List<Annotation> annots = getAnnotationStore().searchByUriUser(uri, user, limit, offset);
         for (Annotation annot : annots) {
-            JSONObject jo = createAnnotatorJson(annot);
+            // check permission
+            if (!annot.isActionAllowed("read", authUser)) continue;
+            JSONObject jo = createAnnotatorJson(annot, (authUser == null));
             if (jo != null) {
-                ja.put(createAnnotatorJson(annot));
+                results.put(jo);
             } else {
                 setStatus(Status.SERVER_ERROR_INTERNAL, "JSON Error");
                 return null;
             }
         }
-
+        // assemble result object
         JSONObject result = new JSONObject();
         try {
-            result.put("rows", ja);
-            result.put("total", ja.length());
+            result.put("rows", results);
+            result.put("total", results.length());
         } catch (JSONException e) {
-            e.printStackTrace();
             setStatus(Status.SERVER_ERROR_INTERNAL, "JSON Error");
             return null;
         }