# HG changeset patch # User casties # Date 1342204862 -7200 # Node ID 629e15b345aa40920bf2fa4ec958455f3669934d # Parent abe25edf21783320f08738697e3eb98308a0eb66 permissions mostly work. need more server-side checking. diff -r abe25edf2178 -r 629e15b345aa src/main/java/de/mpiwg/itgroup/annotations/Actor.java --- 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; } diff -r abe25edf2178 -r 629e15b345aa src/main/java/de/mpiwg/itgroup/annotations/Annotation.java --- 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 */ diff -r abe25edf2178 -r 629e15b345aa src/main/java/de/mpiwg/itgroup/annotations/neo4j/AnnotationStore.java --- 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> 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> nodeIndexes; + public AnnotationStore(GraphDatabaseService graphDb) { + super(); + this.graphDb = graphDb; + nodeIndexes = new ArrayList>(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 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>(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 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 searchByUriUser(String targetUri, String userUri, - String limit, String offset) { - List annotations = new ArrayList(); - if (targetUri != null) { - // there should be only one - Node target = getNodeIndex(NodeTypes.TARGET).get("uri", targetUri) - .getSingle(); - if (target != null) { - Iterable 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 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 searchByUriUser(String targetUri, String userUri, String limit, String offset) { + List annotations = new ArrayList(); + if (targetUri != null) { + // there should be only one + Node target = getNodeIndex(NodeTypes.TARGET).get("uri", targetUri).getSingle(); + if (target != null) { + Iterable 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 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 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 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 idx = getNodeIndex(NodeTypes.ANNOTATION); - IndexHits 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 idx = getNodeIndex(NodeTypes.ANNOTATION); + IndexHits 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 idx = getNodeIndex(NodeTypes.TARGET); - IndexHits 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 idx = getNodeIndex(NodeTypes.TARGET); + IndexHits 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 idx = getNodeIndex(NodeTypes.PERSON); - IndexHits 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 idx = getNodeIndex(NodeTypes.PERSON); + IndexHits 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 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 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); - } + } } diff -r abe25edf2178 -r 629e15b345aa src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorAnnotations.java --- 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); diff -r abe25edf2178 -r 629e15b345aa src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorResourceImpl.java --- 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(); diff -r abe25edf2178 -r 629e15b345aa src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorSearch.java --- 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 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 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; }