diff --git a/e2e-test/java/org/alfresco/rest/nodes/NodesContentAndVersioningTests.java b/e2e-test/java/org/alfresco/rest/nodes/NodesContentAndVersioningTests.java index 61cda4ec6..f9eb55734 100644 --- a/e2e-test/java/org/alfresco/rest/nodes/NodesContentAndVersioningTests.java +++ b/e2e-test/java/org/alfresco/rest/nodes/NodesContentAndVersioningTests.java @@ -33,6 +33,7 @@ import org.json.JSONObject; import org.springframework.http.HttpStatus; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; + /** * * @author mpopa @@ -46,7 +47,7 @@ public class NodesContentAndVersioningTests extends RestTest @BeforeClass(alwaysRun = true) public void dataPreparation() throws Exception - { + { user1 = dataUser.createRandomTestUser(); user2 = dataUser.createRandomTestUser(); site1 = dataSite.usingUser(user1).createPublicRandomSite(); @@ -54,21 +55,23 @@ public class NodesContentAndVersioningTests extends RestTest file1 = dataContent.usingUser(user1).usingSite(site1).createContent(DocumentType.TEXT_PLAIN); file2 = dataContent.usingUser(user2).usingSite(site2).createContent(DocumentType.TEXT_PLAIN); } - - @TestRail(section = { TestGroup.REST_API,TestGroup.NODES }, executionType = ExecutionType.SANITY, - description = "Verify file name in Content-Disposition header") - @Test(groups = { TestGroup.REST_API, TestGroup.NODES, TestGroup.SANITY}) + + @TestRail(section = { TestGroup.REST_API, TestGroup.NODES }, executionType = ExecutionType.SANITY, description = "Verify file name in Content-Disposition header") + @Test(groups = { TestGroup.REST_API, TestGroup.NODES, TestGroup.SANITY }) public void checkFileNameWithRegularCharsInHeader() throws Exception { restClient.authenticateUser(user1).withCoreAPI().usingNode(file1).usingParams("attachment=false").getNodeContent(); restClient.assertStatusCodeIs(HttpStatus.OK); restClient.assertHeaderValueContains("Content-Disposition", String.format("filename=\"%s\"", file1.getName())); } - - @Bug(id="MNT-17545", description = "HTTP Header Injection in ContentStreamer", status = Bug.Status.FIXED) - @TestRail(section = { TestGroup.REST_API,TestGroup.NODES }, executionType = ExecutionType.REGRESSION, - description = "Verify file name with special chars is escaped in Content-Disposition header") - @Test(groups = { TestGroup.REST_API, TestGroup.NODES, TestGroup.REGRESSION}) + + + + + @Bug(id = "MNT-17545", description = "HTTP Header Injection in ContentStreamer", status = Bug.Status.FIXED) + @TestRail(section = { TestGroup.REST_API, + TestGroup.NODES }, executionType = ExecutionType.REGRESSION, description = "Verify file name with special chars is escaped in Content-Disposition header") + @Test(groups = { TestGroup.REST_API, TestGroup.NODES, TestGroup.REGRESSION }) public void checkFileNameWithSpecialCharsInHeader() throws Exception { char c1 = 127; @@ -77,7 +80,7 @@ public class NodesContentAndVersioningTests extends RestTest FileModel file = dataContent.usingUser(user2).usingSite(site2).createContent(new FileModel("\ntest" + c1 + c2 + c3, FileType.TEXT_PLAIN)); restClient.authenticateUser(user2).withCoreAPI().usingNode(file).usingParams("attachment=false").getNodeContent(); restClient.assertStatusCodeIs(HttpStatus.OK); - restClient.assertHeaderValueContains("Content-Disposition","filename=\" test .txt\""); + restClient.assertHeaderValueContains("Content-Disposition", "filename=\" test .txt\""); } @Test(groups = { TestGroup.REST_API, TestGroup.NODES, TestGroup.SANITY }) @@ -86,8 +89,8 @@ public class NodesContentAndVersioningTests extends RestTest public void verifyFileEncodingUsingRestAPI() throws Exception { STEP("1. Create a folder, two text file templates and define the expected encoding."); - FileModel utf8File = new FileModel("utf8File",FileType.TEXT_PLAIN); - FileModel iso8859File = new FileModel("iso8859File",FileType.TEXT_PLAIN); + FileModel utf8File = new FileModel("utf8File", FileType.TEXT_PLAIN); + FileModel iso8859File = new FileModel("iso8859File", FileType.TEXT_PLAIN); FolderModel folder = dataContent.usingUser(user1).usingSite(site1).createFolder(FolderModel.getRandomFolderModel()); String utf8Type = "text/plain;charset=UTF-8"; String iso8859Type = "text/plain;charset=ISO-8859-1"; @@ -110,8 +113,7 @@ public class NodesContentAndVersioningTests extends RestTest } @Test(groups = { TestGroup.REST_API, TestGroup.NODES, TestGroup.SANITY }) - @TestRail(section = { TestGroup.REST_API, - TestGroup.NODES }, executionType = ExecutionType.SANITY, description = "Verify updating a node content.") + @TestRail(section = { TestGroup.REST_API, TestGroup.NODES }, executionType = ExecutionType.SANITY, description = "Verify updating a node content.") public void testUpdateNodeContent() throws Exception { STEP("1. Retrieve the node in order to get data to compare after update GET /nodes/{nodeId}?include=path."); @@ -129,13 +131,12 @@ public class NodesContentAndVersioningTests extends RestTest assertNotSame(initialNode.getName(), updatedBodyNode.getName()); String initialNodeVersion = new JSONObject(initialNode.toJson()).getJSONObject("properties").getString("cm:versionLabel"); - String updatedBodyNodeVersion = new JSONObject(updatedBodyNode.toJson()).getJSONObject("properties").getString("cm:versionLabel"); + String updatedBodyNodeVersion = new JSONObject(updatedBodyNode.toJson()).getJSONObject("properties").getString("cm:versionLabel"); assertTrue(updatedBodyNodeVersion.charAt(0) > initialNodeVersion.charAt(0)); } @Test(groups = { TestGroup.REST_API, TestGroup.NODES, TestGroup.SANITY }) - @TestRail(section = { TestGroup.REST_API, - TestGroup.NODES }, executionType = ExecutionType.SANITY, description = "Test copy a node.") + @TestRail(section = { TestGroup.REST_API, TestGroup.NODES }, executionType = ExecutionType.SANITY, description = "Test copy a node.") public void testCopyNode() throws Exception { STEP("1. Create a lock and lock the node POST /nodes/{nodeId}/lock?include=path,isLocked."); @@ -148,8 +149,7 @@ public class NodesContentAndVersioningTests extends RestTest STEP("2. With another user(that has access to the file), copy the node to another path POST /nodes/{nodeId}/copy?include=path,isLocked."); String postBody = JsonBodyGenerator.keyValueJson("targetParentId", site2.getGuid()); - RestNodeModel copiedNode = restClient.authenticateUser(user2).withCoreAPI().usingNode(file1).usingParams("include=path,isLocked") - .copyNode(postBody); + RestNodeModel copiedNode = restClient.authenticateUser(user2).withCoreAPI().usingNode(file1).usingParams("include=path,isLocked").copyNode(postBody); restClient.assertStatusCodeIs(HttpStatus.CREATED); STEP("3. ParentId, createdAt, path and lock are different, but the nodes have the same contentSize."); @@ -175,25 +175,25 @@ public class NodesContentAndVersioningTests extends RestTest File sampleFile = Utility.getResourceTestDataFile("sampleContent.txt"); STEP("1. Update the node content in order to increase version(one minor and one major) PUT /nodes/{nodeId}/content."); - //minor version update + // minor version update restClient.authenticateUser(user2).withCoreAPI().usingNode(file2).updateNodeContent(sampleFile); restClient.assertStatusCodeIs(HttpStatus.OK); - //major version update + // major version update restClient.authenticateUser(user2).withCoreAPI().usingParams("majorVersion=true").usingNode(file2).updateNodeContent(sampleFile); restClient.assertStatusCodeIs(HttpStatus.OK); STEP("2. List node version history GET /nodes/{nodeId}/versions. And verify that first (in the list) version is 2.0 and last is 1.0."); RestVersionModelsCollection versionListing = restClient.withCoreAPI().usingNode(file2).listVersionHistory(); restClient.assertStatusCodeIs(HttpStatus.OK); - //additional check that the properties are not displayed by default. - assertEquals(versionListing.getEntries().get(versionListing.getPagination().getCount()-1).onModel().getId(),"1.0"); - assertEquals(versionListing.getEntries().get(0).onModel().getId(),"2.0"); + // additional check that the properties are not displayed by default. + assertEquals(versionListing.getEntries().get(versionListing.getPagination().getCount() - 1).onModel().getId(), "1.0"); + assertEquals(versionListing.getEntries().get(0).onModel().getId(), "2.0"); assertNull(versionListing.getEntries().get(0).onModel().getProperties()); STEP("3. List node version using skipCount(1),maxItems(1) and include(properties) GET /nodes/{nodeId}/versions?include=properties&skipCount=1&maxItems=1"); versionListing = restClient.withCoreAPI().usingParams("include=properties&skipCount=1&maxItems=1").usingNode(file2).listVersionHistory(); restClient.assertStatusCodeIs(HttpStatus.OK); - //we expect only version 1.1 to be retrieved with the value for properties. + // we expect only version 1.1 to be retrieved with the value for properties. RestVersionModel version = versionListing.getEntries().get(0).onModel(); assertNotNull(version.getProperties()); assertEquals(version.getId(), "1.1"); @@ -204,18 +204,20 @@ public class NodesContentAndVersioningTests extends RestTest STEP("4. Get version information for version 1.1 GET /nodes/{nodeId}/versions/{versionId} ."); RestVersionModel version11 = restClient.withCoreAPI().usingNode(file2).getVersionInformation("1.1"); restClient.assertStatusCodeIs(HttpStatus.OK); - //aspectNames and properties are displayed by default. We compare id,contentSize and name with the values from v1.1, taken from listing all versions. + // aspectNames and properties are displayed by default. We compare + // id,contentSize and name with the values from v1.1, taken from listing all + // versions. assertNotNull(version11.getAspectNames()); assertNotNull(version11.getProperties()); - assertEquals(version.getId(),version11.getId()); - assertEquals(version.getContent().getSizeInBytes(),version11.getContent().getSizeInBytes()); - assertEquals(version.getName(),version11.getName()); + assertEquals(version.getId(), version11.getId()); + assertEquals(version.getContent().getSizeInBytes(), version11.getContent().getSizeInBytes()); + assertEquals(version.getName(), version11.getName()); STEP("5. Retrieve version 2.0 content GET /nodes/{nodeId}/versions/{versionId}/content"); - //verify the content is the same as the uploaded file and check in headers for Content-Disposition to validate the download as attachment and fileName. - //wait for content to be picked up on AWS QS stacks - Utility.sleep(1000, 60000, () -> - { + // verify the content is the same as the uploaded file and check in headers for + // Content-Disposition to validate the download as attachment and fileName. + // wait for content to be picked up on AWS QS stacks + Utility.sleep(1000, 60000, () -> { RestResponse versionContent = restClient.withCoreAPI().usingNode(file2).getVersionContent("2.0"); restClient.assertStatusCodeIs(HttpStatus.OK); @@ -223,27 +225,25 @@ public class NodesContentAndVersioningTests extends RestTest restClient.assertHeaderValueContains("Content-Disposition", "attachment"); restClient.assertHeaderValueContains("Content-Disposition", String.format("filename=\"%s\"", file2.getName())); }); - } @Test(groups = { TestGroup.REST_API, TestGroup.NODES, TestGroup.SANITY }) - @TestRail(section = { TestGroup.REST_API, - TestGroup.NODES }, executionType = ExecutionType.SANITY, description = "Test revert and delete a node version.") + @TestRail(section = { TestGroup.REST_API, TestGroup.NODES }, executionType = ExecutionType.SANITY, description = "Test revert and delete a node version.") public void testRevertDeleteVersion() throws Exception { STEP("1. Revert to version 1.0 POST /nodes/{nodeId}/versions/{versionId}/revert"); RestVersionModel version = restClient.authenticateUser(user2).withCoreAPI().usingNode(file2).revertVersion("1.0", new String("{}")); restClient.assertStatusCodeIs(HttpStatus.OK); String nodeVersionType = new JSONObject(version.toJson()).getJSONObject("properties").getString("cm:versionType"); - assertEquals(nodeVersionType , "MINOR"); + assertEquals(nodeVersionType, "MINOR"); String nodeVersion = version.getId(); STEP("2. Revert to last minor version /nodes/{nodeId}/versions/{versionId}/revert"); version = restClient.withCoreAPI().usingNode(file2).revertVersion(nodeVersion, new String("{\"majorVersion\": true}")); restClient.assertStatusCodeIs(HttpStatus.OK); nodeVersionType = new JSONObject(version.toJson()).getJSONObject("properties").getString("cm:versionType"); - assertEquals(nodeVersionType , "MAJOR"); - assertTrue(nodeVersion.charAt(0)+1 == version.getId().charAt(0)); + assertEquals(nodeVersionType, "MAJOR"); + assertTrue(nodeVersion.charAt(0) + 1 == version.getId().charAt(0)); STEP("3. Delete last MINOR version DELETE /nodes/{nodeId}/versions/{versionId}"); restClient.withCoreAPI().usingNode(file2).deleteNodeVersion(nodeVersion); @@ -251,4 +251,15 @@ public class NodesContentAndVersioningTests extends RestTest restClient.withCoreAPI().usingNode(file2).getVersionInformation(nodeVersion); restClient.assertStatusCodeIs(HttpStatus.NOT_FOUND); } + + @TestRail(section = { TestGroup.REST_API, TestGroup.NODES }, executionType = ExecutionType.SANITY, description = "Verify file name in Content Range header") + @Test(groups = { TestGroup.REST_API, TestGroup.NODES, TestGroup.SANITY }) + public void checkFileNameContentRangeHeader() throws Exception + { + restClient.configureRequestSpec().addHeader("content-range", "bytes=1-10"); + restClient.authenticateUser(user1).withCoreAPI().usingNode(file1).getNodeContent(); + restClient.assertStatusCodeIs(HttpStatus.PARTIAL_CONTENT); + restClient.assertHeaderValueContains("content-range", "bytes 1-10"); + restClient.assertHeaderValueContains("content-length", String.valueOf(10)); + } } diff --git a/e2e-test/java/org/alfresco/rest/renditions/GetRenditionTests.java b/e2e-test/java/org/alfresco/rest/renditions/GetRenditionTests.java index 4d9b7c2ba..5fcad7e79 100644 --- a/e2e-test/java/org/alfresco/rest/renditions/GetRenditionTests.java +++ b/e2e-test/java/org/alfresco/rest/renditions/GetRenditionTests.java @@ -2,6 +2,8 @@ package org.alfresco.rest.renditions; import static org.alfresco.utility.report.log.Step.STEP; +import org.alfresco.dataprep.CMISUtil; +import org.alfresco.dataprep.CMISUtil.DocumentType; import org.alfresco.rest.RestTest; import org.alfresco.rest.core.RestResponse; import org.alfresco.rest.model.RestNodeModel; @@ -31,12 +33,14 @@ public class GetRenditionTests extends RestTest { private UserModel user; private SiteModel site; + private FileModel file1; @BeforeClass(alwaysRun = true) public void dataPreparation() throws Exception { user = dataUser.createRandomTestUser(); site = dataSite.usingUser(user).createPublicRandomSite(); + file1 = dataContent.usingUser(user).usingSite(site).createContent(DocumentType.TEXT_PLAIN); } @Bug(id = "REPO-2449", status = Status.FIXED) @@ -132,5 +136,23 @@ public class GetRenditionTests extends RestTest Assert.assertTrue(restResponse.getResponse().body().asInputStream().available() > 0); } + @Test(groups = {TestGroup.REST_API, TestGroup.RENDITIONS, TestGroup.SANITY}) + @TestRail(section = {TestGroup.REST_API, TestGroup.RENDITIONS}, executionType = ExecutionType.SANITY, + description = "Verify the Range request header using GET /nodes/{nodeId}/renditions/{renditionId}/content") + public void getVerifyRangeRequestHeader() throws Exception + { + STEP("1. Create thumbnail on file"); + restClient.authenticateUser(user).withCoreAPI().usingNode(file1).createNodeRendition("pdf"); + restClient.assertStatusCodeIs(HttpStatus.ACCEPTED); + + STEP("2. Make GET rendition content using content-range header"); + Utility.sleep(1000, 30000, () -> { + restClient.configureRequestSpec().addHeader("content-range", "bytes=1-10"); + restClient.authenticateUser(user).withCoreAPI().usingNode(file1).getNodeRenditionContent("pdf"); + restClient.assertStatusCodeIs(HttpStatus.PARTIAL_CONTENT); + restClient.assertHeaderValueContains("content-range", "bytes 1-10"); + restClient.assertHeaderValueContains("content-length", String.valueOf(10)); + }); + } } diff --git a/e2e-test/java/org/alfresco/rest/sharedLinks/SharedLinksSanityTests.java b/e2e-test/java/org/alfresco/rest/sharedLinks/SharedLinksSanityTests.java index cb707a713..d41f2d646 100644 --- a/e2e-test/java/org/alfresco/rest/sharedLinks/SharedLinksSanityTests.java +++ b/e2e-test/java/org/alfresco/rest/sharedLinks/SharedLinksSanityTests.java @@ -44,6 +44,7 @@ public class SharedLinksSanityTests extends RestTest private FileModel file5; private FileModel file6; private FileModel file7; + private FileModel file8; private RestSharedLinksModel sharedLink1; private RestSharedLinksModel sharedLink2; @@ -52,7 +53,7 @@ public class SharedLinksSanityTests extends RestTest private RestSharedLinksModel sharedLink5; private RestSharedLinksModel sharedLink6; private RestSharedLinksModel sharedLink7; - + private RestSharedLinksModel sharedLink8; private RestRenditionInfoModel nodeRenditionInfo; private RestSharedLinksModelCollection sharedLinksCollection; @@ -81,7 +82,7 @@ public class SharedLinksSanityTests extends RestTest file4 = dataContent.usingUser(adminUser).usingResource(folder1).createContent(DocumentType.TEXT_PLAIN); file5 = dataContent.usingUser(adminUser).usingResource(folder1).createContent(DocumentType.TEXT_PLAIN); file7 = dataContent.usingUser(adminUser).usingResource(folder1).createContent(DocumentType.TEXT_PLAIN); - + file8 = dataContent.usingUser(adminUser).usingResource(folder1).createContent(DocumentType.TEXT_PLAIN); // Create file6 based on existing resource FileModel newFile = FileModel.getFileModelBasedOnTestDataFile("sampleContent.txt"); newFile.setName("sampleContent.txt"); @@ -254,4 +255,24 @@ public class SharedLinksSanityTests extends RestTest restClient.assertHeaderValueContains("Content-Type","application/pdf;charset=UTF-8"); Assert.assertTrue(restClient.onResponse().getResponse().body().asInputStream().available() > 0); } + + @TestRail(section = { TestGroup.REST_API, TestGroup.SHAREDLINKS }, executionType = ExecutionType.SANITY, description = "Sanity tests for Range reuest header on GET shared-links/{sharedId}/renditions/{renditionId}/content endpoints") + @Test(groups = { TestGroup.REST_API, TestGroup.SHAREDLINKS, TestGroup.SANITY, TestGroup.REQUIRE_TRANSFORMATION }) + public void testGetVerifyRangeReguestOnSharedLinks() throws Exception + { + sharedLink8 = restClient.authenticateUser(testUser1).withCoreAPI().usingSharedLinks().createSharedLink(file8); + restClient.assertStatusCodeIs(HttpStatus.CREATED); + restClient.withCoreAPI().usingNode(file8).createNodeRendition("pdf"); + restClient.assertStatusCodeIs(HttpStatus.ACCEPTED); + + // GET /renditions/{renditionId}/content: get the Range request header for file with shared links endpoints. + Utility.sleep(1000, 30000, () -> + { + restClient.configureRequestSpec().addHeader("content-range", "bytes=1-10"); + restClient.authenticateUser(testUser1).withCoreAPI().usingSharedLinks().getSharedLinkRenditionContent(sharedLink8, "pdf"); + restClient.assertStatusCodeIs(HttpStatus.PARTIAL_CONTENT); + restClient.assertHeaderValueContains("Content-Type","application/pdf;charset=UTF-8"); + restClient.assertHeaderValueContains("content-range", "bytes 1-10"); + }); + } } \ No newline at end of file diff --git a/e2e-test/java/org/alfresco/rest/trashcan/GetDeletedNodesTests.java b/e2e-test/java/org/alfresco/rest/trashcan/GetDeletedNodesTests.java index 5cf7a6759..553b044d1 100644 --- a/e2e-test/java/org/alfresco/rest/trashcan/GetDeletedNodesTests.java +++ b/e2e-test/java/org/alfresco/rest/trashcan/GetDeletedNodesTests.java @@ -49,8 +49,8 @@ public class GetDeletedNodesTests extends RestTest { private UserModel adminUserModel; private SiteModel deleteNodesSiteModel; - private FolderModel deleteNodesFolder1, deleteNodesFolder2, deleteNodesFolder3, deleteNodesFolder4, deleteNodesFolder5; - private FileModel file, file1, file2, file3; + private FolderModel deleteNodesFolder1, deleteNodesFolder2, deleteNodesFolder3, deleteNodesFolder4, deleteNodesFolder5, getDeleteNodesFolder6; + private FileModel file, file1, file2, file3, file4; private RestNodeModelsCollection deletedNodes, deletedNodesMaxItem; private RestNodeModel node; @@ -217,4 +217,29 @@ public class GetDeletedNodesTests extends RestTest restClient.assertHeaderValueContains("Content-Type","application/pdf;charset=UTF-8"); Assert.assertTrue(restClient.onResponse().getResponse().body().asInputStream().available() > 0); } + + @TestRail(section = {TestGroup.REST_API, TestGroup.TRASHCAN, TestGroup.REQUIRE_SOLR}, executionType = ExecutionType.SANITY, + description = "Sanity test to verify Range request header on GET /deleted-nodes/{nodeId}/renditions/{renditionId}/content endpoint") + @Test(groups = {TestGroup.REST_API, TestGroup.TRASHCAN, TestGroup.SANITY}) + public void testGetDeletedNodesRenditionsandVerifyRangeRequestheader() throws Exception + { + // Create file4 based on existing resource + file4 = dataContent.usingUser(adminUserModel).usingSite(deleteNodesSiteModel).createContent(DocumentType.TEXT_PLAIN); + + // Create rendition and delete file4 to be moved in trashcan + restClient.withCoreAPI().usingNode(file4).createNodeRendition("pdf"); + restClient.assertStatusCodeIs(HttpStatus.ACCEPTED); + dataContent.usingUser(adminUserModel).usingResource(file4).deleteContent(); + + // GET /deleted-nodes/{nodeId}/renditions/{id}/content and verify range request header + Utility.sleep(1000, 30000, () -> + { + restClient.configureRequestSpec().addHeader("content-range", "bytes=1-10"); + restClient.authenticateUser(adminUserModel).withCoreAPI().usingTrashcan().getDeletedNodeRenditionContent(file4, "pdf"); + restClient.assertStatusCodeIs(HttpStatus.PARTIAL_CONTENT); + restClient.assertHeaderValueContains("Content-Type", "application/pdf;charset=UTF-8"); + restClient.assertHeaderValueContains("content-range", "bytes 1-10"); + restClient.assertHeaderValueContains("content-length", String.valueOf(10)); + }); + } }