Added warnings when requesting non-public fields via the search API with
accessRewriteDisabled (resolved #43).

Change-Id: I917415f242c1adf884bacb832fd7644cddaa6973
diff --git a/core/Changes b/core/Changes
index dcaf3dc..023b7f9 100644
--- a/core/Changes
+++ b/core/Changes
@@ -1,3 +1,8 @@
+# version 0.62.2
+13/11/2019
+   - Added warnings when requesting non-public fields via the search API with 
+     accessRewriteDisabled (margaretha, resolved #43).
+
 # version 0.62.1
 08/07/2019
    - Added support for public metadata response in search api (margaretha, 
diff --git a/core/pom.xml b/core/pom.xml
index bd89d6d..7bef3cd 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -3,7 +3,7 @@
 	<modelVersion>4.0.0</modelVersion>
 	<groupId>de.ids_mannheim.korap</groupId>
 	<artifactId>Kustvakt-core</artifactId>
-	<version>0.62.1</version>
+	<version>0.62.2</version>
 
 	<properties>
 		<java.version>1.8</java.version>
@@ -240,7 +240,7 @@
 		<dependency>
 			<groupId>de.ids_mannheim.korap</groupId>
 			<artifactId>Koral</artifactId>
-			<version>[0.34,)</version>
+			<version>[0.35,)</version>
 			<exclusions>
 				<exclusion>
 					<groupId>org.eclipse.jetty</groupId>
diff --git a/core/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java b/core/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
index 13694d3..f65165e 100644
--- a/core/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
+++ b/core/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
@@ -54,7 +54,7 @@
 
     // fixme: use unsupported resource and include type in return message
     public static final int POLICY_ERROR_DEFAULT = 400;
-
+    public static final int NON_PUBLIC_FIELD_IGNORED = 401;
     public static final int UNSUPPORTED_RESOURCE = 402;
     //    public static final int REWRITE_FAILED = 403;
     //public static final int UNSUPPORTED_FOUNDRY = 403;
diff --git a/core/src/main/java/de/ids_mannheim/korap/service/SearchService.java b/core/src/main/java/de/ids_mannheim/korap/service/SearchService.java
index 638871b..3a04452 100644
--- a/core/src/main/java/de/ids_mannheim/korap/service/SearchService.java
+++ b/core/src/main/java/de/ids_mannheim/korap/service/SearchService.java
@@ -26,7 +26,6 @@
 import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.query.serialize.MetaQueryBuilder;
 import de.ids_mannheim.korap.query.serialize.QuerySerializer;
-import de.ids_mannheim.korap.rewrite.KoralNode;
 import de.ids_mannheim.korap.rewrite.RewriteHandler;
 import de.ids_mannheim.korap.user.User;
 import de.ids_mannheim.korap.user.User.CorpusAccess;
@@ -140,13 +139,16 @@
             corpusAccess = CorpusAccess.ALL;
             user.setCorpusAccess(CorpusAccess.ALL);
         }
-            
+        
         QuerySerializer serializer = new QuerySerializer();
         serializer.setQuery(q, ql, v);
         if (cq != null) serializer.setCollection(cq);
 
+        List<String> fieldList = convertFieldsToList(fields);
+        handleNonPublicFields(fieldList, accessRewriteDisabled, serializer);
+        
         MetaQueryBuilder meta = createMetaQuery(pageIndex, pageInteger, ctx,
-                pageLength, cutoff, corpusAccess, fields, accessRewriteDisabled);
+                pageLength, cutoff, corpusAccess, fieldList, accessRewriteDisabled);
         serializer.setMeta(meta.raw());
         
         // There is an error in query processing
@@ -173,9 +175,29 @@
 
     }
 
