Added a check for OAuth2 client, VC, and group name length.

Change-Id: I716854dd0f93c4cda80304c4c6cf34fc35e890ea
diff --git a/core/Changes b/core/Changes
index 023b7f9..32a842b 100644
--- a/core/Changes
+++ b/core/Changes
@@ -2,6 +2,8 @@
 13/11/2019
    - Added warnings when requesting non-public fields via the search API with 
      accessRewriteDisabled (margaretha, resolved #43).
+14/11/2019
+   - Added a check for OAuth2 client, VC, and group name length (margaretha)
 
 # version 0.62.1
 08/07/2019
diff --git a/core/src/main/java/de/ids_mannheim/korap/utils/ParameterChecker.java b/core/src/main/java/de/ids_mannheim/korap/utils/ParameterChecker.java
index b4cf3cf..2673c80 100644
--- a/core/src/main/java/de/ids_mannheim/korap/utils/ParameterChecker.java
+++ b/core/src/main/java/de/ids_mannheim/korap/utils/ParameterChecker.java
@@ -46,4 +46,16 @@
                     name + " is missing", name);
         }
     }
+    
+    public static void checkNameValue (String value, String name)
+            throws KustvaktException {
+        if (value == null) {
+            throw new KustvaktException(StatusCodes.INVALID_ARGUMENT,
+                    name + " is null", name);
+        }
+        else if (value.length() < 3) {
+            throw new KustvaktException(StatusCodes.INVALID_ARGUMENT,
+                    name+" must contain at least 3 characters", name);
+        }
+    }
 }
diff --git a/full/Changes b/full/Changes
index 372efbe..3670dcc 100644
--- a/full/Changes
+++ b/full/Changes
@@ -10,14 +10,15 @@
    - Removed UserGroupJson & updated listUserGroups and createUserGroup 
      services (margaretha)
    - Added prefixes to username and groupname parameters in service paths 
