Fixed search-VC task for project-VC, and added tests.

Change-Id: I8cc4a6a8383d8022f7ca681b65a002c8d9021d79
diff --git a/full/src/main/java/de/ids_mannheim/korap/dao/VirtualCorpusAccessDao.java b/full/src/main/java/de/ids_mannheim/korap/dao/VirtualCorpusAccessDao.java
index adae511..f885417 100644
--- a/full/src/main/java/de/ids_mannheim/korap/dao/VirtualCorpusAccessDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/dao/VirtualCorpusAccessDao.java
@@ -16,6 +16,7 @@
 import org.springframework.stereotype.Repository;
 import org.springframework.transaction.annotation.Transactional;
 
+import de.ids_mannheim.korap.constant.PredefinedUserGroup;
 import de.ids_mannheim.korap.constant.VirtualCorpusAccessStatus;
 import de.ids_mannheim.korap.entity.UserGroup;
 import de.ids_mannheim.korap.entity.UserGroup_;
@@ -24,6 +25,7 @@
 import de.ids_mannheim.korap.entity.VirtualCorpusAccess_;
 import de.ids_mannheim.korap.entity.VirtualCorpus_;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.utils.ParameterChecker;
 
 @Transactional
@@ -177,6 +179,44 @@
         }
     }
 
+    public VirtualCorpusAccess retrievePublishedGroupAccess (int vcId)
+            throws KustvaktException {
+        ParameterChecker.checkIntegerValue(vcId, "vcId");
+
+        CriteriaBuilder builder = entityManager.getCriteriaBuilder();
+        CriteriaQuery<VirtualCorpusAccess> query =
+                builder.createQuery(VirtualCorpusAccess.class);
+
+        Root<VirtualCorpusAccess> access =
+                query.from(VirtualCorpusAccess.class);
+        Join<VirtualCorpusAccess, VirtualCorpus> accessVC =
+                access.join(VirtualCorpusAccess_.virtualCorpus);
+        Join<VirtualCorpusAccess, UserGroup> accessGroup =
+                access.join(VirtualCorpusAccess_.userGroup);
+
+        Predicate p = builder.and(
+                builder.equal(accessVC.get(VirtualCorpus_.id), vcId),
+                builder.equal(accessGroup.get(UserGroup_.id),
+                        PredefinedUserGroup.ALL.getId()),
+                builder.equal(access.get(VirtualCorpusAccess_.status),
+                        VirtualCorpusAccessStatus.HIDDEN),
+                builder.notEqual(access.get(VirtualCorpusAccess_.deletedBy),
+                        "NULL"));
+
+        query.select(access);
+        query.where(p);
+
+        try {
+            Query q = entityManager.createQuery(query);
+            return (VirtualCorpusAccess) q.getSingleResult();
+        }
+        catch (NoResultException e) {
+            throw new KustvaktException(StatusCodes.NO_RESULT_FOUND,
+                    "Auto group access  is not found for virtual corpus with id "
+                            + vcId);
+        }
+    }
+
     public void createAccessToVC (VirtualCorpus virtualCorpus,
             UserGroup userGroup, String createdBy,
             VirtualCorpusAccessStatus status) {
diff --git a/full/src/main/java/de/ids_mannheim/korap/dao/VirtualCorpusDao.java b/full/src/main/java/de/ids_mannheim/korap/dao/VirtualCorpusDao.java
index a7690d7..3038d72 100644
--- a/full/src/main/java/de/ids_mannheim/korap/dao/VirtualCorpusDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/dao/VirtualCorpusDao.java
@@ -48,9 +48,9 @@
     private EntityManager entityManager;
 
     public int createVirtualCorpus (String name, VirtualCorpusType type,
-            CorpusAccess requiredAccess, String corpusQuery,
-            String definition, String description, String status,
-            String createdBy) throws KustvaktException {
+            CorpusAccess requiredAccess, String corpusQuery, String definition,
+            String description, String status, String createdBy)
+            throws KustvaktException {
 
         VirtualCorpus vc = new VirtualCorpus();
         vc.setName(name);
@@ -157,9 +157,9 @@
         Query q = entityManager.createQuery(query);
         return q.getResultList();
     }
-    
-    public List<VirtualCorpus> retrieveOwnerVCByType (String userId, VirtualCorpusType type)
-            throws KustvaktException {
+
+    public List<VirtualCorpus> retrieveOwnerVCByType (String userId,
+            VirtualCorpusType type) throws KustvaktException {
         ParameterChecker.checkStringValue(userId, "userId");
 
         CriteriaBuilder builder = entityManager.getCriteriaBuilder();
@@ -168,13 +168,11 @@
 
         Root<VirtualCorpus> virtualCorpus = query.from(VirtualCorpus.class);
         query.select(virtualCorpus);
-        
+
         Predicate p = builder.and(
                 builder.equal(virtualCorpus.get(VirtualCorpus_.createdBy),
                         userId),
-                builder.equal(virtualCorpus.get(VirtualCorpus_.type),
-                        type)
-                );
+                builder.equal(virtualCorpus.get(VirtualCorpus_.type), type));
         query.where(p);
 
         Query q = entityManager.createQuery(query);
diff --git a/full/src/main/java/de/ids_mannheim/korap/service/UserGroupService.java b/full/src/main/java/de/ids_mannheim/korap/service/UserGroupService.java
index 8cce326..612ae24 100644
--- a/full/src/main/java/de/ids_mannheim/korap/service/UserGroupService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/service/UserGroupService.java
@@ -205,4 +205,17 @@
         groupMemberDao.deleteMember(username, groupId, true);
     }
 
+
+    public boolean isMember (String username, UserGroup userGroup)
+            throws KustvaktException {
+        List<UserGroupMember> members =
+                groupMemberDao.retrieveMemberByGroupId(userGroup.getId());
+        for (UserGroupMember member : members) {
+            if (member.getUserId().equals(username)
+                    && member.getStatus().equals(GroupMemberStatus.ACTIVE)) {
+                return true;
+            }
+        }
+        return false;
+    }
 }
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 5bf6180..60c36bc 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
@@ -405,30 +405,45 @@
         VirtualCorpus vc = vcDao.retrieveVCById(vcId);
         VirtualCorpusType type = vc.getType();
 
