diff --git a/src/main/java/org/gridsuite/directory/server/DirectoryService.java b/src/main/java/org/gridsuite/directory/server/DirectoryService.java index ba21acea..e4265faf 100644 --- a/src/main/java/org/gridsuite/directory/server/DirectoryService.java +++ b/src/main/java/org/gridsuite/directory/server/DirectoryService.java @@ -248,11 +248,14 @@ public void createElementInDirectoryPath(String directoryPath, ElementAttributes insertElement(elementAttributes, parentDirectoryUuid); } - private Map getSubDirectoriesCounts(List subDirectories, List types) { - List subdirectoriesCountsList = repositoryService.getSubDirectoriesCounts(subDirectories, types); - Map subdirectoriesCountsMap = new HashMap<>(); - subdirectoriesCountsList.forEach(e -> subdirectoriesCountsMap.put(e.getId(), e.getCount())); - return subdirectoriesCountsMap; + private Map getSubDirectoriesCounts(List subDirectories, List types, String userId) { + List readableSubDirectories = subDirectories.stream().filter(dirId -> hasReadPermissions(userId, List.of(dirId))).toList(); + return repositoryService.findAllByParentIdInAndTypeIn(readableSubDirectories, types).stream() + .filter(child -> hasReadPermissions(userId, List.of(child.getId()))) + .collect(Collectors.groupingBy( + DirectoryElementRepository.ElementParentage::getParentId, + Collectors.counting() + )); } public List getDirectoryElements(UUID directoryUuid, List types, Boolean recursive, String userId) { @@ -270,25 +273,25 @@ public List getDirectoryElements(UUID directoryUuid, List descendents = repositoryService.findAllDescendants(directoryUuid).stream().toList(); return descendents .stream() - .filter(e -> types.isEmpty() || types.contains(e.getType())) + .filter(e -> (types.isEmpty() || types.contains(e.getType())) && hasReadPermissions(userId, List.of(e.getId()))) .map(ElementAttributes::toElementAttributes) .toList(); } else { - return getAllDirectoryElementsStream(directoryUuid, types).toList(); + return getAllDirectoryElementsStream(directoryUuid, types, userId).toList(); } } - private Stream getOnlyElementsStream(UUID directoryUuid, List types) { - return getAllDirectoryElementsStream(directoryUuid, types) + private Stream getOnlyElementsStream(UUID directoryUuid, List types, String userId) { + return getAllDirectoryElementsStream(directoryUuid, types, userId) .filter(elementAttributes -> !elementAttributes.getType().equals(DIRECTORY)); } - private Stream getAllDirectoryElementsStream(UUID directoryUuid, List types) { + private Stream getAllDirectoryElementsStream(UUID directoryUuid, List types, String userId) { List directoryElements = repositoryService.findAllByParentId(directoryUuid); - Map subdirectoriesCountsMap = getSubDirectoriesCountsMap(types, directoryElements); + Map subdirectoriesCountsMap = getSubDirectoriesCountsMap(types, directoryElements, userId); return directoryElements .stream() - .filter(e -> e.getType().equals(DIRECTORY) || types.isEmpty() || types.contains(e.getType())) + .filter(e -> (e.getType().equals(DIRECTORY) || types.isEmpty() || types.contains(e.getType())) && hasReadPermissions(userId, List.of(e.getId()))) .map(e -> toElementAttributes(e, subdirectoriesCountsMap.getOrDefault(e.getId(), 0L))); } @@ -299,21 +302,21 @@ public List getRootDirectories(List types, String use if (!roleService.isUserExploreAdmin()) { directoryElements = directoryElements.stream().filter(directoryElementEntity -> hasReadPermissions(userId, List.of(directoryElementEntity.getId()))).toList(); } - Map subdirectoriesCountsMap = getSubDirectoriesCountsMap(types, directoryElements); + Map subdirectoriesCountsMap = getSubDirectoriesCountsMap(types, directoryElements, userId); return directoryElements.stream() .map(e -> toElementAttributes(e, subdirectoriesCountsMap.getOrDefault(e.getId(), 0L))) .toList(); } - private Map getSubDirectoriesCountsMap(List types, List directoryElements) { - return getSubDirectoriesCounts(directoryElements.stream().map(DirectoryElementEntity::getId).toList(), types); + private Map getSubDirectoriesCountsMap(List types, List directoryElements, String userId) { + return getSubDirectoriesCounts(directoryElements.stream().map(DirectoryElementEntity::getId).toList(), types, userId); } public void updateElement(UUID elementUuid, ElementAttributes newElementAttributes, String userId) { DirectoryElementEntity directoryElement = getDirectoryElementEntity(elementUuid); if (!directoryElement.isAttributesUpdatable(newElementAttributes, userId) || !directoryElement.getName().equals(newElementAttributes.getElementName()) && - directoryHasElementOfNameAndType(directoryElement.getParentId(), newElementAttributes.getElementName(), directoryElement.getType())) { + directoryHasElementOfNameAndType(directoryElement.getParentId(), newElementAttributes.getElementName(), directoryElement.getType(), userId)) { throw new DirectoryException(NOT_ALLOWED); } @@ -350,7 +353,7 @@ private void moveElementDirectory(DirectoryElementEntity element, UUID newDirect List descendents = isDirectory ? repositoryService.findAllDescendants(element.getId()).stream().toList() : List.of(); // validate move elements - validateElementForMove(element, newDirectoryUuid, descendents.stream().map(DirectoryElementEntity::getId).collect(Collectors.toSet())); + validateElementForMove(element, newDirectoryUuid, descendents.stream().map(DirectoryElementEntity::getId).collect(Collectors.toSet()), userId); // we update the parent of the moving element updateElementParentDirectory(element, newDirectoryUuid); @@ -369,12 +372,12 @@ private void moveElementDirectory(DirectoryElementEntity element, UUID newDirect } - private void validateElementForMove(DirectoryElementEntity element, UUID newDirectoryUuid, Set descendentsUuids) { + private void validateElementForMove(DirectoryElementEntity element, UUID newDirectoryUuid, Set descendentsUuids, String userId) { if (newDirectoryUuid == element.getId() || descendentsUuids.contains(newDirectoryUuid)) { throw new DirectoryException(MOVE_IN_DESCENDANT_NOT_ALLOWED); } - if (directoryHasElementOfNameAndType(newDirectoryUuid, element.getName(), element.getType())) { + if (directoryHasElementOfNameAndType(newDirectoryUuid, element.getName(), element.getType(), userId)) { throw DirectoryException.createElementNameAlreadyExists(element.getName()); } } @@ -393,8 +396,8 @@ private void validateNewDirectory(UUID newDirectoryUuid) { } } - private boolean directoryHasElementOfNameAndType(UUID directoryUUID, String elementName, String elementType) { - return getOnlyElementsStream(directoryUUID, List.of(elementType)) + private boolean directoryHasElementOfNameAndType(UUID directoryUUID, String elementName, String elementType, String userId) { + return getOnlyElementsStream(directoryUUID, List.of(elementType), userId) .anyMatch( e -> e.getElementName().equals(elementName) ); @@ -429,7 +432,7 @@ private void deleteElement(ElementAttributes elementAttributes, String userId) { } private void deleteSubElements(UUID elementUuid, String userId) { - getAllDirectoryElementsStream(elementUuid, List.of()).forEach(elementAttributes -> deleteElement(elementAttributes, userId)); + getAllDirectoryElementsStream(elementUuid, List.of(), userId).forEach(elementAttributes -> deleteElement(elementAttributes, userId)); } /** @@ -502,15 +505,15 @@ public List getElements(List ids, boolean strictMode, L //if the user is not an admin we filter out elements he doesn't have the permission on if (!roleService.isUserExploreAdmin()) { elementEntities = elementEntities.stream().filter(directoryElementEntity -> - hasReadPermissions(userId, List.of(directoryElementEntity.getId())) - ).toList(); + hasReadPermissions(userId, List.of(directoryElementEntity.getId())) + ).toList(); } if (strictMode && elementEntities.size() != ids.stream().distinct().count()) { throw new DirectoryException(NOT_FOUND); } - Map subElementsCount = getSubDirectoriesCounts(elementEntities.stream().map(DirectoryElementEntity::getId).toList(), types); + Map subElementsCount = getSubDirectoriesCounts(elementEntities.stream().map(DirectoryElementEntity::getId).toList(), types, userId); return elementEntities.stream() .map(attribute -> toElementAttributes(attribute, subElementsCount.getOrDefault(attribute.getId(), 0L))) diff --git a/src/main/java/org/gridsuite/directory/server/repository/DirectoryElementRepository.java b/src/main/java/org/gridsuite/directory/server/repository/DirectoryElementRepository.java index 90564827..23857e7b 100644 --- a/src/main/java/org/gridsuite/directory/server/repository/DirectoryElementRepository.java +++ b/src/main/java/org/gridsuite/directory/server/repository/DirectoryElementRepository.java @@ -57,15 +57,6 @@ public interface DirectoryElementRepository extends JpaRepository getSubDirectoriesCounts(List subDirectories, List elementTypes); - @Transactional void deleteById(UUID id); @@ -101,4 +92,13 @@ interface SubDirectoryCount { "WHERE e.id IN (SELECT dh.element_id FROM DescendantHierarchy dh) AND e.id != :elementId" ) List findAllDescendants(@Param("elementId") UUID elementId); + + interface ElementParentage { + UUID getId(); + + UUID getParentId(); + } + + @Query("SELECT d.id AS id, d.parentId AS parentId FROM DirectoryElementEntity d WHERE d.parentId IN :parentIds AND (d.type = 'DIRECTORY' OR d.type IN :elementTypes)") + List findAllByParentIdsAndElementTypes(List parentIds, List elementTypes); } diff --git a/src/main/java/org/gridsuite/directory/server/services/DirectoryRepositoryService.java b/src/main/java/org/gridsuite/directory/server/services/DirectoryRepositoryService.java index cbfb71dc..ea04ca2d 100644 --- a/src/main/java/org/gridsuite/directory/server/services/DirectoryRepositoryService.java +++ b/src/main/java/org/gridsuite/directory/server/services/DirectoryRepositoryService.java @@ -105,10 +105,6 @@ public UUID getParentUuid(UUID elementUuid) { .orElse(null); } - public List getSubDirectoriesCounts(List subDirectories, List elementTypes) { - return directoryElementRepository.getSubDirectoriesCounts(subDirectories, elementTypes); - } - public List findAllByIdIn(List uuids) { return directoryElementRepository.findAllByIdIn(uuids); } @@ -117,6 +113,10 @@ public List findAllByParentId(UUID parentId) { return directoryElementRepository.findAllByParentId(parentId); } + public List findAllByParentIdInAndTypeIn(List parentIds, List types) { + return directoryElementRepository.findAllByParentIdsAndElementTypes(parentIds, types); + } + public List findRootDirectories() { return directoryElementRepository.findRootDirectories(); } diff --git a/src/test/java/org/gridsuite/directory/server/AccessRightsControlTest.java b/src/test/java/org/gridsuite/directory/server/AccessRightsControlTest.java index a5aaed1b..3f617d0a 100644 --- a/src/test/java/org/gridsuite/directory/server/AccessRightsControlTest.java +++ b/src/test/java/org/gridsuite/directory/server/AccessRightsControlTest.java @@ -80,6 +80,9 @@ public class AccessRightsControlTest { @Autowired private DirectoryElementRepository directoryElementRepository; + @Autowired + private DirectoryService directoryService; + @Autowired private PermissionRepository permissionRepository; @@ -318,6 +321,36 @@ public void testExistence() throws Exception { insertSubElement(dirUuid1, toElementAttributes(null, "elementName1", TYPE_01, ADMIN_USER), HttpStatus.CONFLICT); } + @Test + public void testDirectoryContentWithPermissions() throws Exception { + // user1 owns a dir with 2 sub-dirs + UUID rootUuid1 = insertRootDirectory("user1", "root1"); + UUID dirUuid1 = insertSubElement(rootUuid1, toElementAttributes(null, "dir1", DIRECTORY, "user1")); + UUID dirUuid2 = insertSubElement(rootUuid1, toElementAttributes(null, "dir2", DIRECTORY, "user1")); + + // both user1 ans user2 can see them + assertEquals(2, directoryService.getDirectoryElements(rootUuid1, List.of(DIRECTORY), false, "user1").size()); + assertEquals(2, directoryService.getDirectoryElements(rootUuid1, List.of(DIRECTORY), false, "user2").size()); + + // user1 restraints access to dir2 + List newPermissions = List.of( + new PermissionDTO(false, List.of(), PermissionType.READ), + new PermissionDTO(false, List.of(), PermissionType.WRITE) + ); + updateDirectoryPermissions("user1", dirUuid2, newPermissions).andExpect(status().isOk()); + + // only user1 still sees 2 sub-dirs ; users2 only 1 + assertEquals(2, directoryService.getDirectoryElements(rootUuid1, List.of(DIRECTORY), false, "user1").size()); + assertEquals(1, directoryService.getDirectoryElements(rootUuid1, List.of(DIRECTORY), false, "user2").size()); + + // user1 restraints access to dir1 + updateDirectoryPermissions("user1", dirUuid1, newPermissions).andExpect(status().isOk()); + + // only user1 still sees 2 sub-dirs ; users2 nothing + assertEquals(2, directoryService.getDirectoryElements(rootUuid1, List.of(DIRECTORY), false, "user1").size()); + assertEquals(0, directoryService.getDirectoryElements(rootUuid1, List.of(DIRECTORY), false, "user2").size()); + } + @Test public void testSetDirectoryPermissions() throws Exception { UUID rootDirectoryUuid = insertRootDirectory(ADMIN_USER, "root1"); diff --git a/src/test/java/org/gridsuite/directory/server/DirectoryTest.java b/src/test/java/org/gridsuite/directory/server/DirectoryTest.java index e8f87130..471af1b2 100644 --- a/src/test/java/org/gridsuite/directory/server/DirectoryTest.java +++ b/src/test/java/org/gridsuite/directory/server/DirectoryTest.java @@ -1121,18 +1121,18 @@ public void testGetElement() { @Test public void testGetElementWithNonAdminUser() { // Insert a root directory by the user1 - UUID rootDirUuid = insertAndCheckRootDirectory("rootDir1", "user1"); + UUID rootDirUuid = insertAndCheckRootDirectory("rootDir1", ADMIN_USER); // Insert an element of type TYPE_02 in the root directory by the user1 - ElementAttributes element1Attributes = toElementAttributes(TYPE_02_UUID, "elementName1", TYPE_02, "user1"); + ElementAttributes element1Attributes = toElementAttributes(TYPE_02_UUID, "elementName1", TYPE_02, ADMIN_USER); insertAndCheckSubElementInRootDir(rootDirUuid, element1Attributes); // Insert an element of type TYPE_03 in the root directory by the user1 - ElementAttributes element2Attributes = toElementAttributes(TYPE_03_UUID, "elementName2", TYPE_03, "user1"); + ElementAttributes element2Attributes = toElementAttributes(TYPE_03_UUID, "elementName2", TYPE_03, ADMIN_USER); insertAndCheckSubElementInRootDir(rootDirUuid, element2Attributes); // Insert an element of type TYPE_03 in the root directory by the user1 - ElementAttributes element3Attributes = toElementAttributes(UUID.randomUUID(), "elementName3", TYPE_03, "user1"); + ElementAttributes element3Attributes = toElementAttributes(UUID.randomUUID(), "elementName3", TYPE_03, ADMIN_USER); insertAndCheckSubElementInRootDir(rootDirUuid, element3Attributes); ElementAttributes rootDirectory = getElements(List.of(rootDirUuid), "user1", false, 200).get(0);