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 a3d57a020a5a298e852021d9628a4a9a74d78055..95fe2b1b843475f2178225c7900ab477272b2b0d 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 @@ -110,31 +110,31 @@ public class JWTWebServiceController { @GetMapping(value = {"/ws/jwt/search/**", "/vo/search/**"}, produces = MediaType.TEXT_PLAIN_VALUE) public void isMemberOf(HttpServletRequest request, HttpServletResponse response) throws IOException { - String group = getGroupFromRequest(request, "/ws/jwt/search/", "/vo/search/"); - - List<String> groupNames = groupNameService.extractGroupNames(group); - - boolean isMember = membershipManager.isCurrentUserMemberOf("ROOT"); - if (!isMember) { - String parentPath = ""; // starting from ROOT - for (String groupName : groupNames) { - Optional<GroupEntity> optionalGroup = groupsDAO.findGroupByParentAndName(parentPath, groupName); - if (optionalGroup.isPresent()) { - GroupEntity groupEntity = optionalGroup.get(); - parentPath = groupEntity.getPath(); - isMember = membershipManager.isCurrentUserMemberOf(groupEntity.getId()); - if (isMember) { - break; - } - } else { - break; + String groupNamesString = getGroupFromRequest(request, "/ws/jwt/search/", "/vo/search/"); + + List<String> groupNames = groupNameService.extractGroupNames(groupNamesString); + + GroupEntity group = null; + + String parentPath = ""; // starting from ROOT + for (String groupName : groupNames) { + Optional<GroupEntity> optionalGroup = groupsDAO.findGroupByParentAndName(parentPath, groupName); + if (optionalGroup.isPresent()) { + GroupEntity groupEntity = optionalGroup.get(); + parentPath = groupEntity.getPath(); + boolean isMember = membershipManager.isCurrentUserMemberOf(groupEntity.getId()); + if (isMember) { + group = groupEntity; } + } else { + group = null; + break; } } - if (isMember) { + if (group != null) { try ( PrintWriter pw = new PrintWriter(response.getOutputStream())) { - pw.println(group); + pw.println(groupNameService.getCompleteName(groupNames)); } } // else: empty response (as defined by GMS standard) diff --git a/gms/src/main/java/it/inaf/ia2/gms/persistence/MembershipsDAO.java b/gms/src/main/java/it/inaf/ia2/gms/persistence/MembershipsDAO.java index 2a4309d7f53f616e93ae895da6fa6c89bd5325fe..06476e98d944b291ff965b3ea647af3e7f706e95 100644 --- a/gms/src/main/java/it/inaf/ia2/gms/persistence/MembershipsDAO.java +++ b/gms/src/main/java/it/inaf/ia2/gms/persistence/MembershipsDAO.java @@ -120,18 +120,22 @@ public class MembershipsDAO { public boolean isMemberOf(String userId, String groupId) { - String sql = "SELECT COUNT(*) FROM gms_membership " - + " WHERE user_id = ? AND group_id = ?"; + String sql = "SELECT COUNT(*)\n" + + "FROM gms_membership m\n" + + "JOIN gms_group g ON g.id = m.group_id\n" + + "JOIN gms_group gs ON g.path @> gs.path\n" + + "WHERE gs.id = ?\n" + + "AND m.user_id = ?"; return jdbcTemplate.query(conn -> { PreparedStatement ps = conn.prepareStatement(sql); - ps.setString(1, userId); - ps.setString(2, groupId); + ps.setString(1, groupId); + ps.setString(2, userId); return ps; }, resultSet -> { resultSet.next(); int count = resultSet.getInt(1); - return count == 1; + return count > 0; }); } diff --git a/gms/src/main/java/it/inaf/ia2/gms/service/GroupNameService.java b/gms/src/main/java/it/inaf/ia2/gms/service/GroupNameService.java index f6651e0f4f730b2a5b22d6a823152559a227daa5..8b58646149e0038c886b53d67d938d7b3cec0040 100644 --- a/gms/src/main/java/it/inaf/ia2/gms/service/GroupNameService.java +++ b/gms/src/main/java/it/inaf/ia2/gms/service/GroupNameService.java @@ -157,6 +157,12 @@ public class GroupNameService { return names; } + public String getCompleteName(List<String> names) { + return String.join(".", names.stream() + .map(n -> n.replace(".", "\\.")) + .collect(Collectors.toList())); + } + private GroupEntity getRoot() { return groupsDAO.findGroupById("ROOT") .orElseThrow(() -> new IllegalStateException("Missing root group")); diff --git a/gms/src/test/java/it/inaf/ia2/gms/controller/JWTWebServiceControllerTest.java b/gms/src/test/java/it/inaf/ia2/gms/controller/JWTWebServiceControllerTest.java index 952f33d4a6859021ab6a46331455cb50ccb446ad..2f4b2a165d6af91ae1f469b661521c8552b749a6 100644 --- a/gms/src/test/java/it/inaf/ia2/gms/controller/JWTWebServiceControllerTest.java +++ b/gms/src/test/java/it/inaf/ia2/gms/controller/JWTWebServiceControllerTest.java @@ -115,11 +115,15 @@ public class JWTWebServiceControllerTest { when(membershipManager.isCurrentUserMemberOf(eq(group3.getId()))).thenReturn(true); - String group = "group\\.1.subgroup.subsubgroup"; + String group = "group%5C.1.subgroup.subsubgroup"; - mockMvc.perform(get("/ws/jwt/search/" + group).principal(principal)) + mockMvc.perform(get("/vo/search/" + group).principal(principal)) .andExpect(status().isOk()) - .andExpect(content().string(group + "\n")); + .andExpect(content().string("group\\.1.subgroup.subsubgroup\n")); + + mockMvc.perform(get("/vo/search/" + group + "/inexistent").principal(principal)) + .andExpect(status().isOk()) + .andExpect(content().string("")); } @Test diff --git a/gms/src/test/java/it/inaf/ia2/gms/persistence/MembershipsDAOTest.java b/gms/src/test/java/it/inaf/ia2/gms/persistence/MembershipsDAOTest.java index cb32b194eec76987f1bc9df058b0205bf7167a57..4529f4996aa89d9826334391263107c4b96f4c0f 100644 --- a/gms/src/test/java/it/inaf/ia2/gms/persistence/MembershipsDAOTest.java +++ b/gms/src/test/java/it/inaf/ia2/gms/persistence/MembershipsDAOTest.java @@ -37,8 +37,8 @@ public class MembershipsDAOTest { @Test public void testAddAndRemoveMembers() { - groupsDAO.createGroup(groupEntity("A")); - groupsDAO.createGroup(groupEntity("B")); + groupsDAO.createGroup(groupEntity("A", "A")); + groupsDAO.createGroup(groupEntity("B", "B")); assertTrue(membershipsDAO.findByGroup("A").isEmpty()); @@ -72,11 +72,48 @@ public class MembershipsDAOTest { membershipsDAO.deleteAllGroupsMembership(new ArrayList<>()); } - private GroupEntity groupEntity(String groupId) { + @Test + public void testIsMemberOfRecursive() { + + groupsDAO.createGroup(groupEntity("ROOT", "")); + + groupsDAO.createGroup(groupEntity("A", "A")); + groupsDAO.createGroup(groupEntity("E", "A.E")); + groupsDAO.createGroup(groupEntity("F", "A.E.F")); + + groupsDAO.createGroup(groupEntity("B", "B")); + groupsDAO.createGroup(groupEntity("C", "B.C")); + groupsDAO.createGroup(groupEntity("D", "B.C.D")); + + membershipsDAO.addMember(membershipEntity(USER_1, "F")); + membershipsDAO.addMember(membershipEntity(USER_1, "C")); + + assertFalse(membershipsDAO.isMemberOf(USER_1, "ROOT")); + assertFalse(membershipsDAO.isMemberOf(USER_1, "A")); + assertFalse(membershipsDAO.isMemberOf(USER_1, "B")); + assertTrue(membershipsDAO.isMemberOf(USER_1, "C")); + assertTrue(membershipsDAO.isMemberOf(USER_1, "D")); + assertFalse(membershipsDAO.isMemberOf(USER_1, "E")); + assertTrue(membershipsDAO.isMemberOf(USER_1, "F")); + + membershipsDAO.addMember(membershipEntity(USER_1, "ROOT")); + + assertTrue(membershipsDAO.isMemberOf(USER_1, "ROOT")); + assertTrue(membershipsDAO.isMemberOf(USER_1, "A")); + assertTrue(membershipsDAO.isMemberOf(USER_1, "B")); + assertTrue(membershipsDAO.isMemberOf(USER_1, "C")); + assertTrue(membershipsDAO.isMemberOf(USER_1, "D")); + assertTrue(membershipsDAO.isMemberOf(USER_1, "E")); + assertTrue(membershipsDAO.isMemberOf(USER_1, "F")); + + assertFalse(membershipsDAO.isMemberOf(USER_1, "inexistent-id")); + } + + private GroupEntity groupEntity(String groupId, String groupPath) { GroupEntity groupEntity = new GroupEntity(); groupEntity.setId(groupId); groupEntity.setName(groupId); - groupEntity.setPath(groupId); + groupEntity.setPath(groupPath); groupEntity.setLeaf(false); return groupEntity; }