diff --git a/source/java/org/alfresco/rest/api/impl/NodesImpl.java b/source/java/org/alfresco/rest/api/impl/NodesImpl.java index a7561a9222..74cfe779af 100644 --- a/source/java/org/alfresco/rest/api/impl/NodesImpl.java +++ b/source/java/org/alfresco/rest/api/impl/NodesImpl.java @@ -268,6 +268,8 @@ public class NodesImpl implements Nodes new HashSet<>(Arrays.asList(new String[] {PARAM_ISFOLDER, PARAM_NODETYPE, PARAM_SUBTYPES})); /* + * Validates that node exists. + * * Note: assumes workspace://SpacesStore */ public NodeRef validateNode(String nodeId) @@ -305,9 +307,17 @@ public class NodesImpl implements Nodes return nodeRef; } + /* + * Check that nodes exists and matches given expected/excluded type(s). + */ public boolean nodeMatches(NodeRef nodeRef, Set expectedTypes, Set excludedTypes) { - if (!nodeService.exists(nodeRef)) + return nodeMatches(nodeRef, expectedTypes, excludedTypes, true); + } + + public boolean nodeMatches(NodeRef nodeRef, Set expectedTypes, Set excludedTypes, boolean existsCheck) + { + if (existsCheck && (! nodeService.exists(nodeRef))) { throw new EntityNotFoundException(nodeRef.getId()); } @@ -327,6 +337,13 @@ public class NodesImpl implements Nodes protected boolean typeMatches(QName type, Set expectedTypes, Set excludedTypes) { + if (((expectedTypes != null) && (expectedTypes.size() == 1)) && + ((excludedTypes == null) || (excludedTypes.size() == 0))) + { + // use isSubClass if checking against single expected type (and no excluded types) + return isSubClass(type, expectedTypes.iterator().next()); + } + Set allExpectedTypes = new HashSet<>(); if (expectedTypes != null) { @@ -530,6 +547,12 @@ public class NodesImpl implements Nodes if (path != null) { + // check that parent is a folder before resolving relative path + if (! nodeMatches(parentNodeRef, Collections.singleton(ContentModel.TYPE_FOLDER), null, false)) + { + throw new InvalidArgumentException("NodeId of folder is expected"); + } + // resolve path relative to current nodeId parentNodeRef = resolveNodeByPath(parentNodeRef, path, true); } @@ -670,7 +693,7 @@ public class NodesImpl implements Nodes if (selectParam.contains(PARAM_SELECT_ISLINK)) { - boolean isLink = typeMatches(nodeTypeQName, Collections.singleton(ContentModel.TYPE_LINK), null); + boolean isLink = isSubClass(nodeTypeQName, ContentModel.TYPE_LINK); node.setIsLink(isLink); } @@ -863,8 +886,15 @@ public class NodesImpl implements Nodes public CollectionWithPagingInfo listChildren(String parentFolderNodeId, Parameters parameters) { String path = parameters.getParameter(PARAM_RELATIVE_PATH); + final NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId, path); + // check that resolved node is a folder + if (! nodeMatches(parentNodeRef, Collections.singleton(ContentModel.TYPE_FOLDER), null, false)) + { + throw new InvalidArgumentException("NodeId of folder is expected"); + } + final List selectParam = parameters.getSelectedProperties(); boolean includeFolders = true; @@ -931,11 +961,6 @@ public class NodesImpl implements Nodes Paging paging = parameters.getPaging(); - if (!nodeMatches(parentNodeRef, Collections.singleton(ContentModel.TYPE_FOLDER), null)) - { - throw new InvalidArgumentException("NodeId of folder is expected"); - } - PagingRequest pagingRequest = Util.getPagingRequest(paging); final PagingResults pagingResults; @@ -1045,7 +1070,7 @@ public class NodesImpl implements Nodes // check that requested parent node exists and it's type is a (sub-)type of folder final NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId, null); - if (! nodeMatches(parentNodeRef, Collections.singleton(ContentModel.TYPE_FOLDER), null)) + if (! nodeMatches(parentNodeRef, Collections.singleton(ContentModel.TYPE_FOLDER), null, false)) { throw new InvalidArgumentException("NodeId of folder is expected: "+parentNodeRef); } @@ -1349,7 +1374,7 @@ public class NodesImpl implements Nodes { final NodeRef nodeRef = validateNode(fileNodeId); - if (! nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_CONTENT), null)) + if (! nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_CONTENT), null, false)) { throw new InvalidArgumentException("NodeId of content is expected: "+nodeRef); } @@ -1394,7 +1419,7 @@ public class NodesImpl implements Nodes { final NodeRef nodeRef = validateNode(fileNodeId); - if (!nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_CONTENT), null)) + if (!nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_CONTENT), null, false)) { throw new InvalidArgumentException("NodeId of content is expected: " + nodeRef); } diff --git a/source/test-java/org/alfresco/rest/api/tests/NodeApiTest.java b/source/test-java/org/alfresco/rest/api/tests/NodeApiTest.java index 7bb7118010..a43146d375 100644 --- a/source/test-java/org/alfresco/rest/api/tests/NodeApiTest.java +++ b/source/test-java/org/alfresco/rest/api/tests/NodeApiTest.java @@ -498,6 +498,10 @@ public class NodeApiTest extends AbstractBaseApiTest // -ve test - try to list children using relative path to node that is of wrong type (ie. not a folder/container) params = Collections.singletonMap("relativePath", folder1 + "/" + contentF1); getAll(myChildrenUrl, user1, paging, params, 400); + + // -ve test - list folder children for non-folder node with relative path should return 400 + params = Collections.singletonMap("relativePath", "/unknown"); + getAll(getChildrenUrl(contentNodeRef), user1, paging, params, 400); } /**