-        if (!user.isAdmin()) {
+        if (!user.isAdmin() || !username.equals(vc.getCreatedBy())) {
             if (type.equals(VirtualCorpusType.PRIVATE)
-                    || type.equals(VirtualCorpusType.PROJECT)) {
+                    || (type.equals(VirtualCorpusType.PROJECT)
+                            && !hasAccess(username, vcId))) {
                 throw new KustvaktException(StatusCodes.AUTHORIZATION_FAILED,
                         "Unauthorized operation for user: " + username,
                         username);
             }
+
             else if (VirtualCorpusType.PUBLISHED.equals(type)) {
-                // add user in auto group 
-                List<VirtualCorpusAccess> hiddenAccessList =
-                        accessDao.retrieveHiddenAccess(vcId);
-                for (VirtualCorpusAccess access : hiddenAccessList) {
-                    if (PredefinedUserGroup.ALL.getId() != access.getUserGroup()
-                            .getId()) {
-                        userGroupService.addUserToGroup(username,
-                                access.getUserGroup());
-                        break;
-                    }
+                // add user in the VC's auto group 
+                VirtualCorpusAccess access =
+                        accessDao.retrievePublishedGroupAccess(vcId);
+                UserGroup userGroup = access.getUserGroup();
+                if (userGroupService.isMember(username, userGroup)) {
+                    userGroupService.addUserToGroup(username, userGroup);
                 }
             }
+            // else VirtualCorpusType.PREDEFINED
         }
 
         String json = vc.getCorpusQuery();
         String statistics = krill.getStatistics(json);
         return converter.createVirtualCorpusDto(vc, statistics);
     }
+
+    private boolean hasAccess (String username, int vcId)
+            throws KustvaktException {
+        UserGroup userGroup;
+        List<VirtualCorpusAccess> accessList =
+                accessDao.retrieveActiveAccessByVC(vcId);
+        for (VirtualCorpusAccess access : accessList) {
+            userGroup = access.getUserGroup();
+            if (userGroupService.isMember(username, userGroup)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+
 }
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 f55f0ea..6afb04b 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
@@ -55,8 +55,115 @@
         }
     }
 
+
     @Test
-    public void tesListVC () throws UniformInterfaceException,
+    public void testSearchPredefinedVC () throws UniformInterfaceException,
+            ClientHandlerException, KustvaktException {
+
+        ClientResponse response = resource().path("vc").path("search").path("3")
+                .header(Attributes.AUTHORIZATION,
+                        handler.createBasicAuthorizationHeaderValue(
+                                "VirtualCorpusControllerTest", "pass"))
+                .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+                .get(ClientResponse.class);
+        String entity = response.getEntity(String.class);
+
+        assertEquals(Status.OK.getStatusCode(), response.getStatus());
+
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals("system VC", node.at("/name").asText());
+        assertEquals(VirtualCorpusType.PREDEFINED.displayName(),
+                node.at("/type").asText());
+    }
+
+    @Test
+    public void testOwnerSearchPrivateVC () throws UniformInterfaceException,
+            ClientHandlerException, KustvaktException {
+
+        ClientResponse response = resource().path("vc").path("search").path("1")
+                .header(Attributes.AUTHORIZATION,
+                        handler.createBasicAuthorizationHeaderValue("dory",
+                                "pass"))
+                .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+                .get(ClientResponse.class);
+        String entity = response.getEntity(String.class);
+
+        assertEquals(Status.OK.getStatusCode(), response.getStatus());
+
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals("dory VC", node.at("/name").asText());
+        assertEquals(VirtualCorpusType.PRIVATE.displayName(),
+                node.at("/type").asText());
+    }
+
+    @Test
+    public void testSearchPrivateVCUnauthorized () throws UniformInterfaceException,
+            ClientHandlerException, KustvaktException {
+        ClientResponse response = resource().path("vc").path("search").path("1")
+                .header(Attributes.AUTHORIZATION,
+                        handler.createBasicAuthorizationHeaderValue(
+                                "VirtualCorpusControllerTest", "pass"))
+                .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+                .get(ClientResponse.class);
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
+        assertEquals(StatusCodes.AUTHORIZATION_FAILED,
+                node.at("/errors/0/0").asInt());
+        assertEquals("Unauthorized operation for user: VirtualCorpusControllerTest",
+                node.at("/errors/0/1").asText());
+
+        checkWWWAuthenticateHeader(response);
+    }
+
+    @Test
+    public void testSearchProjectVC () throws UniformInterfaceException,
+            ClientHandlerException, KustvaktException {
+
+        ClientResponse response = resource().path("vc").path("search").path("2")
+                .header(Attributes.AUTHORIZATION,
+                        handler.createBasicAuthorizationHeaderValue("nemo",
+                                "pass"))
+                .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+                .get(ClientResponse.class);
+        String entity = response.getEntity(String.class);
+
+        assertEquals(Status.OK.getStatusCode(), response.getStatus());
+
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals("group VC", node.at("/name").asText());
+        assertEquals(VirtualCorpusType.PROJECT.displayName(),
+                node.at("/type").asText());
+    }
+
+    @Test
+    public void testSearchProjectVCNonActiveMember () throws UniformInterfaceException,
+            ClientHandlerException, KustvaktException {
+
+        ClientResponse response = resource().path("vc").path("search").path("2")
+                .header(Attributes.AUTHORIZATION,
+                        handler.createBasicAuthorizationHeaderValue("marlin",
+                                "pass"))
+                .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+                .get(ClientResponse.class);
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
+        assertEquals(StatusCodes.AUTHORIZATION_FAILED,
+                node.at("/errors/0/0").asInt());
+        assertEquals("Unauthorized operation for user: marlin",
+                node.at("/errors/0/1").asText());
+
+        checkWWWAuthenticateHeader(response);
+    }
+
+//    @Test
+//    public void testSearchPublishedVC () {
+//
+//    }
+    
+    @Test
+    public void testListVC () throws UniformInterfaceException,
             ClientHandlerException, KustvaktException {
         ClientResponse response = resource().path("vc").path("list")
                 .header(Attributes.AUTHORIZATION,
@@ -118,18 +225,18 @@
                 .get(ClientResponse.class);
         entity = response.getEntity(String.class);
         assertEquals(Status.OK.getStatusCode(), response.getStatus());
-//        System.out.println(entity);
+        //        System.out.println(entity);
         JsonNode node = JsonUtils.readTree(entity);
         assertEquals(2, node.size());
-//        EM: order may be different
-//        assertEquals("new vc", node.get(0).get("name").asText());
+        //        EM: order may be different
+        //        assertEquals("new vc", node.get(0).get("name").asText());
 
         String vcId = null;
-        for (int i=0; i<node.size(); i++){
-            if (node.get(i).get("name").asText().equals("new vc")){
+        for (int i = 0; i < node.size(); i++) {
+            if (node.get(i).get("name").asText().equals("new vc")) {
                 vcId = node.get(i).get("id").asText();
             }
-        }         
+        }
 
         // delete new VC
         resource().path("vc").path("delete").queryParam("vcId", vcId)
@@ -343,7 +450,8 @@
         assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
         assertEquals(StatusCodes.AUTHORIZATION_FAILED,
                 node.at("/errors/0/0").asInt());
-        assertEquals("Unauthorized operation for user: VirtualCorpusControllerTest",
+        assertEquals(
+                "Unauthorized operation for user: VirtualCorpusControllerTest",
                 node.at("/errors/0/1").asText());
 
         checkWWWAuthenticateHeader(response);
@@ -479,7 +587,8 @@
         assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
         assertEquals(StatusCodes.AUTHORIZATION_FAILED,
                 node.at("/errors/0/0").asInt());
-        assertEquals("Unauthorized operation for user: VirtualCorpusControllerTest",
+        assertEquals(
+                "Unauthorized operation for user: VirtualCorpusControllerTest",
                 node.at("/errors/0/1").asText());
 
         checkWWWAuthenticateHeader(response);
@@ -487,41 +596,37 @@
 
     @Test
     public void testlistAccessByVC () throws KustvaktException {
-        ClientResponse response =
-                resource().path("vc").path("access").path("list")
-                        .queryParam("vcId", "2")
-                        .header(Attributes.AUTHORIZATION,
-                                handler.createBasicAuthorizationHeaderValue(
-                                        "dory", "pass"))
-                        .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
-                        .header(HttpHeaders.CONTENT_TYPE,
-                                ContentType.APPLICATION_JSON)
-                        .get(ClientResponse.class);
+        ClientResponse response = resource().path("vc").path("access")
+                .path("list").queryParam("vcId", "2")
+                .header(Attributes.AUTHORIZATION,
+                        handler.createBasicAuthorizationHeaderValue("dory",
+                                "pass"))
+                .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+                .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON)
+                .get(ClientResponse.class);
         String entity = response.getEntity(String.class);
-//        System.out.println(entity);
+        //        System.out.println(entity);
         JsonNode node = JsonUtils.readTree(entity);
         assertEquals(1, node.at("/0/accessId").asInt());
         assertEquals(2, node.at("/0/vcId").asInt());
         assertEquals("group VC", node.at("/0/vcName").asText());
         assertEquals(2, node.at("/0/userGroupId").asInt());
         assertEquals("dory group", node.at("/0/userGroupName").asText());
-        
+
     }
-    
+
     @Test
     public void testlistAccessNonVCAAdmin () throws KustvaktException {
-        ClientResponse response =
-                resource().path("vc").path("access").path("list")
-                        .queryParam("vcId", "2")
-                        .header(Attributes.AUTHORIZATION,
-                                handler.createBasicAuthorizationHeaderValue(
-                                        "nemo", "pass"))
-                        .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
-                        .header(HttpHeaders.CONTENT_TYPE,
-                                ContentType.APPLICATION_JSON)
-                        .get(ClientResponse.class);
+        ClientResponse response = resource().path("vc").path("access")
+                .path("list").queryParam("vcId", "2")
+                .header(Attributes.AUTHORIZATION,
+                        handler.createBasicAuthorizationHeaderValue("nemo",
+                                "pass"))
+                .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+                .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON)
+                .get(ClientResponse.class);
         String entity = response.getEntity(String.class);
-        assertEquals("[]", entity);       
+        assertEquals("[]", entity);
     }
 
     @Test
@@ -545,18 +650,16 @@
 
     @Test
     public void testlistAccessByGroup () throws KustvaktException {
-        ClientResponse response =
-                resource().path("vc").path("access").path("list").path("byGroup")
-                        .queryParam("groupId", "2")
-                        .header(Attributes.AUTHORIZATION,
-                                handler.createBasicAuthorizationHeaderValue(
-                                        "dory", "pass"))
-                        .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
-                        .header(HttpHeaders.CONTENT_TYPE,
-                                ContentType.APPLICATION_JSON)
-                        .get(ClientResponse.class);
+        ClientResponse response = resource().path("vc").path("access")
+                .path("list").path("byGroup").queryParam("groupId", "2")
+                .header(Attributes.AUTHORIZATION,
+                        handler.createBasicAuthorizationHeaderValue("dory",
+                                "pass"))
+                .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+                .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON)
+                .get(ClientResponse.class);
         String entity = response.getEntity(String.class);
-//        System.out.println(entity);
+        //        System.out.println(entity);
         JsonNode node = JsonUtils.readTree(entity);
         assertEquals(1, node.at("/0/accessId").asInt());
         assertEquals(2, node.at("/0/vcId").asInt());
@@ -564,13 +667,13 @@
         assertEquals(2, node.at("/0/userGroupId").asInt());
         assertEquals("dory group", node.at("/0/userGroupName").asText());
     }
- 
+
     // share VC
     @Test
     public void testCreateDeleteAccess () {
         // TODO Auto-generated method stub
 
     }
-    
-    
+
+
 }