From e0a092f134af09190ed987b6c17bdf620455ed42 Mon Sep 17 00:00:00 2001
From: Sonia Zorba <sonia.zorba@inaf.it>
Date: Thu, 18 Mar 2021 11:46:10 +0100
Subject: [PATCH] Added createGroup WS method to GroupsController; deprecated
 equivalent feature on JWTWebServiceController

---
 .../ia2/gms/client/call/CreateGroupCall.java  |  8 ++-
 .../ia2/gms/controller/GroupsController.java  | 39 +++++++++++-
 .../controller/JWTWebServiceController.java   |  2 +
 .../gms/controller/GroupsControllerTest.java  | 60 ++++++++++++++++++-
 4 files changed, 105 insertions(+), 4 deletions(-)

diff --git a/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/CreateGroupCall.java b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/CreateGroupCall.java
index edb5158..0b2667d 100644
--- a/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/CreateGroupCall.java
+++ b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/CreateGroupCall.java
@@ -2,9 +2,11 @@ package it.inaf.ia2.gms.client.call;
 
 import it.inaf.ia2.client.BaseCall;
 import it.inaf.ia2.gms.client.GmsClient;
+import java.net.URLEncoder;
 import java.net.http.HttpRequest;
 import java.net.http.HttpRequest.BodyPublishers;
 import java.net.http.HttpResponse.BodyHandlers;
