Fixed sqlite trigger, member exist error message & issue #16.

Change-Id: If00402734bf7ce71fa699eee9e7609ea83203191
diff --git a/core/Changes b/core/Changes
index f1cb067..0ad7a54 100644
--- a/core/Changes
+++ b/core/Changes
@@ -2,7 +2,8 @@
 13/03/2018
 	- removed old policy and deprecated code (margaretha)
 	- moved authentication related code to /full (margaretha)
-	- elaborated default layer names in the configuration file. (margaretha)
+	- elaborated default layer names in the configuration file (margaretha)
+	- added GROUP_DELETED status code (margaretha)
 
 version 0.59.10 
 20/02/2018
@@ -13,7 +14,7 @@
 	- updated library versions and java environment (margaretha)
 	- added status codes (margaretha)
 	- moved validation.properties (margaretha)
-	- fixed unrecognize media-type application/json (margaretha)
+	- fixed unrecognized media-type application/json (margaretha)
 	
 version 0.59.9 	
 08/11/2017
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 941b5af..f32fb89 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
@@ -88,6 +88,7 @@
     public static final int GROUP_MEMBER_NOT_FOUND = 603;
     public static final int INVITATION_EXPIRED = 604;
     public static final int GROUP_NOT_FOUND = 605;
+    public static final int GROUP_DELETED = 606;
     
 
 //    public static final int ARGUMENT_VALIDATION_FAILURE = 700;
diff --git a/full/Changes b/full/Changes
index 02416e2..3a47fd0 100644
--- a/full/Changes
+++ b/full/Changes
@@ -9,6 +9,9 @@
 	- removed old policy and deprecated code (margaretha)
 	- moved authentication related code to /full (margaretha)
 	- added userRoles attribute to UserGroupDto. (margaretha)
+	- fixed sqlite trigger (margaretha)
+	- fixed member exist error message (margaretha)
+	- fixed member invitation to join deleted group (margaretha)
 
 version 0.59.10	
 20/02/2018 
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 428d87c..28f14a7 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
@@ -234,12 +234,13 @@
         int groupId = userGroup.getId();
         ParameterChecker.checkIntegerValue(groupId, "userGroupId");
 
-        if (memberExists(username, groupId, status)) {
+        GroupMemberStatus existingStatus = memberExists(username, groupId, status);
+        if (existingStatus != null){
             throw new KustvaktException(StatusCodes.GROUP_MEMBER_EXISTS,
-                    "Username " + username + " with status " + status
+                    "Username " + username + " with status " + existingStatus
                             + " exists in the user-group "
                             + userGroup.getName(),
-                    username, status.name(), userGroup.getName());
+                    username, existingStatus.name(), userGroup.getName());
         }
 
         setMemberRoles();
@@ -259,7 +260,7 @@
         }
     }
 