+    private void handleNonPublicFields (List<String> fieldList,
+            boolean accessRewriteDisabled, QuerySerializer serializer) {
+        List<String> nonPublicFields = new ArrayList<>(); 
+        nonPublicFields.add("snippet");
+        
+        List<String> ignoredFields = new ArrayList<>();
+        if (accessRewriteDisabled && !fieldList.isEmpty()) {
+            for (String field : fieldList) {
+                if (nonPublicFields.contains(field)) {
+                    ignoredFields.add(field);
+                }
+            }
+            if (!ignoredFields.isEmpty()) {
+                serializer.addWarning(StatusCodes.NON_PUBLIC_FIELD_IGNORED,
+                        "The requested non public fields are ignored",
+                        ignoredFields);
+            }
+        }
+    }
+    
     private MetaQueryBuilder createMetaQuery (Integer pageIndex,
             Integer pageInteger, String ctx, Integer pageLength,
-            Boolean cutoff, CorpusAccess corpusAccess, String fields,
+            Boolean cutoff, CorpusAccess corpusAccess, List<String> fieldList,
             boolean accessRewriteDisabled) {
         MetaQueryBuilder meta = new MetaQueryBuilder();
         meta.addEntry("startIndex", pageIndex);
@@ -197,20 +219,24 @@
             meta.addEntry("timeout", 90000);
         }
         
