Index: src/main/java/de/mpiwg/itgroup/annotations/Actor.java
===================================================================
--- src/main/java/de/mpiwg/itgroup/annotations/Actor.java	(revision 14)
+++ src/main/java/de/mpiwg/itgroup/annotations/Actor.java	(revision 15)
@@ -4,4 +4,5 @@
 package de.mpiwg.itgroup.annotations;
 
+import de.mpiwg.itgroup.annotations.neo4j.AnnotationStore;
 import de.mpiwg.itgroup.annotations.old.NS;
 
@@ -22,17 +23,19 @@
 
     /**
-     * Returns if this Actor is equivalent to an Actor with this id. If this is
+     * Returns if this Actor is equivalent to Person person. If this is
      * a Group returns true when the Person is in the Group.
      * 
-     * @param userId
+     * @param person
+     * @param store AnnotationStore to check group membership
      * @return
      */
-    public boolean isEquivalentWith(String userId) {
-        if (userId == null) return false;
-        if (userId.equals(getIdString())) {
+    public boolean isEquivalentWith(Person person, AnnotationStore store) {
+        if (person == null) return false;
+        if (person.equals(getIdString())) {
             return true;
         }
-        if (isGroup()) {
-            // TODO: check if person in group
+        if (isGroup() && store != null) {
+            // check if person in group
+            return store.isPersonInGroup(person, (Group) this);            
         }
         return false;
Index: src/main/java/de/mpiwg/itgroup/annotations/Annotation.java
===================================================================
--- src/main/java/de/mpiwg/itgroup/annotations/Annotation.java	(revision 14)
+++ src/main/java/de/mpiwg/itgroup/annotations/Annotation.java	(revision 15)
@@ -3,4 +3,6 @@
  */
 package de.mpiwg.itgroup.annotations;
+
+import de.mpiwg.itgroup.annotations.neo4j.AnnotationStore;
 
 /**
@@ -86,8 +88,9 @@
      * 
      * @param action
-     * @param userId
+     * @param user
+     * @param store AnnotationStore to check group membership
      * @return
      */
-    public boolean isActionAllowed(String action, String userId) {
+    public boolean isActionAllowed(String action, Person user, AnnotationStore store) {
         if (action.equals("read")) {
             Actor reader = getReadPermission();
@@ -95,32 +98,32 @@
                 return true;
             } else {
-                return reader.isEquivalentWith(userId);
+                return reader.isEquivalentWith(user, store);
             }
         } else if (action.equals("update")) {
             // require at least an authenticated user
-            if (userId == null) return false;
+            if (user == null) return false;
             Actor updater = getUpdatePermission();
             if (updater == null) {
                 return true;
             } else {
-                return updater.isEquivalentWith(userId);
+                return updater.isEquivalentWith(user, store);
             }
         } else if (action.equals("delete")) {
             // require at least an authenticated user
-            if (userId == null) return false;
+            if (user == null) return false;
             Actor updater = getUpdatePermission();
             if (updater == null) {
                 return true;
             } else {
-                return updater.isEquivalentWith(userId);
+                return updater.isEquivalentWith(user, store);
             }
         } else if (action.equals("admin")) {
             // require at least an authenticated user
-            if (userId == null) return false;
+            if (user == null) return false;
             Actor admin = getAdminPermission();
             if (admin == null) {
                 return true;
             } else {
-                return admin.isEquivalentWith(userId);
+                return admin.isEquivalentWith(user, store);
             }
         }
Index: src/main/java/de/mpiwg/itgroup/annotations/Group.java
===================================================================
--- src/main/java/de/mpiwg/itgroup/annotations/Group.java	(revision 12)
+++ src/main/java/de/mpiwg/itgroup/annotations/Group.java	(revision 15)
@@ -21,4 +21,12 @@
     }
 
+    public Group(String id, String uri, String name) {
+        super();
+        this.id = id;
+        this.uri = uri;
+        this.name = name;
+    }
+
+
     @Override
     public boolean isGroup() {
Index: src/main/java/de/mpiwg/itgroup/annotations/Person.java
===================================================================
--- src/main/java/de/mpiwg/itgroup/annotations/Person.java	(revision 12)
+++ src/main/java/de/mpiwg/itgroup/annotations/Person.java	(revision 15)
@@ -24,4 +24,11 @@
     }
 
+    public Person(String id, String uri, String name) {
+        super();
+        this.id = id;
+        this.uri = uri;
+        this.name = name;
+    }
+
     @Override
     public boolean isGroup() {
@@ -36,3 +43,15 @@
     }
 
+    /**
+     * Returns a Person with this id or null.
+     * 
+     * @param id
+     * @return
+     */
+    public static Person createPersonWithId(String id) {
+        if (id != null) {
+            return new Person(id);
+        }
+        return null;
+    }
 }
Index: src/main/java/de/mpiwg/itgroup/annotations/neo4j/AnnotationStore.java
===================================================================
--- src/main/java/de/mpiwg/itgroup/annotations/neo4j/AnnotationStore.java	(revision 14)
+++ src/main/java/de/mpiwg/itgroup/annotations/neo4j/AnnotationStore.java	(revision 15)
@@ -35,5 +35,5 @@
 
     public static enum NodeTypes {
-        ANNOTATION, PERSON, TARGET
+        ANNOTATION, PERSON, TARGET, GROUP 
     }
 
@@ -41,5 +41,5 @@
 
     public static enum RelationTypes implements RelationshipType {
-        ANNOTATES, CREATED, PERMITS_ADMIN, PERMITS_DELETE, PERMITS_UPDATE, PERMITS_READ
+        ANNOTATES, CREATED, PERMITS_ADMIN, PERMITS_DELETE, PERMITS_UPDATE, PERMITS_READ, MEMBER_OF
     }
 
@@ -54,4 +54,5 @@
         nodeIndexes.add(NodeTypes.PERSON.ordinal(), graphDb.index().forNodes("persons"));
         nodeIndexes.add(NodeTypes.TARGET.ordinal(), graphDb.index().forNodes("targets"));
+        nodeIndexes.add(NodeTypes.GROUP.ordinal(), graphDb.index().forNodes("groups"));
     }
 
@@ -60,4 +61,58 @@
     }
 
+    /**
+     * @param userUri
+     * @return
+     */
+    public Node getPersonNodeByUri(String userUri) {
+        if (userUri == null) return null;
+        Node person = getNodeIndex(NodeTypes.PERSON).get("uri", userUri).getSingle();
+        return person;
+    }
+
+    
+    /**
+     * Returns List of Groups the person is member of.
+     * 
+     * @param person
+     * @return
+     */
+    public List<Group> getGroupsForPersonNode(Node person) {
+        ArrayList<Group> groups = new ArrayList<Group>();
+        Iterable<Relationship> rels = person.getRelationships(RelationTypes.MEMBER_OF);
+        for (Relationship rel : rels) {
+            Node groupNode = rel.getEndNode();
+            Actor group = createActorFromNode(groupNode);
+            // make sure we're getting a group
+            if (!(group instanceof Group)) {
+                logger.error("target of MEMBER_OF is not GROUP! rel="+rel);
+                continue;
+            }
+            groups.add((Group) group);
+        }
+        return groups;
+    }
+    
+    /**
+     * Returns if person with uri is in Group group.
+     * 
+     * @param person
+     * @param group
+     * @return
+     */
+    public boolean isPersonInGroup(Person person, Group group) {
+        Node pn = getPersonNodeByUri(person.getUriString());
+        if (pn == null) return false;
+        // optimised version of getGroupsForPersonNode
+        Iterable<Relationship> rels = pn.getRelationships(RelationTypes.MEMBER_OF);
+        for (Relationship rel : rels) {
+            Node gn = rel.getEndNode();
+            if (gn.getProperty("uri", "").equals(group.getUriString()) || gn.getProperty("id", "").equals(group.getId())) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
     /**
      * Returns the Annotation with the given id.
@@ -143,11 +198,12 @@
      */
     protected Actor createActorFromNode(Node actorNode) {
+        String id = (String) actorNode.getProperty("id", null);
         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);
+            return new Person(id, uri, name);
         } else if (type != null && type.equals("GROUP")) {
-            return new Group(uri, name);
+            return new Group(id, uri, name);
         }
         return null;
@@ -210,5 +266,5 @@
             Actor creator = annot.getCreator();
             if (creator != null) {
-                Node creatorNode = getOrCreatePersonNode(creator);
+                Node creatorNode = getOrCreateActorNode(creator);
                 getOrCreateRelation(creatorNode, RelationTypes.CREATED, annotNode);
             }
@@ -301,5 +357,5 @@
         if (userUri != null) {
             // there should be only one
-            Node person = getNodeIndex(NodeTypes.PERSON).get("uri", userUri).getSingle();
+            Node person = getPersonNodeByUri(userUri);
             if (person != null) {
                 Iterable<Relationship> relations = person.getRelationships(RelationTypes.CREATED);
@@ -381,9 +437,15 @@
     }
 
-    protected Node getOrCreatePersonNode(Actor actor) {
-        // Person is identified by URI
+    protected Node getOrCreateActorNode(Actor actor) {
+        // Person/Group is identified by URI or id
         String uri = actor.getUriString();
         String name = actor.getName();
-        Index<Node> idx = getNodeIndex(NodeTypes.PERSON);
+        String id = actor.getId();
+        Index<Node> idx;
+        if (actor.isGroup()) {
+            idx = getNodeIndex(NodeTypes.GROUP);
+        } else {
+            idx = getNodeIndex(NodeTypes.PERSON);
+        }
         IndexHits<Node> persons = idx.get("uri", uri);
         Node person = persons.getSingle();
@@ -393,5 +455,9 @@
             try {
                 person = graphDb.createNode();
-                person.setProperty("TYPE", NodeTypes.PERSON.name());
+                if (actor.isGroup()) {
+                    person.setProperty("TYPE", NodeTypes.GROUP.name());
+                } else {
+                    person.setProperty("TYPE", NodeTypes.PERSON.name());                    
+                }
                 person.setProperty("uri", uri);
                 idx.add(person, "uri", uri);
@@ -399,4 +465,7 @@
                     person.setProperty("name", name);
                 }
+                if (id != null) {
+                    person.setProperty("id", id);
+                }
                 tx.success();
             } finally {
@@ -417,5 +486,5 @@
         Node newActorNode = null;
         if (actor != null) {
-            newActorNode = getOrCreatePersonNode(actor);
+            newActorNode = getOrCreateActorNode(actor);
         }
         Relationship rel = getRelation(annotNode, type, null);
@@ -464,4 +533,11 @@
     }
 
+    /** returns the (first) Relationship of RelationTypes type from Node start.
+     *  
+     * @param start
+     * @param type
+     * @param direction
+     * @return
+     */
     protected Relationship getRelation(Node start, RelationTypes type, Direction direction) {
         Iterable<Relationship> rels;
Index: src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorAnnotations.java
===================================================================
--- src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorAnnotations.java	(revision 14)
+++ src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorAnnotations.java	(revision 15)
@@ -7,5 +7,4 @@
 import java.io.IOException;
 
-import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
@@ -19,4 +18,5 @@
 
 import de.mpiwg.itgroup.annotations.Annotation;
+import de.mpiwg.itgroup.annotations.Person;
 import de.mpiwg.itgroup.annotations.neo4j.AnnotationStore;
 
@@ -52,10 +52,10 @@
 
         // do authentication
-        String authUser = this.checkAuthToken(entity);
+        Person authUser = Person.createPersonWithId(this.checkAuthToken(entity));
         logger.debug("request authenticated=" + authUser);
 
         Annotation annot = getAnnotationStore().getAnnotationById(id);
         if (annot != null) {
-            if (! annot.isActionAllowed("read", authUser)) {
+            if (! annot.isActionAllowed("read", authUser, null)) {
                 setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Not Authorized!");
                 return null;
@@ -84,5 +84,5 @@
         
         // do authentication TODO: who's allowed to create? 
-        String authUser = this.checkAuthToken(entity);
+        Person authUser = Person.createPersonWithId(this.checkAuthToken(entity));
         logger.debug("request authenticated=" + authUser);
         if (authUser == null) {
@@ -142,5 +142,5 @@
 
         // do authentication
-        String authUser = this.checkAuthToken(entity);
+        Person authUser = Person.createPersonWithId(this.checkAuthToken(entity));
         logger.debug("request authenticated=" + authUser);
 
@@ -160,5 +160,5 @@
                 return null;
             }
-            if (! storedAnnot.isActionAllowed("update", authUser)) {
+            if (! storedAnnot.isActionAllowed("update", authUser, null)) {
                 setStatus(Status.CLIENT_ERROR_FORBIDDEN);
                 return null;
@@ -205,9 +205,9 @@
 
         // do authentication
-        String authUser = this.checkAuthToken(entity);
+        Person authUser = Person.createPersonWithId(this.checkAuthToken(entity));
         logger.debug("request authenticated=" + authUser);
         Annotation annot = getAnnotationStore().getAnnotationById(id);
         if (annot != null) {
-            if (! annot.isActionAllowed("delete", authUser)) {
+            if (! annot.isActionAllowed("delete", authUser, null)) {
                 setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Not Authorized!");
                 return null;
Index: src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorGroups.java
===================================================================
--- src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorGroups.java	(revision 15)
+++ src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorGroups.java	(revision 15)
@@ -0,0 +1,84 @@
+/**
+ * ReST API for accessing groups in the Annotation store.
+ */
+package de.mpiwg.itgroup.annotations.restlet;
+
+import java.util.List;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.neo4j.graphdb.Node;
+import org.restlet.data.Form;
+import org.restlet.data.Status;
+import org.restlet.ext.json.JsonRepresentation;
+import org.restlet.representation.Representation;
+import org.restlet.resource.Get;
+
+import de.mpiwg.itgroup.annotations.Actor;
+import de.mpiwg.itgroup.annotations.Group;
+import de.mpiwg.itgroup.annotations.neo4j.AnnotationStore;
+
+
+/**
+ * API for accessing groups in the Annotation store.
+ * 
+ * @author casties
+ *
+ */
+public class AnnotatorGroups extends AnnotatorResourceImpl {
+    protected String getAllowedMethodsForHeader() {
+        return "OPTIONS,GET";
+    }
+
+    /**
+     * GET with JSON content-type.
+     * Parameters: 
+     *   user: short user name
+     *   uri: user uri
+     *   
+     * @param entity
+     * @return
+     */
+    @Get("json")
+    public Representation doGetJSON(Representation entity) {
+        logger.debug("AnnotatorGroups doGetJSON!");
+        setCorsHeaders();
+        Form form = getRequest().getResourceRef().getQueryAsForm();
+        String user = form.getFirstValue("user");
+        String uri = form.getFirstValue("uri");
+        if (uri == null || uri.isEmpty()) {
+            // get uri from user-id
+            uri = Actor.getUriFromId(user, false);
+        }
+        JSONArray results = new JSONArray();
+        AnnotationStore store = getAnnotationStore();
+        Node person = store.getPersonNodeByUri(uri);
+        if (person != null) {
+            List<Group> groups = store.getGroupsForPersonNode(person);
+            for (Group group : groups) {
+                JSONObject jo = new JSONObject();
+                try {
+                    jo.put("id", group.getId());
+                    jo.put("name", group.getName());
+                    jo.put("uri", group.getUriString());
+                } catch (JSONException e) {
+                }
+                results.put(jo);
+            }
+        }
+        // assemble result object
+        JSONObject result = new JSONObject();
+        try {
+            result.put("rows", results);
+            result.put("total", results.length());
+        } catch (JSONException e) {
+            setStatus(Status.SERVER_ERROR_INTERNAL, "JSON Error");
+            return null;
+        }
+        logger.debug("sending:");
+        logger.debug(result);
+        return new JsonRepresentation(result);
+
+    }
+}
Index: src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorResourceImpl.java
===================================================================
--- src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorResourceImpl.java	(revision 14)
+++ src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorResourceImpl.java	(revision 15)
@@ -533,5 +533,5 @@
     }
 
-    @SuppressWarnings("unused")
+    @SuppressWarnings("unused") // i in for loop
     protected Actor getActorFromPermissions(JSONArray perms) throws JSONException {
         Actor actor = null;
Index: src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorSearch.java
===================================================================
--- src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorSearch.java	(revision 14)
+++ src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorSearch.java	(revision 15)
@@ -16,4 +16,6 @@
 
 import de.mpiwg.itgroup.annotations.Annotation;
+import de.mpiwg.itgroup.annotations.Person;
+import de.mpiwg.itgroup.annotations.neo4j.AnnotationStore;
 
 /**
@@ -42,5 +44,5 @@
         setCorsHeaders();
         // do authentication
-        String authUser = this.checkAuthToken(entity);
+        Person authUser = Person.createPersonWithId(this.checkAuthToken(entity));
         logger.debug("request authenticated=" + authUser);
 
@@ -54,8 +56,9 @@
         // do search
         logger.debug(String.format("searching for uri=%s user=%s", uri, user));
-        List<Annotation> annots = getAnnotationStore().searchByUriUser(uri, user, limit, offset);
+        AnnotationStore store = getAnnotationStore();
+        List<Annotation> annots = store.searchByUriUser(uri, user, limit, offset);
         for (Annotation annot : annots) {
             // check permission
-            if (!annot.isActionAllowed("read", authUser)) continue;
+            if (!annot.isActionAllowed("read", authUser, store)) continue;
             JSONObject jo = createAnnotatorJson(annot, (authUser == null));
             if (jo != null) {
Index: src/main/java/de/mpiwg/itgroup/annotations/restlet/RestServer.java
===================================================================
--- src/main/java/de/mpiwg/itgroup/annotations/restlet/RestServer.java	(revision 6)
+++ src/main/java/de/mpiwg/itgroup/annotations/restlet/RestServer.java	(revision 15)
@@ -166,4 +166,5 @@
         router.attach("/annotator/annotations/{id}", AnnotatorAnnotations.class);
         router.attach("/annotator/search", AnnotatorSearch.class);
+        router.attach("/annotator/groups", AnnotatorGroups.class);
 
         // router.attach("",redirector); router.attach("/annotator",