-    private boolean memberExists (String username, int groupId,
+    private GroupMemberStatus memberExists (String username, int groupId,
             GroupMemberStatus status) throws KustvaktException {
         UserGroupMember existingMember;
         try {
@@ -267,20 +268,20 @@
                     groupMemberDao.retrieveMemberById(username, groupId);
         }
         catch (KustvaktException e) {
-            return false;
+            return null;
         }
 
         GroupMemberStatus existingStatus = existingMember.getStatus();
         if (existingStatus.equals(GroupMemberStatus.ACTIVE)
                 || existingStatus.equals(status)) {
-            return true;
+            return existingStatus;
         }
         else if (existingStatus.equals(GroupMemberStatus.DELETED)) {
             // hard delete, not customizable
             deleteMember(username, groupId, "system", false);
         }
 
-        return false;
+        return null;
     }
 
     public void inviteGroupMembers (UserGroupJson group, String inviter)
@@ -291,6 +292,12 @@
         ParameterChecker.checkObjectValue(members, "members");
 
         UserGroup userGroup = retrieveUserGroupById(groupId);
+        if (userGroup.getStatus() == UserGroupStatus.DELETED) {
+            throw new KustvaktException(StatusCodes.GROUP_DELETED,
+                    "Group " + userGroup.getName() + " has been deleted.",
+                    userGroup.getName());
+        }
+
         User user = authManager.getUser(inviter);
         if (isUserGroupAdmin(inviter, userGroup) || user.isSystemAdmin()) {
             for (String memberName : members) {
diff --git a/full/src/main/resources/db/new-sqlite/V1.2__triggers.sql b/full/src/main/resources/db/new-sqlite/V1.2__triggers.sql
index 0acd2f7..890e792 100644
--- a/full/src/main/resources/db/new-sqlite/V1.2__triggers.sql
+++ b/full/src/main/resources/db/new-sqlite/V1.2__triggers.sql
@@ -1,8 +1,8 @@
---CREATE TRIGGER insert_member_status AFTER INSERT ON user_group_member
---     BEGIN
---      UPDATE user_group_member SET status_date = DATETIME('NOW', 'utc')  WHERE rowid = new.rowid;
---     END;
---
+CREATE TRIGGER insert_member_status AFTER INSERT ON user_group_member
+     BEGIN
+      UPDATE user_group_member SET status_date = DATETIME('now', 'localtime')  WHERE rowid = new.rowid;
+     END;
+
 CREATE TRIGGER update_member_status AFTER UPDATE ON user_group_member	
      BEGIN
       UPDATE user_group_member SET status_date = (datetime('now','localtime'))  WHERE rowid = old.rowid;
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 e79195a..ff6a563 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
@@ -60,7 +60,7 @@
         String entity = response.getEntity(String.class);
         System.out.println(entity);
         assertEquals(Status.OK.getStatusCode(), response.getStatus());
-      
+
         JsonNode node = JsonUtils.readTree(entity);
 
         JsonNode group = node.get(1);
@@ -423,6 +423,37 @@
     }
 
     @Test
+    public void testInviteDeletedMember2 () throws UniformInterfaceException,
+            ClientHandlerException, KustvaktException {
+        // pearl has status deleted in dory group
+        String[] members = new String[] { "pearl" };
+
+        UserGroupJson userGroup = new UserGroupJson();
+        userGroup.setMembers(members);
+        // dory group
+        userGroup.setId(2);
+
+        ClientResponse response = resource().path("group").path("member")
+                .path("invite").type(MediaType.APPLICATION_JSON)
+                .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+                .header(Attributes.AUTHORIZATION,
+                        handler.createBasicAuthorizationHeaderValue("dory",
+                                "pass"))
+                .entity(userGroup).post(ClientResponse.class);
+
+        assertEquals(Status.OK.getStatusCode(), response.getStatus());
+
+        // check member
+        JsonNode node = retrieveUserGroups("pearl");
+        assertEquals(1, node.size());
+        JsonNode group = node.get(0);
+        assertEquals(GroupMemberStatus.PENDING.name(),
+                group.at("/userMemberStatus").asText());
+
+        testDeletePendingMember();
+    }
+    
+    @Test
     public void testInvitePendingMember () throws UniformInterfaceException,
             ClientHandlerException, KustvaktException {
         // marlin has status PENDING in dory group
@@ -454,11 +485,12 @@
                 node.at("/errors/0/2").asText());
     }
 
+
     @Test
-    public void testInviteDeletedMember2 () throws UniformInterfaceException,
+    public void testInviteActiveMember () throws UniformInterfaceException,
             ClientHandlerException, KustvaktException {
-        // pearl has status deleted in dory group
-        String[] members = new String[] { "pearl" };
+        // nemo has status active in dory group
+        String[] members = new String[] { "nemo" };
 
         UserGroupJson userGroup = new UserGroupJson();
         userGroup.setMembers(members);
@@ -473,19 +505,51 @@
                                 "pass"))
                 .entity(userGroup).post(ClientResponse.class);
 
-        assertEquals(Status.OK.getStatusCode(), response.getStatus());
+        assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
 
-        // check member
-        JsonNode node = retrieveUserGroups("pearl");
-        assertEquals(1, node.size());
-        JsonNode group = node.get(0);
-        assertEquals(GroupMemberStatus.PENDING.name(),
-                group.at("/userMemberStatus").asText());
-
-        testDeletePendingMember();
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(StatusCodes.GROUP_MEMBER_EXISTS,
+                node.at("/errors/0/0").asInt());
+        assertEquals(
+                "Username nemo with status ACTIVE exists in the user-group "
+                        + "dory group",
+                node.at("/errors/0/1").asText());
+        assertEquals("[nemo, ACTIVE, dory group]",
+                node.at("/errors/0/2").asText());
     }
 
+    @Test
+    public void testInviteMemberToDeletedGroup ()
+            throws UniformInterfaceException, ClientHandlerException, KustvaktException {
+        String[] members = new String[] { "nemo" };
 
+        UserGroupJson userGroup = new UserGroupJson();
+        userGroup.setMembers(members);
+        // dory's deleted group
+        userGroup.setId(4);
+
+        ClientResponse response = resource().path("group").path("member")
+                .path("invite").type(MediaType.APPLICATION_JSON)
+                .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+                .header(Attributes.AUTHORIZATION,
+                        handler.createBasicAuthorizationHeaderValue("dory",
+                                "pass"))
+                .entity(userGroup).post(ClientResponse.class);
+
+        assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(StatusCodes.GROUP_DELETED,
+                node.at("/errors/0/0").asInt());
+        assertEquals(
+                "Group deleted group has been deleted.",
+                node.at("/errors/0/1").asText());
+        assertEquals("deleted group",
+                node.at("/errors/0/2").asText());
+    }
+    
     // marlin has GroupMemberStatus.PENDING in dory group
     @Test
     public void testSubscribePendingMember () throws KustvaktException {