-        if (fields != null && !fields.isEmpty()){
-            List<String> fieldList = convertFieldsToList(fields);
+        if (fieldList != null && !fieldList.isEmpty()){
             meta.addEntry("fields", fieldList);
         }
         return meta;
     }
 
     private List<String> convertFieldsToList (String fields) {
-        String[] fieldArray = fields.split(",");
-        List<String> fieldList = new ArrayList<>(fieldArray.length);
-        for (String field :  fieldArray){
-            fieldList.add(field.trim());
+        if (fields != null && !fields.isEmpty()) {
+            String[] fieldArray = fields.split(",");
+            List<String> fieldList = new ArrayList<>(fieldArray.length);
+            for (String field : fieldArray) {
+                fieldList.add(field.trim());
+            }
+            return fieldList;
         }
-        return fieldList;
+        else {
+            return new ArrayList<>();
+        }
     }
     
     private String searchNeo4J (String query, int pageLength,
diff --git a/full/Changes b/full/Changes
index c8eeab2..6a8b188 100644
--- a/full/Changes
+++ b/full/Changes
@@ -11,6 +11,8 @@
      services (margaretha)
    - Added prefixes to username and groupname parameters in service paths 
      (margaretha, resolved #35)  
+13/11/2019
+   - Added tests for issue #43 (margaretha)
      
 
 # version 0.62.1
diff --git a/full/pom.xml b/full/pom.xml
index 011c48a..564d3be 100644
--- a/full/pom.xml
+++ b/full/pom.xml
@@ -205,7 +205,7 @@
 		<dependency>
 			<groupId>de.ids_mannheim.korap</groupId>
 			<artifactId>Kustvakt-core</artifactId>
-			<version>[0.62.1,)</version>
+			<version>[0.62.2,)</version>
 		</dependency>
 		<!-- LDAP -->
 		<dependency>
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/PublicMetadataTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/PublicMetadataTest.java
index 5412949..6975d54 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/PublicMetadataTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/PublicMetadataTest.java
@@ -53,6 +53,48 @@
 
         assertTrue(node.at("/matches/0/snippet").isMissingNode());
     }
+    
+    @Test
+    public void testSearchPublicMetadataWithCustomFields () throws KustvaktException {
+        ClientResponse response = resource().path(API_VERSION).path("search")
+                .queryParam("q", "Sonne").queryParam("ql", "poliqarp")
+                .queryParam("fields", "author,title")
+                .queryParam("access-rewrite-disabled", "true")
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals("availability(ALL)",
+                node.at("/collection/rewrites/0/scope").asText());
+
+        assertTrue(node.at("/matches/0/snippet").isMissingNode());
+        assertEquals("Goethe, Johann Wolfgang von",
+                node.at("/matches/0/author").asText());
+        assertEquals("Italienische Reise",
+                node.at("/matches/0/title").asText());
+        assertEquals(3, node.at("/matches/0").size());
+    }
+    
+    @Test
+    public void testSearchPublicMetadataWithNonPublicField () throws KustvaktException {
+        ClientResponse response = resource().path(API_VERSION).path("search")
+                .queryParam("q", "Sonne").queryParam("ql", "poliqarp")
+                .queryParam("fields", "author,title,snippet")
+                .queryParam("access-rewrite-disabled", "true")
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+
+        assertEquals(StatusCodes.NON_PUBLIC_FIELD_IGNORED,
+                node.at("/warnings/0/0").asInt());
+        assertEquals("The requested non public fields are ignored",
+                node.at("/warnings/0/1").asText());
+        assertEquals("snippet",
+                node.at("/warnings/0/2").asText());
+    }
 
 //  EM: The API is disabled
     @Ignore
diff --git a/lite/Changes b/lite/Changes
index 5cc49c6..39ac301 100644
--- a/lite/Changes
+++ b/lite/Changes
@@ -1,3 +1,7 @@
+# version 0.62.2
+13/11/2019
+   - Added tests for issue #43 (margaretha)
+
 # version 0.62.1
 08/07/2019
    - Added tests for public metadata response in search api (margaretha, issue #43)
diff --git a/lite/pom.xml b/lite/pom.xml
index 67d1421..c2f72f0 100644
--- a/lite/pom.xml
+++ b/lite/pom.xml
@@ -3,7 +3,7 @@
 	<modelVersion>4.0.0</modelVersion>
 	<groupId>de.ids_mannheim.korap</groupId>
 	<artifactId>Kustvakt-lite</artifactId>
-	<version>0.62.1</version>
+	<version>0.62.2</version>
 	<properties>
 		<java.version>1.8</java.version>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -137,7 +137,7 @@
 		<dependency>
 			<groupId>de.ids_mannheim.korap</groupId>
 			<artifactId>Kustvakt-core</artifactId>
-			<version>[0.62.1,)</version>
+			<version>[0.62.2,)</version>
 		</dependency>
 		<!-- Jersey test framework -->
 		<dependency>
diff --git a/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteSearchControllerTest.java b/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteSearchControllerTest.java
index d5d885d..6463ce9 100644
--- a/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteSearchControllerTest.java
+++ b/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteSearchControllerTest.java
@@ -409,6 +409,46 @@
     }
     
     @Test
+    public void testSearchPublicMetadataWithCustomFields () throws KustvaktException {
+        ClientResponse response = resource().path(API_VERSION).path("search")
+                .queryParam("q", "Sonne").queryParam("ql", "poliqarp")
+                .queryParam("fields", "author,title")
+                .queryParam("access-rewrite-disabled", "true")
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        
+        assertTrue(node.at("/matches/0/snippet").isMissingNode());
+        assertEquals("Goethe, Johann Wolfgang von",
+                node.at("/matches/0/author").asText());
+        assertEquals("Italienische Reise",
+                node.at("/matches/0/title").asText());
+        assertEquals(3, node.at("/matches/0").size());
+    }
+    
+    @Test
+    public void testSearchPublicMetadataWithNonPublicField () throws KustvaktException {
+        ClientResponse response = resource().path(API_VERSION).path("search")
+                .queryParam("q", "Sonne").queryParam("ql", "poliqarp")
+                .queryParam("fields", "author,title,snippet")
+                .queryParam("access-rewrite-disabled", "true")
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+
+        assertEquals(StatusCodes.NON_PUBLIC_FIELD_IGNORED,
+                node.at("/warnings/0/0").asInt());
+        assertEquals("The requested non public fields are ignored",
+                node.at("/warnings/0/1").asText());
+        assertEquals("snippet",
+                node.at("/warnings/0/2").asText());
+    }
+    
+    @Test
     public void testSearchWithInvalidPage () throws KustvaktException {
         ClientResponse response = resource().path(API_VERSION).path("search")
                 .queryParam("q", "[orth=die]").queryParam("ql", "poliqarp")