diff --git a/source/java/org/alfresco/rest/api/Nodes.java b/source/java/org/alfresco/rest/api/Nodes.java index 76cef2d925..8ead27f7d0 100644 --- a/source/java/org/alfresco/rest/api/Nodes.java +++ b/source/java/org/alfresco/rest/api/Nodes.java @@ -245,7 +245,7 @@ public interface Nodes * @return */ List addTargets(String sourceNodeId, List entities); - + /** * Lock a node * @param nodeId @@ -254,7 +254,7 @@ public interface Nodes * @return */ Node lock(String nodeId, LockInfo lockInfo, Parameters parameters); - + /** * Unlock a node * @param nodeId diff --git a/source/java/org/alfresco/rest/api/impl/NodesImpl.java b/source/java/org/alfresco/rest/api/impl/NodesImpl.java index db2550d25b..a9e3e234ed 100644 --- a/source/java/org/alfresco/rest/api/impl/NodesImpl.java +++ b/source/java/org/alfresco/rest/api/impl/NodesImpl.java @@ -1333,7 +1333,7 @@ public class NodesImpl implements Nodes Set assocTypeQNames = buildAssocTypes(assocTypeQNameParam); // call GetChildrenCannedQuery (via FileFolderService) - if (((filterProps == null) || (filterProps.size() == 0)) && + if (((filterProps == null) || (filterProps.size() == 0)) && ((assocTypeQNames == null) || (assocTypeQNames.size() == 0)) && (smartStore.isVirtual(parentNodeRef)|| (smartStore.canVirtualize(parentNodeRef)))) { @@ -1996,11 +1996,11 @@ public class NodesImpl implements Nodes return false; } - + private boolean isLocked(NodeRef nodeRef, Set aspects) { boolean locked = false; - if (((aspects != null) && aspects.contains(ContentModel.ASPECT_LOCKABLE)) + if (((aspects != null) && aspects.contains(ContentModel.ASPECT_LOCKABLE)) || nodeService.hasAspect(nodeRef, ContentModel.ASPECT_LOCKABLE)) { locked = lockService.isLocked(nodeRef); @@ -2970,10 +2970,10 @@ public class NodesImpl implements Nodes lockInfo = validateLockInformation(lockInfo); lockService.lock(nodeRef, lockInfo.getMappedType(), lockInfo.getTimeToExpire(), lockInfo.getLifetime()); - + return getFolderOrDocument(nodeId, parameters); } - + private LockInfo validateLockInformation(LockInfo lockInfo) { // Set default values for the lock details. @@ -3001,7 +3001,7 @@ public class NodesImpl implements Nodes { throw new PermissionDeniedException("Current user doesn't have permission to unlock node " + nodeId); } - + lockService.unlock(nodeRef); return getFolderOrDocument(nodeId, parameters); } diff --git a/source/java/org/alfresco/rest/api/nodes/NodesEntityResource.java b/source/java/org/alfresco/rest/api/nodes/NodesEntityResource.java index 71e12e0d1f..7fec701ba9 100644 --- a/source/java/org/alfresco/rest/api/nodes/NodesEntityResource.java +++ b/source/java/org/alfresco/rest/api/nodes/NodesEntityResource.java @@ -1,4 +1,4 @@ -/* +/* * #%L * Alfresco Remote API * %% @@ -9,43 +9,43 @@ * the paid license agreement will prevail. Otherwise, the software is * provided under the following open source license terms: * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - * #L% - */ + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ package org.alfresco.rest.api.nodes; -import java.io.InputStream; - -import javax.servlet.http.HttpServletResponse; - -import org.alfresco.rest.api.Nodes; -import org.alfresco.rest.api.model.LockInfo; -import org.alfresco.rest.api.model.Node; -import org.alfresco.rest.api.model.NodeTarget; -import org.alfresco.rest.framework.BinaryProperties; -import org.alfresco.rest.framework.Operation; -import org.alfresco.rest.framework.WebApiDescription; -import org.alfresco.rest.framework.WebApiParam; -import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; -import org.alfresco.rest.framework.resource.EntityResource; -import org.alfresco.rest.framework.resource.actions.interfaces.BinaryResourceAction; -import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction; -import org.alfresco.rest.framework.resource.content.BasicContentInfo; -import org.alfresco.rest.framework.resource.content.BinaryResource; -import org.alfresco.rest.framework.resource.parameters.Parameters; -import org.alfresco.rest.framework.webscripts.WithResponse; -import org.alfresco.util.ParameterCheck; +import java.io.InputStream; + +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.rest.api.Nodes; +import org.alfresco.rest.api.model.LockInfo; +import org.alfresco.rest.api.model.Node; +import org.alfresco.rest.api.model.NodeTarget; +import org.alfresco.rest.framework.BinaryProperties; +import org.alfresco.rest.framework.Operation; +import org.alfresco.rest.framework.WebApiDescription; +import org.alfresco.rest.framework.WebApiParam; +import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; +import org.alfresco.rest.framework.resource.EntityResource; +import org.alfresco.rest.framework.resource.actions.interfaces.BinaryResourceAction; +import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction; +import org.alfresco.rest.framework.resource.content.BasicContentInfo; +import org.alfresco.rest.framework.resource.content.BinaryResource; +import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.rest.framework.webscripts.WithResponse; +import org.alfresco.util.ParameterCheck; import org.springframework.beans.factory.InitializingBean; /** @@ -170,7 +170,7 @@ public class NodesEntityResource implements { return nodes.moveOrCopyNode(nodeId, target.getTargetParentId(), target.getName(), parameters, false); } - + @Operation("lock") @WebApiDescription(title = "Lock Node", description="Places a lock on a node.", @@ -178,15 +178,15 @@ public class NodesEntityResource implements public Node lock(String nodeId, LockInfo lockInfo, Parameters parameters, WithResponse withResponse) { return nodes.lock(nodeId, lockInfo, parameters); - } - - @Operation("unlock") - @WebApiDescription(title = "Unlock Node", - description="Removes a lock on a node.", - successStatus = HttpServletResponse.SC_OK) - public Node unlock(String nodeId, Void ignore, Parameters parameters, WithResponse withResponse) - { - return nodes.unlock(nodeId, parameters); + } + + @Operation("unlock") + @WebApiDescription(title = "Unlock Node", + description="Removes a lock on a node.", + successStatus = HttpServletResponse.SC_OK) + public Node unlock(String nodeId, Void ignore, Parameters parameters, WithResponse withResponse) + { + return nodes.unlock(nodeId, parameters); } } 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 169075d696..c5e6c22f2d 100644 --- a/source/test-java/org/alfresco/rest/api/tests/NodeApiTest.java +++ b/source/test-java/org/alfresco/rest/api/tests/NodeApiTest.java @@ -86,6 +86,7 @@ import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.site.SiteVisibility; import org.alfresco.util.GUID; import org.alfresco.util.TempFileProvider; +import org.apache.http.HttpStatus; import org.json.simple.JSONObject; import org.junit.After; import org.junit.Before; @@ -113,7 +114,7 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest private static final String URL_DELETED_NODES = "deleted-nodes"; private static final String EMPTY_BODY = "{}"; - + protected PermissionService permissionService; @@ -3579,7 +3580,7 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest // some cleanup deleteNode(folderId, true, 204); } - + /** * Tests lock of a node *

POST:

@@ -3589,7 +3590,7 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest public void testLock() throws Exception { setRequestContext(user1); - + // create folder Folder folderResp = createFolder(Nodes.PATH_MY, "folder" + RUNID); String folderId = folderResp.getId(); @@ -3632,14 +3633,14 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest // Lock on already locked node post(getNodeOperationUrl(d1Id, "lock"), toJsonAsStringNonNull(lockInfo), null, 200); - + // Test delete on a folder which contains a locked node - NodeLockedException deleteNode(folderId, true, 409); - + // Content update on a locked node updateTextFile(d1Id, "Updated text", null, 409); unlock(d1Id); - + // Test lock file // create folder String folderAName = "folder" + RUNID + "_A"; @@ -3649,7 +3650,7 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest // create a file in the folderA Document dA1 = createTextFile(folderAId, "content" + RUNID + "_A1", "A1 content"); String dA1Id = dA1.getId(); - + lockInfo = new LockInfo(); lockInfo.setTimeToExpire(60); lockInfo.setType("ALLOW_OWNER_CHANGES"); @@ -3657,22 +3658,22 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest // lock the file post(getNodeOperationUrl(dA1Id, "lock"), toJsonAsStringNonNull(lockInfo), null, 200); - + params = Collections.singletonMap("include", "aspectNames,properties,isLocked"); response = getSingle(URL_NODES, dA1Id, params, null, 200); node = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Node.class); assertTrue(node.getIsLocked()); // note: this can be updated by the owner since the lock type is "ALLOW_OWNER_CHANGES" updateTextFile(node.getId(), "Updated text", null, 200); - + // Lock body properties - boundary values Document dB1 = createTextFile(folderAId, "content" + RUNID + "_dB1", "dB1 content"); String dB1Id = dB1.getId(); - + lockInfo = new LockInfo(); lockInfo.setTimeToExpire(-100); // values lower than 0 are considered as no expiry time post(getNodeOperationUrl(dB1Id, "lock"), toJsonAsStringNonNull(lockInfo), null, 200); - + // Lock node by a different user than the owner setRequestContext(user1); Folder folder1Resp = createFolder(Nodes.PATH_SHARED, "folder1" + RUNID); @@ -3690,7 +3691,7 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest // Missing target node lockInfo = new LockInfo(); post(getNodeOperationUrl("fakeId", "lock"), toJsonAsStringNonNull(lockInfo), null, 404); - + // Cannot lock Data Dictionary node params = new HashMap<>(); params.put(Nodes.PARAM_RELATIVE_PATH, "/Data Dictionary"); @@ -3703,7 +3704,7 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest // Lock node already locked by another user - UnableToAquireLockException post(getNodeOperationUrl(dB1Id, "lock"), EMPTY_BODY, null, 422); - + // Lock node without permission (node created by user 1 in the Home folder) setRequestContext(user1); Folder folder2Resp = createFolder(Nodes.PATH_MY, "folder2" + RUNID); @@ -3715,10 +3716,10 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest setRequestContext(user2); post(getNodeOperationUrl(f2d1Id, "lock"), EMPTY_BODY, null, 403); - + // Invalid lock body values setRequestContext(user1); - + Folder folderC = createFolder(Nodes.PATH_MY, "folder" + RUNID + "_C"); String folderCId = folderC.getId(); @@ -3732,22 +3733,22 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest body = new HashMap<>(); body.put("type", "ALLOW_ADD_CHILDREN"); post(getNodeOperationUrl(dC1Id, "lock"), toJsonAsStringNonNull(body), null, 400); - + body = new HashMap<>(); body.put("lifetime", "PERSISTENT123"); post(getNodeOperationUrl(dC1Id, "lock"), toJsonAsStringNonNull(body), null, 400); - + body = new HashMap<>(); body.put("timeToExpire", "NaN"); post(getNodeOperationUrl(dC1Id, "lock"), toJsonAsStringNonNull(body), null, 400); - + body = new HashMap<>(); body.put("invalid_property", "true"); post(getNodeOperationUrl(dC1Id, "lock"), toJsonAsStringNonNull(body), null, 400); // Invalid lock of a folder post(getNodeOperationUrl(folderId, "lock"), toJsonAsStringNonNull(lockInfo), null, 400); - + //cleanup setRequestContext(user1); // all locks were made by user1 unlock(dB1Id); @@ -3758,8 +3759,8 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest deleteNode(folder1Id); deleteNode(folder2Id); } - - + + /** * Tests unlock of a node *

POST:

@@ -3769,16 +3770,16 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest public void testUnlock() throws Exception { setRequestContext(user1); - + // create folder Folder folderResp = createFolder(Nodes.PATH_MY, "folder" + RUNID); String folderId = folderResp.getId(); - + // create doc d1 String d1Name = "content" + RUNID + "_1l"; Document d1 = createTextFile(folderId, d1Name, "The quick brown fox jumps over the lazy dog 1."); String d1Id = d1.getId(); - + lock(d1Id, EMPTY_BODY); HttpResponse response = post(getNodeOperationUrl(d1Id, "unlock"), null, null, 200); @@ -3788,32 +3789,32 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest assertEquals(d1Id, documentResp.getId()); assertNull(documentResp.getProperties().get("cm:lockType")); assertNull(documentResp.getProperties().get("cm:lockOwner")); - + lock(d1Id, EMPTY_BODY); // Users with admin rights can unlock nodes locked by other users. setRequestContext(networkAdmin); post(getNodeOperationUrl(d1Id, "unlock"), null, null, 200); - + // -ve // Missing target node post(getNodeOperationUrl("fakeId", "unlock"), null, null, 404); - + // Unlock by a user without permission lock(d1Id, EMPTY_BODY); setRequestContext(user2); post(getNodeOperationUrl(d1Id, "unlock"), null, null, 403); - + setRequestContext(user1); //Unlock on a not locked node post(getNodeOperationUrl(folderId, "unlock"), null, null, 403); - + // clean up setRequestContext(user1); // all locks were made by user1 - + unlock(d1Id); deleteNode(folderId); } - + @Override public String getScope() {