Resolved #49. Added page param check in the search api (margaretha)

Change-Id: I30950d9c941aedcd1d0ec07aab4fc44ce5fd26a9
diff --git a/core/Changes b/core/Changes
index c35049b..c750d6d 100644
--- a/core/Changes
+++ b/core/Changes
@@ -8,6 +8,8 @@
    - Added cq parameter to VC statistics API and deprecate corpusQuery (margaretha)
 15/07/2019
    - Added backward compatibility support for corpusQuery parameter (margaretha)    
+28/08/2019
+   - Resolved #49. Added page param check in the search api (margaretha)
 
 # version 0.62
 18/03/2019
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 35f3547..638871b 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,6 +26,7 @@
 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;
@@ -124,6 +125,11 @@
             Integer pageLength, Boolean cutoff, boolean accessRewriteDisabled)
             throws KustvaktException {
 
+        if (pageInteger != null && pageInteger < 1) {
+            throw new KustvaktException(StatusCodes.INVALID_ARGUMENT,
+                    "page must start from 1", "page");
+        }
+        
         KustvaktConfiguration.BACKENDS eng = this.config.chooseBackend(engine);
         User user = createUser(username, headers);
         CorpusAccess corpusAccess = user.getCorpusAccess();
@@ -142,7 +148,7 @@
         MetaQueryBuilder meta = createMetaQuery(pageIndex, pageInteger, ctx,
                 pageLength, cutoff, corpusAccess, fields, accessRewriteDisabled);
         serializer.setMeta(meta.raw());
-
+        
         // There is an error in query processing
         // - either query, corpus or meta
         if (serializer.hasErrors()) {
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchControllerTest.java
index 33b6729..18e2c35 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchControllerTest.java
@@ -19,6 +19,7 @@
 import de.ids_mannheim.korap.config.Attributes;
 import de.ids_mannheim.korap.config.SpringJerseyTest;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.query.serialize.QuerySerializer;
 import de.ids_mannheim.korap.utils.JsonUtils;
 
@@ -289,6 +290,20 @@
         assertEquals("availability(PUB)",
                 node.at("/collection/rewrites/0/scope").asText());
     }
+    
+    @Test
+    public void testSearchWithInvalidPage () throws KustvaktException {
+        ClientResponse response = resource().path(API_VERSION).path("search")
+                .queryParam("q", "[orth=die]").queryParam("ql", "poliqarp")
+                .queryParam("page", "0")
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.BAD_REQUEST.getStatusCode(),
+                response.getStatus());
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(StatusCodes.INVALID_ARGUMENT, node.at("/errors/0/0").asInt());
+        assertEquals("page must start from 1",node.at("/errors/0/1").asText());
+    }
 
     @Test
     public void testSearchSentenceMeta () throws KustvaktException {
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 fb993be..67ad568 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
@@ -27,6 +27,7 @@
 import de.ids_mannheim.korap.config.Attributes;
 import de.ids_mannheim.korap.config.LiteJerseyTest;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.query.serialize.QuerySerializer;
 import de.ids_mannheim.korap.utils.JsonUtils;
 import de.ids_mannheim.korap.web.SearchKrill;
@@ -408,6 +409,20 @@
     }
     
     @Test
+    public void testSearchWithInvalidPage () throws KustvaktException {
+        ClientResponse response = resource().path(API_VERSION).path("search")
+                .queryParam("q", "[orth=die]").queryParam("ql", "poliqarp")
+                .queryParam("page", "0")
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.BAD_REQUEST.getStatusCode(),
+                response.getStatus());
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(StatusCodes.INVALID_ARGUMENT, node.at("/errors/0/0").asInt());
+        assertEquals("page must start from 1",node.at("/errors/0/1").asText());
+    }
+    
+    @Test
     public void testCloseIndex () throws IOException {
         searchKrill.getStatistics(null);
         assertEquals(true, searchKrill.getIndex().isReaderOpen());