mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-10-01 14:41:46 +00:00
MNT-20714: /nodes/{nodeId}/content REST API fails for content created by a deleted user
cherry-pick 3bf2a0ce73
from master
This commit is contained in:
@@ -2449,26 +2449,21 @@ public class NodesImpl implements Nodes
|
||||
@Override
|
||||
public Node moveOrCopyNode(String sourceNodeId, String targetParentId, String name, Parameters parameters, boolean isCopy)
|
||||
{
|
||||
FileInfo fi = retryingTransactionHelper.doInTransaction(() -> {
|
||||
if ((sourceNodeId == null) || (sourceNodeId.isEmpty()))
|
||||
{
|
||||
throw new InvalidArgumentException("Missing sourceNodeId");
|
||||
}
|
||||
|
||||
if ((targetParentId == null) || (targetParentId.isEmpty()))
|
||||
{
|
||||
throw new InvalidArgumentException("Missing targetParentId");
|
||||
}
|
||||
|
||||
final NodeRef parentNodeRef = validateOrLookupNode(targetParentId, null);
|
||||
final NodeRef sourceNodeRef = validateOrLookupNode(sourceNodeId, null);
|
||||
|
||||
return moveOrCopyImpl(sourceNodeRef, parentNodeRef, name, isCopy);
|
||||
}, false, true);
|
||||
if ((sourceNodeId == null) || (sourceNodeId.isEmpty()))
|
||||
{
|
||||
throw new InvalidArgumentException("Missing sourceNodeId");
|
||||
}
|
||||
|
||||
return retryingTransactionHelper.doInTransaction(() -> {
|
||||
return getFolderOrDocument(fi.getNodeRef().getId(), parameters);
|
||||
}, false, false);
|
||||
if ((targetParentId == null) || (targetParentId.isEmpty()))
|
||||
{
|
||||
throw new InvalidArgumentException("Missing targetParentId");
|
||||
}
|
||||
|
||||
final NodeRef parentNodeRef = validateOrLookupNode(targetParentId, null);
|
||||
final NodeRef sourceNodeRef = validateOrLookupNode(sourceNodeId, null);
|
||||
|
||||
FileInfo fi = moveOrCopyImpl(sourceNodeRef, parentNodeRef, name, isCopy);
|
||||
return getFolderOrDocument(fi.getNodeRef().getId(), parameters);
|
||||
}
|
||||
|
||||
public void updateCustomAspects(NodeRef nodeRef, List<String> aspectNames, List<QName> excludedAspects)
|
||||
@@ -3271,28 +3266,22 @@ public class NodesImpl implements Nodes
|
||||
@Override
|
||||
public Node lock(String nodeId, LockInfo lockInfo, Parameters parameters)
|
||||
{
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
NodeRef nodeRef = validateOrLookupNode(nodeId, null);
|
||||
NodeRef nodeRef = validateOrLookupNode(nodeId, null);
|
||||
|
||||
if (isSpecialNode(nodeRef, getNodeType(nodeRef)))
|
||||
{
|
||||
throw new PermissionDeniedException("Current user doesn't have permission to lock node " + nodeId);
|
||||
}
|
||||
if (isSpecialNode(nodeRef, getNodeType(nodeRef)))
|
||||
{
|
||||
throw new PermissionDeniedException("Current user doesn't have permission to lock node " + nodeId);
|
||||
}
|
||||
|
||||
if (!nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_CONTENT), null, false))
|
||||
{
|
||||
throw new InvalidArgumentException("Node of type cm:content or a subtype is expected: " + nodeId);
|
||||
}
|
||||
if (!nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_CONTENT), null, false))
|
||||
{
|
||||
throw new InvalidArgumentException("Node of type cm:content or a subtype is expected: " + nodeId);
|
||||
}
|
||||
|
||||
LockInfo validatedLockInfo = validateLockInformation(lockInfo);
|
||||
lockService.lock(nodeRef, validatedLockInfo.getMappedType(), validatedLockInfo.getTimeToExpire(), validatedLockInfo.getLifetime());
|
||||
LockInfo validatedLockInfo = validateLockInformation(lockInfo);
|
||||
lockService.lock(nodeRef, validatedLockInfo.getMappedType(), validatedLockInfo.getTimeToExpire(), validatedLockInfo.getLifetime());
|
||||
|
||||
return null;
|
||||
}, false, true);
|
||||
|
||||
return retryingTransactionHelper.doInTransaction(() -> {
|
||||
return getFolderOrDocument(nodeId, parameters);
|
||||
}, false, false);
|
||||
return getFolderOrDocument(nodeId, parameters);
|
||||
}
|
||||
|
||||
private LockInfo validateLockInformation(LockInfo lockInfo)
|
||||
@@ -3316,25 +3305,19 @@ public class NodesImpl implements Nodes
|
||||
@Override
|
||||
public Node unlock(String nodeId, Parameters parameters)
|
||||
{
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
NodeRef nodeRef = validateOrLookupNode(nodeId, null);
|
||||
NodeRef nodeRef = validateOrLookupNode(nodeId, null);
|
||||
|
||||
if (isSpecialNode(nodeRef, getNodeType(nodeRef)))
|
||||
{
|
||||
throw new PermissionDeniedException("Current user doesn't have permission to unlock node " + nodeId);
|
||||
}
|
||||
if (!lockService.isLocked(nodeRef))
|
||||
{
|
||||
throw new IntegrityException("Can't unlock node " + nodeId + " because it isn't locked", null);
|
||||
}
|
||||
if (isSpecialNode(nodeRef, getNodeType(nodeRef)))
|
||||
{
|
||||
throw new PermissionDeniedException("Current user doesn't have permission to unlock node " + nodeId);
|
||||
}
|
||||
if (!lockService.isLocked(nodeRef))
|
||||
{
|
||||
throw new IntegrityException("Can't unlock node " + nodeId + " because it isn't locked", null);
|
||||
}
|
||||
|
||||
lockService.unlock(nodeRef);
|
||||
return null;
|
||||
}, false, true);
|
||||
|
||||
return retryingTransactionHelper.doInTransaction(() -> {
|
||||
return getFolderOrDocument(nodeId, parameters);
|
||||
}, false, false);
|
||||
lockService.unlock(nodeRef);
|
||||
return getFolderOrDocument(nodeId, parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -163,7 +163,7 @@ public class Node implements Comparable<Node>
|
||||
PersonService.PersonInfo pInfo = null;
|
||||
try
|
||||
{
|
||||
NodeRef pNodeRef = personService.getPerson(userName, false);
|
||||
NodeRef pNodeRef = personService.getPersonOrNull(userName);
|
||||
if (pNodeRef != null)
|
||||
{
|
||||
pInfo = personService.getPerson(pNodeRef);
|
||||
|
@@ -4431,6 +4431,76 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest
|
||||
assertEquals(f1Id, documentResp.getParentId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests update of content after owner of the document is deleted
|
||||
* <p>PUT:</p>
|
||||
* {@literal <host>:<port>/alfresco/api/-default-/public/alfresco/versions/1/nodes/<nodeId>/content}
|
||||
*/
|
||||
@Test
|
||||
public void testUploadContentDeletedOwner() throws Exception
|
||||
{
|
||||
// Create person2delete
|
||||
String personToDelete = createUser("usertodelete-" + RUNID, "userdelPassword", networkOne);
|
||||
|
||||
// PersonToDelete creates a site and adds user1 as a site collab
|
||||
setRequestContext(personToDelete);
|
||||
String site1Title = "site-testUploadContentDeadUser_DocLib-" + RUNID;
|
||||
String site1Id = createSite(site1Title, SiteVisibility.PUBLIC).getId();
|
||||
String site1DocLibNodeId = getSiteContainerNodeId(site1Id, "documentLibrary");
|
||||
|
||||
addSiteMember(site1Id, user1, SiteRole.SiteCollaborator);
|
||||
|
||||
// PersonToDelete creates a file within DL
|
||||
Document deadDoc = createTextFile(site1DocLibNodeId, "testdeaddoc.txt", "The quick brown fox jumps over the lazy dog 1.");
|
||||
final String deadDocUrl = getNodeContentUrl(deadDoc.getId());
|
||||
|
||||
// PersonToDelete updates the file
|
||||
String content = "Soft you a word or two before you go... I took by the throat the circumcised dog, And smote him, thus.";
|
||||
String docName = "goodbye-world.txt";
|
||||
Map params_doc = new HashMap<>();
|
||||
params_doc.put(Nodes.PARAM_NAME, docName);
|
||||
deadDoc = updateFileWithContent(deadDoc.getId(), content, params_doc, 200);
|
||||
assertEquals("person2delete cannot update document", docName, deadDoc.getName());
|
||||
|
||||
// Download the file and confirm its contents on person2delete
|
||||
HttpResponse response = getSingle(deadDocUrl, personToDelete, null, 200);
|
||||
assertEquals("person2delete cannot view document", content, response.getResponse());
|
||||
|
||||
// Download the file and confirm its contents on user1
|
||||
response = getSingle(deadDocUrl, user1, null, 200);
|
||||
assertEquals("user1 cannot view document", content, response.getResponse());
|
||||
|
||||
// PersonToDelete is deleted
|
||||
transactionHelper.doInTransaction(() -> {
|
||||
deleteUser(personToDelete, networkOne);
|
||||
return null;
|
||||
});
|
||||
|
||||
// User1 updates the file
|
||||
setRequestContext(user1);
|
||||
content = "This did I fear, but thought he had no weapon; For he was great of heart.";
|
||||
updateFileWithContent(deadDoc.getId(), content, null, 200);
|
||||
|
||||
// Download the file and confirm its contents (ensure rollback didn't happen)
|
||||
response = getSingle(deadDocUrl, user1, null, 200);
|
||||
assertEquals("user1 cannot update after owner is deleted", content, response.getResponse());
|
||||
}
|
||||
|
||||
private Document updateFileWithContent(String docId, String content, Map<String, String> params, int expectedStatus) throws Exception
|
||||
{
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(content.getBytes());
|
||||
File txtFile = TempFileProvider.createTempFile(inputStream, getClass().getSimpleName(), ".txt");
|
||||
|
||||
BinaryPayload payload = new BinaryPayload(txtFile);
|
||||
|
||||
HttpResponse response = putBinary(getNodeContentUrl(docId), payload, null, params, expectedStatus);
|
||||
if (expectedStatus != 200)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates authority context
|
||||
*
|
||||
|
Reference in New Issue
Block a user