Resolved #40.

Change-Id: I94bcea2ec4807535cc026dc2c04a841e7441c415
diff --git a/full/Changes b/full/Changes
index 21aecba..a7ff8d3 100644
--- a/full/Changes
+++ b/full/Changes
@@ -7,6 +7,8 @@
    - Fixed missing scopes after requesting access token with refresh token 
      (margaretha)
    - Fixed post requests with status OK and empty body (margaretha)
+07/08/2019
+   - Resolved #40 (margaretha)   
 
 # version 0.62
 28/02/2019
diff --git a/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java b/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java
index e18d258..c4a7e35 100644
--- a/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java
@@ -275,6 +275,8 @@
                     deleteVCAccess(hiddenAccess.getId(), "system");
                     int groupId = hiddenAccess.getUserGroup().getId();
                     userGroupService.deleteAutoHiddenGroup(groupId, "system");
+                    // EM: should the users within the hidden group receive 
+                    // notifications? 
                 }
                 // else remains the same
             }
@@ -642,14 +644,15 @@
                         username);
             }
 
-            else if (VirtualCorpusType.PUBLISHED.equals(type)) {
+            else if (VirtualCorpusType.PUBLISHED.equals(type)
+                    && !username.equals("guest")) {
                 // add user in the VC's auto group
                 UserGroup userGroup = userGroupService
                         .retrieveHiddenUserGroupByVC(vc.getId());
                 try {
                     userGroupService.addGroupMember(username, userGroup,
                             "system", GroupMemberStatus.ACTIVE);
-                    // member roles has not been set (not necessary)
+                    // member roles are not set (not necessary)
                 }
                 catch (KustvaktException e) {
                     // member exists
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupController.java
index a70292c..98298c8 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupController.java
@@ -283,14 +283,22 @@
         }
     }
 
+    /** Very similar to addMemberRoles web-service, but allows deletion 
+     * as well.
+     * 
+     * @param securityContext
+     * @param groupId
+     * @param memberUsername
+     * @param roleIds
+     * @return
+     */
     @POST
     @Path("member/role/edit")
     @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
     public Response editMemberRoles (@Context SecurityContext securityContext,
             @FormParam("groupId") int groupId,
             @FormParam("memberUsername") String memberUsername,
-            @FormParam("roleIds") List<Integer> roleIds,
-            @PathParam("version") String version) {
+            @FormParam("roleIds") List<Integer> roleIds) {
         TokenContext context =
                 (TokenContext) securityContext.getUserPrincipal();
         try {
@@ -307,8 +315,7 @@
 
     /**
      * Adds roles of an active member of a user-group. Only user-group
-     * admins
-     * and system admins are allowed.
+     * admins and system admins are allowed.
      * 
      * @param securityContext
      * @param groupId
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/VCReferenceTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/VCReferenceTest.java
index 31c34b6..e74105c 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/VCReferenceTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/VCReferenceTest.java
@@ -9,9 +9,13 @@
 import org.springframework.beans.factory.annotation.Autowired;
 
 import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.net.HttpHeaders;
 import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.ClientResponse.Status;
 
 import de.ids_mannheim.korap.KrillCollection;
+import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
+import de.ids_mannheim.korap.config.Attributes;
 import de.ids_mannheim.korap.config.NamedVCLoader;
 import de.ids_mannheim.korap.config.SpringJerseyTest;
 import de.ids_mannheim.korap.dao.VirtualCorpusDao;
@@ -138,4 +142,60 @@
                 node.at("/errors/0/0").asInt());
         assertEquals("guest", node.at("/errors/0/2").asText());
     }
+    
+    @Test
+    public void testSearchWithPublishedVCRefGuest () throws KustvaktException {
+        ClientResponse response = resource().path(API_VERSION).path("search")
+                .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
+                .queryParam("cq", "referTo \"marlin/published-vc\"")
+                .get(ClientResponse.class);
+
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertTrue(node.at("/matches").size() > 0);
+        
+        assertEquals("CC-BY.*", node.at("/collection/operands/0/value").asText());
+        assertEquals("koral:doc", node.at("/collection/operands/1/@type").asText());
+        assertEquals("GOE", node.at("/collection/operands/1/value").asText());
+        assertEquals("corpusSigle", node.at("/collection/operands/1/key").asText());
+        
+        node = node.at("/collection/operands/1/rewrites");
+        assertEquals(3, node.size());
+        assertEquals("operation:deletion", node.at("/0/operation").asText());
+        assertEquals("@type(koral:docGroupRef)", node.at("/0/scope").asText());
+        assertEquals("operation:deletion", node.at("/1/operation").asText());
+        assertEquals("ref(marlin/published-vc)", node.at("/1/scope").asText());
+        assertEquals("operation:insertion", node.at("/2/operation").asText());
+    }
+    
+    @Test
+    public void testSearchWithPublishedVCRef () throws KustvaktException {
+        ClientResponse response = resource().path(API_VERSION).path("search")
+                .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
+                .queryParam("cq", "referTo \"marlin/published-vc\"")
+                .header(Attributes.AUTHORIZATION, HttpAuthorizationHandler
+                        .createBasicAuthorizationHeaderValue("squirt", "pass"))
+                .get(ClientResponse.class);
+
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertTrue(node.at("/matches").size() > 0);
+        
+        // check dory in the hidden group of the vc
+        response = resource().path(API_VERSION).path("group")
+                .path("list").path("system-admin")
+                .queryParam("status", "HIDDEN")
+                .header(Attributes.AUTHORIZATION, HttpAuthorizationHandler
+                        .createBasicAuthorizationHeaderValue("admin", "pass"))
+                .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+                .get(ClientResponse.class);
+
+        assertEquals(Status.OK.getStatusCode(), response.getStatus());
+        String entity = response.getEntity(String.class);
+        node = JsonUtils.readTree(entity);
+        assertEquals(3, node.at("/0/id").asInt());
+        
+        String members = node.at("/0/members").toString();
+        assertTrue(members.contains("\"userId\":\"squirt\""));
+    } 
 }
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java
index cb12c8f..9da6393 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java
@@ -225,7 +225,8 @@
         String entity = response.getEntity(String.class);
         node = JsonUtils.readTree(entity);
         assertEquals(3, node.at("/0/id").asInt());
-        assertEquals("gill", node.at("/0/members/1/userId").asText());
+        String members = node.at("/0/members").toString();
+        assertTrue(members.contains("\"userId\":\"gill\""));
     }
 
     @Test