+import java.nio.charset.StandardCharsets;
 
 public class CreateGroupCall extends BaseCall<GmsClient> {
 
@@ -14,10 +16,12 @@ public class CreateGroupCall extends BaseCall<GmsClient> {
 
     public boolean createGroup(String completeGroupName, boolean leaf) {
 
-        HttpRequest groupsRequest = client.newRequest("ws/jwt/" + completeGroupName)
+        HttpRequest groupsRequest = client.newRequest("group")
                 .header("Accept", "text/plain")
                 .header("Content-Type", "application/x-www-form-urlencoded")
-                .POST(BodyPublishers.ofString("leaf=" + leaf))
+                .POST(BodyPublishers.ofString(
+                        "name=" + URLEncoder.encode(completeGroupName, StandardCharsets.UTF_8)
+                        + "&leaf=" + leaf))
                 .build();
 
         return client.call(groupsRequest, BodyHandlers.ofInputStream(), 201, res -> true);
diff --git a/gms/src/main/java/it/inaf/ia2/gms/controller/GroupsController.java b/gms/src/main/java/it/inaf/ia2/gms/controller/GroupsController.java
index d4c855a..e806e75 100644
--- a/gms/src/main/java/it/inaf/ia2/gms/controller/GroupsController.java
+++ b/gms/src/main/java/it/inaf/ia2/gms/controller/GroupsController.java
@@ -14,9 +14,12 @@ import it.inaf.ia2.gms.model.request.RenameGroupRequest;
 import it.inaf.ia2.gms.model.request.SearchFilterRequest;
 import it.inaf.ia2.gms.persistence.model.GroupEntity;
 import it.inaf.ia2.gms.service.GroupNameService;
+import it.inaf.ia2.gms.service.GroupsService;
 import it.inaf.ia2.gms.service.GroupsTreeBuilder;
+import java.io.IOException;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
 import java.util.List;
 import java.util.Optional;
 import javax.servlet.http.HttpServletRequest;
@@ -46,6 +49,9 @@ public class GroupsController {
     @Autowired
     private GroupsManager groupsManager;
 
+    @Autowired
+    private GroupsService groupsService;
+
     @Autowired
     private GroupsTreeBuilder groupsTreeBuilder;
 
@@ -56,7 +62,7 @@ public class GroupsController {
     private GroupStatusManager groupStatusManager;
 
     @Autowired
-    private GroupNameService groupNameService;
+    protected GroupNameService groupNameService;
 
     @GetMapping(value = "/groups", produces = MediaType.APPLICATION_JSON_VALUE)
     public ResponseEntity<?> getGroupsTab(@Valid GroupsRequest request) {
@@ -139,4 +145,35 @@ public class GroupsController {
     private <T extends PaginatedModelRequest & SearchFilterRequest> PaginatedData<GroupNode> getGroupsPanel(GroupEntity parentGroup, T request) {
         return groupsTreeBuilder.listSubGroups(parentGroup, request, servletRequest.getUserPrincipal().getName());
     }
+
+    /**
+     * Creates a group and its ancestors if they are missing. It doesn't fail if
+     * the last group already exists.
+     */
+    @PostMapping(value = "/group", produces = MediaType.TEXT_PLAIN_VALUE, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
+    public void createGroup(@RequestParam("name") String groupParam,
+            @RequestParam(value = "leaf", required = false, defaultValue = "false") boolean leaf,
+            HttpServletRequest request, HttpServletResponse response) throws IOException {
+
+        List<String> groupNames = groupNameService.extractGroupNames(groupParam);
+
+        String leafParam = request.getParameter("leaf");
+        //boolean leaf = leafParam == null ? false : Boolean.valueOf(leafParam);
+
+        GroupEntity group = groupsManager.getRoot();
+        for (int i = 0; i < groupNames.size(); i++) {
+            String name = groupNames.get(i);
+            Optional<GroupEntity> optGroup = groupsService.findGroupByParentAndName(group, name);
+            if (optGroup.isPresent()) {
+                group = optGroup.get();
+            } else {
+                group = groupsManager.createGroup(group, name, i == groupNames.size() - 1 ? leaf : false);
+            }
+        }
+
+        response.setStatus(HttpServletResponse.SC_CREATED);
+        try ( PrintWriter pw = new PrintWriter(response.getOutputStream())) {
+            pw.println(groupParam);
+        }
+    }
 }
diff --git a/gms/src/main/java/it/inaf/ia2/gms/controller/JWTWebServiceController.java b/gms/src/main/java/it/inaf/ia2/gms/controller/JWTWebServiceController.java
index 983e874..38f1e4f 100644
--- a/gms/src/main/java/it/inaf/ia2/gms/controller/JWTWebServiceController.java
+++ b/gms/src/main/java/it/inaf/ia2/gms/controller/JWTWebServiceController.java
@@ -173,6 +173,8 @@ public class JWTWebServiceController {
      * Creates a group and its ancestors if they are missing. It doesn't fail if
      * the last group already exists.
      */
+    // Moved to GroupsController with different parameters
+    @Deprecated
     @PostMapping(value = "/ws/jwt/{group:.+}", produces = MediaType.TEXT_PLAIN_VALUE)
     public void createGroup(@PathVariable("group") String groupParam, HttpServletRequest request, HttpServletResponse response) throws IOException {
 
diff --git a/gms/src/test/java/it/inaf/ia2/gms/controller/GroupsControllerTest.java b/gms/src/test/java/it/inaf/ia2/gms/controller/GroupsControllerTest.java
index cdbdb8b..369a8ed 100644
--- a/gms/src/test/java/it/inaf/ia2/gms/controller/GroupsControllerTest.java
+++ b/gms/src/test/java/it/inaf/ia2/gms/controller/GroupsControllerTest.java
@@ -9,7 +9,10 @@ import it.inaf.ia2.gms.model.Permission;
 import it.inaf.ia2.gms.model.request.AddGroupRequest;
 import it.inaf.ia2.gms.model.response.GroupsTabResponse;
 import it.inaf.ia2.gms.model.response.PaginatedData;
+import it.inaf.ia2.gms.persistence.GroupsDAO;
 import it.inaf.ia2.gms.persistence.LoggingDAO;
+import it.inaf.ia2.gms.persistence.model.GroupEntity;
+import it.inaf.ia2.gms.service.GroupNameService;
 import it.inaf.ia2.gms.service.GroupsService;
 import it.inaf.ia2.gms.service.GroupsTreeBuilder;
 import java.util.ArrayList;
@@ -21,6 +24,7 @@ import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
@@ -59,6 +63,9 @@ public class GroupsControllerTest {
     @Mock
     private GroupsTreeBuilder groupsTreeBuilder;
 
+    @Mock
+    private GroupsDAO groupsDAO;
+
     @Mock
     private LoggingDAO loggingDAO;
 
@@ -72,6 +79,7 @@ public class GroupsControllerTest {
     @Before
     public void init() {
         mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
+        controller.groupNameService = new GroupNameService(groupsDAO);
         GmsTestUtils.mockPrincipal(servletRequest);
     }
 
@@ -93,7 +101,7 @@ public class GroupsControllerTest {
     }
 
     @Test
-    public void testAddGroups() throws Exception {
+    public void testAddGroupPaginated() throws Exception {
 
         AddGroupRequest request = new AddGroupRequest();
         request.setNewGroupName("New Group");
@@ -108,6 +116,7 @@ public class GroupsControllerTest {
 
         mockMvc.perform(post("/group")
                 .content(mapper.writeValueAsString(request))
+                .accept(MediaType.APPLICATION_JSON)
                 .contentType(MediaType.APPLICATION_JSON))
                 .andExpect(status().isCreated());
     }
@@ -121,4 +130,53 @@ public class GroupsControllerTest {
 
         verify(groupsManager, times(1)).deleteGroup(eq("id"));
     }
+
+    @Test
+    public void testAddGroupTextPlain() throws Exception {
+
+        GroupEntity peopleGroup = getPeopleGroup();
+
+        when(groupsManager.getRoot()).thenReturn(getRoot());
+        when(groupsManager.createGroup(any(GroupEntity.class), eq("people"), eq(false))).thenReturn(peopleGroup);
+        when(groupsManager.createGroup(any(GroupEntity.class), eq("name.surname"), eq(true))).thenReturn(getNameSurnameGroup());
+
+        mockMvc.perform(post("/group")
+                .param("name", "people.name\\.surname")
+                .param("leaf", "true")
+                .accept(MediaType.TEXT_PLAIN)
+                .contentType(MediaType.APPLICATION_FORM_URLENCODED))
+                .andExpect(status().isCreated());
+
+        verify(groupsService, times(2)).findGroupByParentAndName(any(GroupEntity.class), any());
+        verify(groupsManager, times(1)).createGroup(argGroupIdEq(GroupsService.ROOT), eq("people"), eq(false));
+        verify(groupsManager, times(1)).createGroup(argGroupIdEq("people_id"), eq("name.surname"), eq(true));
+    }
+
+    private GroupEntity argGroupIdEq(String groupId) {
+        return argThat(g -> g.getId().equals(groupId));
+    }
+
+    private GroupEntity getRoot() {
+        GroupEntity root = new GroupEntity();
+        root.setId(GroupsService.ROOT);
+        root.setName(GroupsService.ROOT);
+        root.setPath("");
+        return root;
+    }
+
+    private GroupEntity getPeopleGroup() {
+        GroupEntity lbt = new GroupEntity();
+        lbt.setId("people_id");
+        lbt.setName("people");
+        lbt.setPath("people_id");
+        return lbt;
+    }
+
+    private GroupEntity getNameSurnameGroup() {
+        GroupEntity inaf = new GroupEntity();
+        inaf.setId("user_group_id");
+        inaf.setName("name.surname");
+        inaf.setPath("people_id.user_group_id");
+        return inaf;
+    }
 }
-- 
GitLab