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:
Andrei Forascu
2019-10-17 17:22:11 +03:00
parent aef618761e
commit 2e2a766edf
3 changed files with 108 additions and 55 deletions

View File

@@ -2449,7 +2449,6 @@ public class NodesImpl implements Nodes
@Override @Override
public Node moveOrCopyNode(String sourceNodeId, String targetParentId, String name, Parameters parameters, boolean isCopy) public Node moveOrCopyNode(String sourceNodeId, String targetParentId, String name, Parameters parameters, boolean isCopy)
{ {
FileInfo fi = retryingTransactionHelper.doInTransaction(() -> {
if ((sourceNodeId == null) || (sourceNodeId.isEmpty())) if ((sourceNodeId == null) || (sourceNodeId.isEmpty()))
{ {
throw new InvalidArgumentException("Missing sourceNodeId"); throw new InvalidArgumentException("Missing sourceNodeId");
@@ -2463,12 +2462,8 @@ public class NodesImpl implements Nodes
final NodeRef parentNodeRef = validateOrLookupNode(targetParentId, null); final NodeRef parentNodeRef = validateOrLookupNode(targetParentId, null);
final NodeRef sourceNodeRef = validateOrLookupNode(sourceNodeId, null); final NodeRef sourceNodeRef = validateOrLookupNode(sourceNodeId, null);
return moveOrCopyImpl(sourceNodeRef, parentNodeRef, name, isCopy); FileInfo fi = moveOrCopyImpl(sourceNodeRef, parentNodeRef, name, isCopy);
}, false, true);
return retryingTransactionHelper.doInTransaction(() -> {
return getFolderOrDocument(fi.getNodeRef().getId(), parameters); return getFolderOrDocument(fi.getNodeRef().getId(), parameters);
}, false, false);
} }
public void updateCustomAspects(NodeRef nodeRef, List<String> aspectNames, List<QName> excludedAspects) public void updateCustomAspects(NodeRef nodeRef, List<String> aspectNames, List<QName> excludedAspects)
@@ -3271,7 +3266,6 @@ public class NodesImpl implements Nodes
@Override @Override
public Node lock(String nodeId, LockInfo lockInfo, Parameters parameters) 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))) if (isSpecialNode(nodeRef, getNodeType(nodeRef)))
@@ -3287,12 +3281,7 @@ public class NodesImpl implements Nodes
LockInfo validatedLockInfo = validateLockInformation(lockInfo); LockInfo validatedLockInfo = validateLockInformation(lockInfo);
lockService.lock(nodeRef, validatedLockInfo.getMappedType(), validatedLockInfo.getTimeToExpire(), validatedLockInfo.getLifetime()); lockService.lock(nodeRef, validatedLockInfo.getMappedType(), validatedLockInfo.getTimeToExpire(), validatedLockInfo.getLifetime());
return null;
}, false, true);
return retryingTransactionHelper.doInTransaction(() -> {
return getFolderOrDocument(nodeId, parameters); return getFolderOrDocument(nodeId, parameters);
}, false, false);
} }
private LockInfo validateLockInformation(LockInfo lockInfo) private LockInfo validateLockInformation(LockInfo lockInfo)
@@ -3316,7 +3305,6 @@ public class NodesImpl implements Nodes
@Override @Override
public Node unlock(String nodeId, Parameters parameters) public Node unlock(String nodeId, Parameters parameters)
{ {
retryingTransactionHelper.doInTransaction(() -> {
NodeRef nodeRef = validateOrLookupNode(nodeId, null); NodeRef nodeRef = validateOrLookupNode(nodeId, null);
if (isSpecialNode(nodeRef, getNodeType(nodeRef))) if (isSpecialNode(nodeRef, getNodeType(nodeRef)))
@@ -3329,12 +3317,7 @@ public class NodesImpl implements Nodes
} }
lockService.unlock(nodeRef); lockService.unlock(nodeRef);
return null;
}, false, true);
return retryingTransactionHelper.doInTransaction(() -> {
return getFolderOrDocument(nodeId, parameters); return getFolderOrDocument(nodeId, parameters);
}, false, false);
} }
/** /**

View File

@@ -163,7 +163,7 @@ public class Node implements Comparable<Node>
PersonService.PersonInfo pInfo = null; PersonService.PersonInfo pInfo = null;
try try
{ {
NodeRef pNodeRef = personService.getPerson(userName, false); NodeRef pNodeRef = personService.getPersonOrNull(userName);
if (pNodeRef != null) if (pNodeRef != null)
{ {
pInfo = personService.getPerson(pNodeRef); pInfo = personService.getPerson(pNodeRef);

View File

@@ -4431,6 +4431,76 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest
assertEquals(f1Id, documentResp.getParentId()); 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 * Creates authority context
* *