-     (margaretha, resolved #35)  
+     (margaretha, resolved #35)
 13/11/2019
    - Added tests for issue #43 (margaretha)
 14/11/2019
    - Added client description and URL to list-authorized-clients service 
-     (margaretha, close #53)     
+     (margaretha, close #53)
    - Implemented a service to list clients registered by a user (margaretha, 
-     close #52)   
+     close #52)
+   - Added a check for OAuth2 client, VC, and group name length (margaretha)
 
 # version 0.62.1
 08/07/2019
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2ClientService.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2ClientService.java
index de7a90c..cfe962d 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2ClientService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2ClientService.java
@@ -32,6 +32,7 @@
 import de.ids_mannheim.korap.oauth2.entity.Authorization;
 import de.ids_mannheim.korap.oauth2.entity.OAuth2Client;
 import de.ids_mannheim.korap.oauth2.entity.RefreshToken;
+import de.ids_mannheim.korap.utils.ParameterChecker;
 import de.ids_mannheim.korap.web.input.OAuth2ClientJson;
 
 /**
@@ -80,6 +81,9 @@
 
     public OAuth2ClientDto registerClient (OAuth2ClientJson clientJson,
             String registeredBy) throws KustvaktException {
+        
+        ParameterChecker.checkNameValue(clientJson.getName(), "clientName");
+        
         String url = clientJson.getUrl();
         int urlHashCode = 0;
         if (url != null && !url.isEmpty()) {
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 14391d0..090660e 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
@@ -214,7 +214,7 @@
      */
     public boolean createUserGroup (String groupName, String members, String createdBy)
             throws KustvaktException {
-        ParameterChecker.checkStringValue(groupName, "groupName");
+        ParameterChecker.checkNameValue(groupName, "groupName");
         ParameterChecker.checkStringValue(createdBy, "createdBy");
         
         if (!groupNamePattern.matcher(groupName).matches()) {
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 4ebb07a..4532991 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
@@ -314,26 +314,26 @@
         }
     }
 
-    public int storeVC (VirtualCorpusJson vc, String name, String createdBy)
+    public void storeVC (VirtualCorpusJson vc, String vcName, String createdBy)
             throws KustvaktException {
         ParameterChecker.checkStringValue(vc.getCorpusQuery(), "corpusQuery");
         String koralQuery = serializeCorpusQuery(vc.getCorpusQuery());
 
-        return storeVC(name, vc.getType(), koralQuery, vc.getDefinition(),
+        storeVC(vcName, vc.getType(), koralQuery, vc.getDefinition(),
                 vc.getDescription(), vc.getStatus(), vc.isCached(), createdBy);
     }
 
-    public int storeVC (String name, VirtualCorpusType type, String koralQuery,
+    public void storeVC (String vcName, VirtualCorpusType type, String koralQuery,
             String definition, String description, String status,
             boolean isCached, String username) throws KustvaktException {
-        ParameterChecker.checkStringValue(name, "name");
+        ParameterChecker.checkNameValue(vcName, "vcName");
         ParameterChecker.checkObjectValue(type, "type");
 
-        if (!vcNamePattern.matcher(name).matches()) {
+        if (!vcNamePattern.matcher(vcName).matches()) {
             throw new KustvaktException(StatusCodes.INVALID_ARGUMENT,
                     "Virtual corpus name must only contains letters, numbers, "
                             + "underscores, hypens and spaces",
-                    name);
+                    vcName);
         }
 
         if (type.equals(VirtualCorpusType.SYSTEM) && !username.equals("system")
@@ -343,12 +343,12 @@
         }
 
         CorpusAccess requiredAccess =
-                determineRequiredAccess(isCached, name, koralQuery);
+                determineRequiredAccess(isCached, vcName, koralQuery);
 
-        if (DEBUG) jlog.debug("Storing VC " + name + "in the database ");
+        if (DEBUG) jlog.debug("Storing VC " + vcName + "in the database ");
         int vcId = 0;
         try {
-            vcId = vcDao.createVirtualCorpus(name, type, requiredAccess,
+            vcId = vcDao.createVirtualCorpus(vcName, type, requiredAccess,
                     koralQuery, definition, description, status, isCached,
                     username);
 
@@ -369,8 +369,6 @@
         if (type.equals(VirtualCorpusType.PUBLISHED)) {
             publishVC(vcId);
         }
-        // EM: should this return anything?
-        return vcId;
     }
 
     private String serializeCorpusQuery (String corpusQuery)
diff --git a/full/src/main/resources/db/mysql/V1.4__oauth2_tables.sql b/full/src/main/resources/db/mysql/V1.4__oauth2_tables.sql
index ff575ee..ff0230f 100644
--- a/full/src/main/resources/db/mysql/V1.4__oauth2_tables.sql
+++ b/full/src/main/resources/db/mysql/V1.4__oauth2_tables.sql
@@ -3,12 +3,12 @@
 -- oauth2 db tables
 CREATE TABLE IF NOT EXISTS oauth2_client (
 	id VARCHAR(100) PRIMARY KEY NOT NULL,
-	name VARCHAR(200) NOT NULL,
-	secret VARCHAR(200) DEFAULT NULL,
-	type VARCHAR(200) NOT NULL,
+	name VARCHAR(100) NOT NULL,
+	secret VARCHAR(255) DEFAULT NULL,
+	type VARCHAR(50) NOT NULL,
 	super BOOLEAN DEFAULT FALSE,
 	redirect_uri TEXT DEFAULT NULL,
-	description VARCHAR(250) NOT NULL,
+	description VARCHAR(255) NOT NULL,
 	registered_by VARCHAR(100) NOT NULL,
 	url_hashcode INTEGER NOT NULL,	
 	url TEXT DEFAULT NULL,
@@ -16,7 +16,7 @@
 );
 
 CREATE TABLE IF NOT EXISTS oauth2_access_scope (
-	id VARCHAR(255) PRIMARY KEY NOT NULL
+	id VARCHAR(100) PRIMARY KEY NOT NULL
 );
 
 -- authorization tables are not needed if using cache 
diff --git a/full/src/main/resources/db/sqlite/V1.4__oauth2_tables.sql b/full/src/main/resources/db/sqlite/V1.4__oauth2_tables.sql
index 2b55824..00be974 100644
--- a/full/src/main/resources/db/sqlite/V1.4__oauth2_tables.sql
+++ b/full/src/main/resources/db/sqlite/V1.4__oauth2_tables.sql
@@ -3,9 +3,9 @@
 -- oauth2 db tables
 CREATE TABLE IF NOT EXISTS oauth2_client (
 	id VARCHAR(100) PRIMARY KEY NOT NULL,
-	name VARCHAR(255) NOT NULL,
+	name VARCHAR(100) NOT NULL,
 	secret VARCHAR(255) DEFAULT NULL,
-	type VARCHAR(255) NOT NULL,
+	type VARCHAR(50) NOT NULL,
 	super BOOLEAN DEFAULT FALSE,
 	redirect_uri TEXT DEFAULT NULL,
 	description VARCHAR(255) NOT NULL,
@@ -17,7 +17,7 @@
 CREATE UNIQUE INDEX client_url_index on oauth2_client(url_hashcode);
 
 CREATE TABLE IF NOT EXISTS oauth2_access_scope (
-	id VARCHAR(255) PRIMARY KEY NOT NULL
+	id VARCHAR(100) PRIMARY KEY NOT NULL
 );
 
 -- authorization tables are not needed if using cache
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ClientControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ClientControllerTest.java
index dfbcee8..59b96f1 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ClientControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ClientControllerTest.java
@@ -153,6 +153,24 @@
     }
 
     @Test
+    public void testRegisterClientNameTooShort ()
+            throws UniformInterfaceException, ClientHandlerException,
+            KustvaktException {
+        OAuth2ClientJson json = new OAuth2ClientJson();
+        json.setName("R");
+        json.setType(OAuth2ClientType.PUBLIC);
+
+        ClientResponse response = registerClient(username, json);
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(StatusCodes.INVALID_ARGUMENT,
+                node.at("/errors/0/0").asInt());
+        assertEquals("clientName must contain at least 3 characters",
+                node.at("/errors/0/1").asText());
+        assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+    }
+    
+    @Test
     public void testRegisterPublicClient () throws UniformInterfaceException,
             ClientHandlerException, KustvaktException {
         OAuth2ClientJson json = new OAuth2ClientJson();
@@ -196,7 +214,7 @@
         testDeregisterPublicClientMissingId();
         testDeregisterPublicClient(clientId,username);
     }
-
+    
     private void testAccessTokenAfterDeregistration (String clientId,
             String clientSecret) throws KustvaktException {
         String userAuthHeader = HttpAuthorizationHandler
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerTest.java
index 59524af..2770714 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerTest.java
@@ -205,6 +205,22 @@
     }
     
     @Test
+    public void testCreateGroupNameTooShort () throws UniformInterfaceException,
+            ClientHandlerException, KustvaktException {
+        String groupName = "a"; 
+        String members = "marlin,nemo";
+
+        ClientResponse response = testCreateUserGroup(groupName, members);
+        assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+        
+        JsonNode node = JsonUtils.readTree(response.getEntity(String.class));
+        assertEquals(StatusCodes.INVALID_ARGUMENT, node.at("/errors/0/0").asInt());
+        assertEquals("groupName must contain at least 3 characters",
+                node.at("/errors/0/1").asText());
+        assertEquals("groupName", node.at("/errors/0/2").asText());
+    }
+    
+    @Test
     public void testUserGroup () throws UniformInterfaceException,
             ClientHandlerException, KustvaktException {
 
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 418ffb5..a696b57 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
@@ -485,6 +485,28 @@
                 node.at("/errors/0/0").asInt());
     }
 
+    
+    @Test
+    public void testCreateVCNameTooShort () throws KustvaktException {
+        String json = "{\"type\": \"PRIVATE\","
+                + "\"corpusQuery\": \"creationDate since 1820\"}";
+
+        ClientResponse response = resource().path(API_VERSION).path("vc")
+                .path("~"+testUser).path("ne")
+                .header(Attributes.AUTHORIZATION, HttpAuthorizationHandler
+                        .createBasicAuthorizationHeaderValue(testUser, "pass"))
+                .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON)
+                .entity(json).put(ClientResponse.class);
+        String entity = response.getEntity(String.class);
+        assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(StatusCodes.INVALID_ARGUMENT,
+                node.at("/errors/0/0").asInt());
+        assertEquals("vcName must contain at least 3 characters",
+                node.at("/errors/0/1").asText());
+    }
+
     @Test
     public void testCreateVCUnauthorized () throws KustvaktException {
         String json = "{\"type\": \"PRIVATE\","