diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/CustomDefinitionsAPI.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/CustomDefinitionsAPI.java index 0d99973877..21672f0bf0 100644 --- a/amps/ags/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/CustomDefinitionsAPI.java +++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/CustomDefinitionsAPI.java @@ -26,8 +26,6 @@ */ package org.alfresco.rest.v0; -import static org.testng.AssertJUnit.assertTrue; - import java.text.MessageFormat; import org.alfresco.rest.core.v0.BaseAPI; @@ -38,7 +36,9 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; - +import static org.testng.AssertJUnit.assertTrue; +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertNotNull; /** * Methods to make API requests using v0 API on Records Management Custom Model Reference Definitions * @@ -57,6 +57,8 @@ public class CustomDefinitionsAPI extends BaseAPI * create reference endpoint */ private static final String CREATE_RELATIONSHIP_API_ENDPOINT = "{0}node/{1}/customreferences"; + private static final String GET_RELATIONSHIP_API_ENDPOINT = "{0}node/{1}/relationships"; + private static final String DELETE_RELATIONSHIP_API_ENDPOINT = "{0}node/{1}/targetnode/{2}/uniqueName/{3}"; /** * logger @@ -141,4 +143,48 @@ public class CustomDefinitionsAPI extends BaseAPI assertTrue("Creating relationship from " + recordNodeIdFrom + " to " + recordNodeIdTo + " failed.", success); } + public void createRelationship( + String adminUser, + String adminPassword, + int expectedStatus, + String recordNodeIdFrom, + String recordNodeIdTo, + CustomDefinitions relationshipType) { + //create the request body + JSONObject requestParams = new JSONObject(); + requestParams.put("toNode", NODE_REF_WORKSPACE_SPACES_STORE + recordNodeIdTo); + requestParams.put("refId", getCustomReferenceId(adminUser, adminPassword, relationshipType + .getDefinition())); + //send the API request to create the relationship + JSONObject setRelationshipStatus = doPostRequest(adminUser, adminPassword, requestParams, + MessageFormat.format(CREATE_RELATIONSHIP_API_ENDPOINT, "{0}", NODE_PREFIX + recordNodeIdFrom)); + //check the response + assertEquals("POST request for createRelationship was not successful.", expectedStatus, setRelationshipStatus.getJSONObject("status").get("code")); + } + + public JSONObject getRelationshipDetails( + String adminUser, + String adminPassword, + String nodeRef) { + //send the API request to create the relationship + JSONObject relationshipDetails = doGetRequest(adminUser, adminPassword, + MessageFormat.format(GET_RELATIONSHIP_API_ENDPOINT, "{0}", NODE_PREFIX + nodeRef)); + //check the response + assertNotNull("The Relationship detail is not found for the Noderef " + nodeRef, relationshipDetails); + return relationshipDetails; + } + + public void deleteRelationship( + String adminUser, + String adminPassword, + String recordNodeIdFrom, + String recordNodeIdTo, + String relationshipUniqueName) { + //send the API request to create the relationship + JSONObject setRelationshipStatus = doDeleteRequest(adminUser, adminPassword, + MessageFormat.format(DELETE_RELATIONSHIP_API_ENDPOINT, "{0}", NODE_PREFIX + recordNodeIdFrom,NODE_PREFIX + recordNodeIdTo,relationshipUniqueName)); + //check the response + boolean success = (setRelationshipStatus != null) && setRelationshipStatus.getBoolean("success"); + assertTrue("Deleting relationship from " + recordNodeIdFrom + " to " + recordNodeIdTo + " failed.", success); + } } diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/AddRelationshipTests.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/AddRelationshipTests.java new file mode 100644 index 0000000000..5ec667b95f --- /dev/null +++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/AddRelationshipTests.java @@ -0,0 +1,202 @@ +/* + * #%L + * Alfresco Records Management Module + * %% + * Copyright (C) 2005 - 2022 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * - + * If the software was purchased under a paid Alfresco license, the terms of + * 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% + */ + +package org.alfresco.rest.rm.community.records; +import static org.alfresco.rest.core.v0.BaseAPI.RM_SITE_ID; +import static org.alfresco.rest.rm.community.base.TestData.HOLD_DESCRIPTION; +import static org.alfresco.rest.rm.community.base.TestData.HOLD_REASON; +import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix; +import java.util.Collections; +import org.alfresco.rest.rm.community.base.BaseRMRestTest; +import org.alfresco.rest.rm.community.model.custom.CustomDefinitions; +import org.alfresco.rest.rm.community.model.record.Record; +import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory; +import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild; +import org.alfresco.rest.v0.CustomDefinitionsAPI; +import org.alfresco.rest.v0.HoldsAPI; +import org.alfresco.rest.v0.RMRolesAndActionsAPI; +import org.alfresco.rest.v0.RecordsAPI; +import org.alfresco.rest.v0.RecordCategoriesAPI; +import org.alfresco.test.AlfrescoTest; +import org.apache.commons.lang.StringUtils; +import org.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.testng.annotations.Test; +import static org.apache.commons.httpclient.HttpStatus.SC_INTERNAL_SERVER_ERROR; +import static org.apache.commons.httpclient.HttpStatus.SC_OK; +/** + * Add Relationship tests + * @author Kavit Shah + */ +public class AddRelationshipTests extends BaseRMRestTest +{ + private final String TEST_PREFIX = generateTestPrefix(AddRelationshipTests.class); + private final String CATEGORY = TEST_PREFIX + "category"; + private final String HOLD1 = TEST_PREFIX + "hold1"; + private final String FOLDER = TEST_PREFIX + "RM_2709_1814_FOLDER"; + private final String RECORD1 = TEST_PREFIX + "RM_2709_1814_RECORD_ONE"; + private final String RECORD2 = TEST_PREFIX + "RM_1814_RECORD_TWO"; + private String hold1NodeRef; + @Autowired + private HoldsAPI holdsAPI; + @Autowired + private RecordsAPI recordsAPI; + @Autowired + private CustomDefinitionsAPI customDefinitionsAPI; + @Autowired + private RMRolesAndActionsAPI rmRolesAndActionsAPI; + @Autowired + private RecordCategoriesAPI recordCategoriesAPI; + + @Test (priority = 1) + @AlfrescoTest (jira = "RM-1814") + public void addRelationshipToHoldRecord() + { + String CATEGORY_RELATIONSHIP = CATEGORY + "To Hold"; + //create RM site + createRMSiteIfNotExists(); + //create record category, record folder and records + RecordCategory recordCategory = createCategoryIfDoesNotExist(CATEGORY_RELATIONSHIP); + RecordCategoryChild recordCategoryChild = createRecordFolderInCategory(FOLDER, recordCategory); + + createRecordItems(recordCategoryChild, RECORD1); + Record record2 = createRecordItems(recordCategoryChild, RECORD2); + + //create Hold + hold1NodeRef = holdsAPI.createHoldAndGetNodeRef(getAdminUser().getUsername(), + getAdminUser().getPassword(), HOLD1, HOLD_REASON, HOLD_DESCRIPTION); + //add RECORD2 to holds + holdsAPI.addItemsToHolds(getDataUser().usingAdmin().getAdminUser().getUsername(), + getDataUser().usingAdmin().getAdminUser().getPassword(), + SC_OK, Collections.singletonList(record2.getId()), + Collections.singletonList(hold1NodeRef)); + + // get records nodeRefs + String elRecordFullName1 = recordsAPI.getRecordFullName(getDataUser().usingAdmin().getAdminUser().getUsername(), + getDataUser().usingAdmin().getAdminUser().getPassword(), FOLDER, RECORD1); + String elRecordNodeRef1 = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(), + getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordFullName1, "/" + CATEGORY_RELATIONSHIP + "/" + FOLDER); + + String elRecordFullName2 = recordsAPI.getRecordFullName(getDataUser().usingAdmin().getAdminUser().getUsername(), + getDataUser().usingAdmin().getAdminUser().getPassword(), FOLDER, RECORD2); + String elRecordNodeRef2 = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(), + getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordFullName2, "/" + CATEGORY_RELATIONSHIP + "/" + FOLDER); + + // create Relationship + customDefinitionsAPI.createRelationship(getDataUser().usingAdmin().getAdminUser().getUsername(), + getDataUser().usingAdmin().getAdminUser().getPassword(), + SC_INTERNAL_SERVER_ERROR, + formatNodeRef(elRecordNodeRef1), + formatNodeRef(elRecordNodeRef2), + CustomDefinitions.ATTACHMENT); + + //delete preconditions + deletePrecondition(); + } + + @Test (priority = 2) + @AlfrescoTest (jira = "RM-1874") + public void deleteRelationship() + { + String CATEGORY_RELATIONSHIP = CATEGORY + "deleteRelationship"; + // create RM site + createRMSiteIfNotExists(); + // create record category, record folder and records + RecordCategory recordCategory = createCategoryIfDoesNotExist(CATEGORY_RELATIONSHIP); + RecordCategoryChild recordCategoryChild = createRecordFolderInCategory(FOLDER, recordCategory); + + createRecordItems(recordCategoryChild, RECORD1); + createRecordItems(recordCategoryChild, RECORD2); + + // Add Relationship + String elRecordFullName1 = recordsAPI.getRecordFullName(getDataUser().usingAdmin().getAdminUser().getUsername(), + getDataUser().usingAdmin().getAdminUser().getPassword(), FOLDER, RECORD1); + String elRecordNodeRef1 = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(), + getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordFullName1, "/" + CATEGORY_RELATIONSHIP + "/" + FOLDER); + + String elRecordFullName2 = recordsAPI.getRecordFullName(getDataUser().usingAdmin().getAdminUser().getUsername(), + getDataUser().usingAdmin().getAdminUser().getPassword(), FOLDER, RECORD2); + String elRecordNodeRef2 = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(), + getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordFullName2, "/" + CATEGORY_RELATIONSHIP + "/" + FOLDER); + + customDefinitionsAPI.createRelationship(getDataUser().usingAdmin().getAdminUser().getUsername(), + getDataUser().usingAdmin().getAdminUser().getPassword(), + formatNodeRef(elRecordNodeRef1), + formatNodeRef(elRecordNodeRef2), + CustomDefinitions.ATTACHMENT); + + // Get RelationshipDetails + JSONObject relationshipDetails = customDefinitionsAPI.getRelationshipDetails(getDataUser().usingAdmin().getAdminUser().getUsername(), + getDataUser().usingAdmin().getAdminUser().getPassword(), + formatNodeRef(elRecordNodeRef1)); + + // Delete RelationshipDetails + customDefinitionsAPI.deleteRelationship(getDataUser().usingAdmin().getAdminUser().getUsername(), + getDataUser().usingAdmin().getAdminUser().getPassword(), + formatNodeRef(elRecordNodeRef1), + formatNodeRef(elRecordNodeRef2), + relationshipUniqueName(relationshipDetails)); + + // delete category + tearDown(CATEGORY_RELATIONSHIP); + } + + private void deletePrecondition() + { + holdsAPI.deleteHold(getAdminUser(), hold1NodeRef); + } + + private Record createRecordItems(RecordCategoryChild recordCategoryChild, String record) { + return createElectronicRecord(recordCategoryChild.getId(), record); + } + + private RecordCategory createCategoryIfDoesNotExist(String CATEGORY_ALL) { + return createRootCategory(getDataUser().usingAdmin().getAdminUser(), CATEGORY_ALL); + } + + private RecordCategoryChild createRecordFolderInCategory(String FOLDER_SEARCH, RecordCategory recordCategory) { + return createFolder(getDataUser().usingAdmin().getAdminUser(), recordCategory.getId(), FOLDER_SEARCH); + } + + private String formatNodeRef(String nodeRef) { + return StringUtils.remove(nodeRef,"workspace://SpacesStore/"); + } + + private void tearDown(String category) { + rmRolesAndActionsAPI.deleteAllItemsInContainer(getDataUser().usingAdmin().getAdminUser().getUsername(), + getDataUser().usingAdmin().getAdminUser().getPassword(), RM_SITE_ID, FOLDER); + rmRolesAndActionsAPI.deleteAllItemsInContainer(getDataUser().usingAdmin().getAdminUser().getUsername(), + getDataUser().usingAdmin().getAdminUser().getPassword(), RM_SITE_ID, category); + recordCategoriesAPI.deleteCategory(getDataUser().usingAdmin().getAdminUser().getUsername(), + getDataUser().usingAdmin().getAdminUser().getPassword(), category); + } + + private String relationshipUniqueName(JSONObject relationshipDetails) { + return relationshipDetails.getJSONObject("data").getJSONArray("items").getJSONObject(0).getJSONObject("node") + .get("relationshipUniqueName").toString(); + } +} diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/CreateElectronicRecordsTests.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/CreateElectronicRecordsTests.java new file mode 100644 index 0000000000..6e171b601a --- /dev/null +++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/CreateElectronicRecordsTests.java @@ -0,0 +1,148 @@ +/*- + * #%L + * Alfresco Records Management Module + * %% + * Copyright (C) 2005 - 2022 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * - + * If the software was purchased under a paid Alfresco license, the terms of + * 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% + */ +package org.alfresco.rest.rm.community.records; + +import static java.util.Arrays.asList; +import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix; +import static org.alfresco.rest.rm.community.utils.CoreUtil.createBodyForMoveCopy; +import static org.alfresco.rest.rm.community.utils.CoreUtil.toContentModel; +import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.createElectronicRecordModel; +import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.getFile; +import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.IMAGE_FILE; +import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.createRecordModel; +import static org.alfresco.utility.data.RandomData.getRandomName; +import static org.alfresco.utility.report.log.Step.STEP; +import static org.springframework.http.HttpStatus.CREATED; +import static org.springframework.http.HttpStatus.OK; +import org.alfresco.rest.model.RestNodeModel; +import org.alfresco.rest.rm.community.base.BaseRMRestTest; +import org.alfresco.rest.rm.community.model.record.Record; +import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory; +import org.alfresco.rest.rm.community.requests.gscore.api.RecordFolderAPI; +import org.alfresco.test.AlfrescoTest; +import org.alfresco.utility.model.UserModel; +import org.springframework.beans.factory.annotation.Autowired; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.alfresco.rest.v0.RMRolesAndActionsAPI; +/** + * This class contains the tests for + * CreateElectronicRecordsTests Action REST API + * + * @author Shishuraj Bisht + */ +public class CreateElectronicRecordsTests extends BaseRMRestTest { + + private RecordCategory rootCategory; + private UserModel updateUser; + /** + * data prep services + */ + + @Autowired + private RMRolesAndActionsAPI rmRolesAndActionsAPI; + + private final String TEST_PREFIX = generateTestPrefix(CreateElectronicRecordsTests.class); + private final String RM_ADMIN = TEST_PREFIX + "rm_admin"; + + @BeforeClass (alwaysRun = true) + public void preConditions() + { + STEP("Create RM Site"); + createRMSiteIfNotExists(); + + STEP("Create RM Admin user"); + rmRolesAndActionsAPI.createUserAndAssignToRole(getAdminUser().getUsername(), getAdminUser().getPassword(), RM_ADMIN, + getAdminUser().getPassword(), + "Administrator"); + + STEP("Create root level category"); + rootCategory = createRootCategory(getRandomName("Category")); + + STEP("Create the record folder1 inside the rootCategory"); + String recordFolder1 = createCategoryFolderInFilePlan().getId(); + } + + /** + * Test v0 methods to create and get electronic records. + */ + @Test + @AlfrescoTest (jira = "RM-2768") + public void createElectronicRecordTest() throws Exception { + + //create electronic record in record folder + String recordFolder1 = createRecordFolder(rootCategory.getId(), getRandomName("recFolder")).getId(); + RecordFolderAPI recordFolderAPI = getRestAPIFactory().getRecordFolderAPI(); + + Record electronicRecord = recordFolderAPI.createRecord(createElectronicRecordModel(), recordFolder1, getFile(IMAGE_FILE)); + assertStatusCode(CREATED); + STEP("Check the electronic record has been created"); + assertStatusCode(CREATED); + + // Get recordsAPI instance initialised to updateUser + org.alfresco.rest.rm.community.requests.gscore.api.RecordsAPI recordsAPI = getRestAPIFactory().getRecordsAPI(updateUser); + + for (Record record: asList(electronicRecord)) { + recordsAPI.getRecord(record.getId()); + assertStatusCode(OK); + + // Generate update metadata + String newName = getModifiedPropertyValue(record.getName()); + String newTitle = getModifiedPropertyValue(record.getProperties().getTitle()); + String newDescription = getModifiedPropertyValue(record.getProperties().getDescription()); + + // Update record + recordsAPI.updateRecord(createRecordModel(newName, newDescription, newTitle), record.getId()); + assertStatusCode(OK); + } + // move the record from one folder1 to folder2 + STEP("Create the record folder2 inside the rootCategory"); + String recordFolder2 = createCategoryFolderInFilePlan().getId(); + + STEP("Move record from folder1 to folder2"); + RestNodeModel electronicDocRestNodeModel = getRestAPIFactory() + .getNodeAPI(toContentModel(electronicRecord.getId())) + .move(createBodyForMoveCopy(recordFolder2)); + assertStatusCode(OK); + } + + private String getModifiedPropertyValue(String originalValue) { + /* to be used to append to modifications */ + String MODIFIED_PREFIX = "modified_"; + return MODIFIED_PREFIX + originalValue; + } + + @AfterClass (alwaysRun = true) + public void deletePreConditions() { + STEP("Delete the created rootCategory along with corresponding record folders/records present in it"); + getRestAPIFactory().getRecordCategoryAPI().deleteRecordCategory(rootCategory.getId()); + } + + } + + diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/DeclareInPlaceRecordTests.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/DeclareInPlaceRecordTests.java new file mode 100644 index 0000000000..3e128883f2 --- /dev/null +++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/DeclareInPlaceRecordTests.java @@ -0,0 +1,145 @@ +/* + * #%L + * Alfresco Records Management Module + * %% + * Copyright (C) 2005 - 2022 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * - + * If the software was purchased under a paid Alfresco license, the terms of + * 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% + */ +package org.alfresco.rest.rm.community.records; + +import org.alfresco.dataprep.CMISUtil; +import org.alfresco.rest.rm.community.base.BaseRMRestTest; +import org.alfresco.rest.rm.community.model.record.Record; +import org.alfresco.rest.v0.RMRolesAndActionsAPI; +import org.alfresco.rest.v0.RecordsAPI; +import org.alfresco.test.AlfrescoTest; +import org.alfresco.utility.constants.UserRole; +import org.alfresco.utility.model.FileModel; +import org.alfresco.utility.model.FolderModel; +import org.alfresco.utility.model.SiteModel; +import org.alfresco.utility.model.UserModel; +import org.springframework.beans.factory.annotation.Autowired; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.UNFILED_RECORDS_CONTAINER_ALIAS; +import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix; +import static org.alfresco.utility.report.log.Step.STEP; +import static org.springframework.http.HttpStatus.CREATED; +import static org.testng.Assert.assertTrue; +/** + * This class contains the tests for + * Create the Document, marking them as Record, Hiding them using Site Collaborator + * The Rm_Admin user then verofy if he is able to access the documents using Rest Api + * + * @author Kavit Shah + */ +public class DeclareInPlaceRecordTests extends BaseRMRestTest { + + private final String TEST_PREFIX = generateTestPrefix(DeclareInPlaceRecordTests.class); + private final String RM_ADMIN = TEST_PREFIX + "rm_admin"; + private UserModel testUser; + private UserModel RmAdminUser; + private SiteModel testSite; + private FolderModel testFolder; + /** + * data prep services + */ + @Autowired + private RMRolesAndActionsAPI rmRolesAndActionsAPI; + @Autowired + private RecordsAPI recordsAPI; + + @BeforeClass(alwaysRun = true) + public void preConditions() { + STEP("Create RM Site"); + createRMSiteIfNotExists(); + + STEP("Create RM Admin user"); + rmRolesAndActionsAPI.createUserAndAssignToRole(getAdminUser().getUsername(), getAdminUser().getPassword(), RM_ADMIN, + getAdminUser().getPassword(), + "Administrator"); + + RmAdminUser = new UserModel(RM_ADMIN,getAdminUser().getPassword()); + + STEP("Create collab_user user"); + testUser = getDataUser().createRandomTestUser(); + testSite = dataSite.usingAdmin().createPublicRandomSite(); + + // invite collab_user to Collaboration site with Contributor role + getDataUser().addUserToSite(testUser, testSite, UserRole.SiteContributor); + + testFolder = dataContent.usingSite(testSite).usingUser(testUser).createFolder(); + } + + @Test + @AlfrescoTest(jira = "RM-2366") + public void declareInplaceRecord() { + + // Upload document in a folder in a collaboration site + FileModel uploadedDocHidden = dataContent.usingSite(testSite) + .usingUser(testUser) + .usingResource(testFolder) + .createContent(CMISUtil.DocumentType.TEXT_PLAIN); + + // declare uploadedDocument as record + Record uploadedRecordHidden = getRestAPIFactory().getFilesAPI(testUser).declareAsRecord(uploadedDocHidden.getNodeRefWithoutVersion()); + assertStatusCode(CREATED); + + recordsAPI.hideRecord(testUser.getUsername(),testUser.getPassword(),uploadedRecordHidden.getId()); + + // Upload document in a folder in a collaboration site + FileModel uploadedDocWithoutHidden = dataContent.usingSite(testSite) + .usingUser(testUser) + .usingResource(testFolder) + .createContent(CMISUtil.DocumentType.TEXT_PLAIN); + + Record uploadedRecordWithoutHidden = getRestAPIFactory().getFilesAPI(testUser).declareAsRecord(uploadedDocWithoutHidden.getNodeRefWithoutVersion()); + assertStatusCode(CREATED); + + assertTrue(isRecordChildOfUnfiledContainer(uploadedRecordHidden.getId()), uploadedRecordHidden.getId() + " doesn't exist in Unfiled Records"); + assertTrue(isRecordChildOfUnfiledContainer(uploadedRecordWithoutHidden.getId()), uploadedRecordWithoutHidden.getId() + " doesn't exist in Unfiled Records"); + } + + @AfterClass(alwaysRun = true) + public void deletePreConditions() { + STEP("Delete the records created in the test"); + getRestAPIFactory() + .getUnfiledContainersAPI(RmAdminUser) + .getUnfiledContainerChildren(UNFILED_RECORDS_CONTAINER_ALIAS) + .getEntries() + .stream() + .forEach(x -> getRestAPIFactory() + .getRecordsAPI() + .deleteRecord(x.getEntry().getId())); + + } + + private boolean isRecordChildOfUnfiledContainer(String recordId) { + return getRestAPIFactory() + .getUnfiledContainersAPI(RmAdminUser) + .getUnfiledContainerChildren(UNFILED_RECORDS_CONTAINER_ALIAS) + .getEntries() + .stream() + .anyMatch(c -> c.getEntry().getId().equals(recordId)); + } +} diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/FileUnfiledRecordsTests.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/FileUnfiledRecordsTests.java new file mode 100644 index 0000000000..e07f2fcd44 --- /dev/null +++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/FileUnfiledRecordsTests.java @@ -0,0 +1,226 @@ +/* + * #%L + * Alfresco Records Management Module + * %% + * Copyright (C) 2005 - 2022 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * - + * If the software was purchased under a paid Alfresco license, the terms of + * 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% + */ + +package org.alfresco.rest.rm.community.records; + +import org.alfresco.dataprep.CMISUtil; +import org.alfresco.rest.core.v0.BaseAPI; +import org.alfresco.rest.model.RestNodeModel; +import org.alfresco.rest.rm.community.base.BaseRMRestTest; +import org.alfresco.rest.rm.community.model.record.Record; +import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory; +import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild; +import org.alfresco.rest.rm.community.requests.gscore.api.RecordFolderAPI; +import org.alfresco.rest.rm.community.requests.gscore.api.UnfiledRecordFolderAPI; +import org.alfresco.rest.v0.RMRolesAndActionsAPI; +import org.alfresco.rest.v0.RecordsAPI; +import org.alfresco.test.AlfrescoTest; +import org.alfresco.utility.constants.UserRole; +import org.alfresco.utility.model.FileModel; +import org.alfresco.utility.model.SiteModel; +import org.alfresco.utility.model.UserModel; +import org.apache.chemistry.opencmis.client.api.CmisObject; +import org.apache.http.HttpResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.alfresco.rest.core.v0.APIUtils.convertHTTPResponseToJSON; +import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.UNFILED_RECORDS_CONTAINER_ALIAS; +import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentType.UNFILED_RECORD_FOLDER_TYPE; +import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix; +import static org.alfresco.rest.rm.community.utils.CoreUtil.createBodyForMoveCopy; +import static org.alfresco.rest.rm.community.utils.CoreUtil.toContentModel; +import static org.alfresco.utility.data.RandomData.getRandomAlphanumeric; +import static org.alfresco.utility.data.RandomData.getRandomName; +import static org.alfresco.utility.report.log.Step.STEP; +import static org.springframework.http.HttpStatus.CREATED; + +public class FileUnfiledRecordsTests extends BaseRMRestTest { + + private final String TEST_PREFIX = generateTestPrefix(FileUnfiledRecordsTests.class); + private final String RM_ADMIN = TEST_PREFIX + "rm_admin"; + public static final String NODE_REF_WORKSPACE_SPACES_STORE = "workspace://SpacesStore/"; + private UserModel testUser; + private SiteModel testSite; + private String unfiledRecordFolderId; + private UserModel RmAdminUser; + private RecordCategory rootCategory; + private RecordCategoryChild recordFolder; + private final String recordName = "RM-2790 record"; + private final String recordTitle = recordName + " title"; + private final String recordDescription = recordName + " description"; + /** + * data prep services + */ + @Autowired + private RMRolesAndActionsAPI rmRolesAndActionsAPI; + @Autowired + private RecordsAPI recordsAPI; + + @BeforeClass(alwaysRun = true) + public void preConditions() { + + STEP("Create RM Site"); + createRMSiteIfNotExists(); + + STEP("Create RM Admin user"); + rmRolesAndActionsAPI.createUserAndAssignToRole(getAdminUser().getUsername(), getAdminUser().getPassword(), RM_ADMIN, + getAdminUser().getPassword(), + "Administrator"); + + RmAdminUser = new UserModel(RM_ADMIN, getAdminUser().getPassword()); + + STEP("Create collab_user user"); + testUser = getDataUser().createRandomTestUser(); + testSite = dataSite.usingAdmin().createPublicRandomSite(); + + // invite collab_user to Collaboration site with Contributor role + getDataUser().addUserToSite(testUser, testSite, UserRole.SiteContributor); + } + + @Test + @AlfrescoTest(jira = "RM-2790") + public void fileUnfiledRecords() throws Exception { + + STEP("Upload the document to test site and then make it reacord"); + // Upload document in a folder in a collaboration site + FileModel uploadedDocbyCollabUser = dataContent.usingSite(testSite) + .usingUser(testUser) + .createContent(CMISUtil.DocumentType.TEXT_PLAIN); + + // declare uploadedDocument as record + Record uploadedDocRecordbyCollabUser = getRestAPIFactory().getFilesAPI(testUser) + .declareAsRecord(uploadedDocbyCollabUser.getNodeRefWithoutVersion()); + assertStatusCode(CREATED); + + STEP("Create root level category"); + rootCategory = createRootCategory(RmAdminUser, getRandomName("Category")); + + STEP("Create the record folder inside the rootCategory"); + recordFolder = createFolder(RmAdminUser, rootCategory.getId(), getRandomName("Folder")); + + STEP("Create a non-electronic record by completing some of the fields"); + Map, String> non_electronic_records_properties = new HashMap<>(); + non_electronic_records_properties.put(BaseAPI.RMProperty.TITLE, recordTitle); + non_electronic_records_properties.put(BaseAPI.RMProperty.DESCRIPTION, recordDescription); + non_electronic_records_properties.put(BaseAPI.RMProperty.NAME, recordName); + non_electronic_records_properties.put(BaseAPI.RMProperty.PHYSICAL_SIZE, ""); + non_electronic_records_properties.put(BaseAPI.RMProperty.NUMBER_OF_COPIES, ""); + non_electronic_records_properties.put(BaseAPI.RMProperty.SHELF, ""); + non_electronic_records_properties.put(BaseAPI.RMProperty.STORAGE_LOCATION, ""); + non_electronic_records_properties.put(BaseAPI.RMProperty.BOX, ""); + non_electronic_records_properties.put(BaseAPI.RMProperty.FILE, ""); + + HttpResponse nonElectronicRecordHttpResponse = recordsAPI.createNonElectronicRecord(getAdminUser().getUsername(), + getAdminUser().getPassword(), non_electronic_records_properties, rootCategory.getName(), recordFolder.getName()); + + String nonElectronicRecordId = getNodeRef(nonElectronicRecordHttpResponse); + + STEP("Check the non-electronic record has been created"); + assertStatusCode(CREATED); + + STEP("Create a electronic record by completing some of the fields"); + Map electronic_records_properties = new HashMap<>(); + electronic_records_properties.put(BaseAPI.RMProperty.DESCRIPTION, recordDescription); + electronic_records_properties.put(BaseAPI.RMProperty.NAME, recordName); + + recordsAPI.uploadElectronicRecord(RmAdminUser.getUsername(), + RmAdminUser.getPassword(), electronic_records_properties, recordFolder.getName(), CMISUtil.DocumentType.TEXT_PLAIN); + + CmisObject electronicRecord = recordsAPI.getRecord(RmAdminUser.getUsername(), + RmAdminUser.getPassword(),recordFolder.getName(), electronic_records_properties.get(BaseAPI.RMProperty.NAME)); + + STEP("Check the electronic record has been created"); + assertStatusCode(CREATED); + + STEP("Create a root folder under FilePlan - Unfiled"); + String unFiledFolder = createUnFileFolder(); + + STEP("Move all the Unfiled Records to unFiledFolder"); + RestNodeModel uploadDocRestNodeModel = getRestAPIFactory() + .getNodeAPI(toContentModel(uploadedDocRecordbyCollabUser.getId())) + .move(createBodyForMoveCopy(unFiledFolder)); + + RestNodeModel nonElectronicDocRestNodeModel = getRestAPIFactory() + .getNodeAPI(toContentModel(nonElectronicRecordId)) + .move(createBodyForMoveCopy(unFiledFolder)); + + RestNodeModel electronicDocRestNodeModel = getRestAPIFactory() + .getNodeAPI(toContentModel(electronicRecord.getId())) + .move(createBodyForMoveCopy(unFiledFolder)); + + STEP("Move all the Record present in the unFiledFolder to Folder inside Root Category"); + + getRestAPIFactory() + .getNodeAPI(toContentModel(uploadDocRestNodeModel.getId())) + .move(createBodyForMoveCopy(recordFolder.getId())); + + getRestAPIFactory() + .getNodeAPI(toContentModel(nonElectronicDocRestNodeModel.getId())) + .move(createBodyForMoveCopy(recordFolder.getId())); + + getRestAPIFactory() + .getNodeAPI(toContentModel(electronicDocRestNodeModel.getId())) + .move(createBodyForMoveCopy(recordFolder.getId())); + + getRestAPIFactory().getRecordsAPI().deleteRecord(uploadDocRestNodeModel.getId()); + getRestAPIFactory().getRecordsAPI().deleteRecord(nonElectronicDocRestNodeModel.getId()); + getRestAPIFactory().getRecordsAPI().deleteRecord(electronicDocRestNodeModel.getId()); + + UnfiledRecordFolderAPI unfiledRecordFoldersAPI = getRestAPIFactory().getUnfiledRecordFoldersAPI(); + unfiledRecordFoldersAPI.deleteUnfiledRecordFolder(unFiledFolder); + + RecordFolderAPI recordFolderAPI = getRestAPIFactory().getRecordFolderAPI(); + String recordFolderId = recordFolder.getId(); + recordFolderAPI.deleteRecordFolder(recordFolderId); + } + + @AfterClass (alwaysRun = true) + public void deletePreConditions() + { + STEP("Delete the created rootCategory along with corresponding record folders/records present in it"); + getRestAPIFactory().getRecordCategoryAPI().deleteRecordCategory(rootCategory.getId()); + } + + private String createUnFileFolder() { + String categoryName = "RM-2790 record Category name " + getRandomAlphanumeric(); + + unfiledRecordFolderId = createUnfiledContainerChild(UNFILED_RECORDS_CONTAINER_ALIAS, + categoryName + getRandomAlphanumeric(), UNFILED_RECORD_FOLDER_TYPE).getId(); + return unfiledRecordFolderId; + } + + private String getNodeRef(HttpResponse httpResponse) { + return convertHTTPResponseToJSON(httpResponse).getString("persistedObject") + .replace(NODE_REF_WORKSPACE_SPACES_STORE, ""); + } +} diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/InplaceRecordSearchTests.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/InplaceRecordSearchTests.java new file mode 100644 index 0000000000..091c683d61 --- /dev/null +++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/InplaceRecordSearchTests.java @@ -0,0 +1,179 @@ +/* + * #%L + * Alfresco Records Management Module + * %% + * Copyright (C) 2005 - 2022 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * - + * If the software was purchased under a paid Alfresco license, the terms of + * 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% + */ + +package org.alfresco.rest.rm.community.records; + +import org.alfresco.dataprep.CMISUtil; +import org.alfresco.rest.rm.community.base.BaseRMRestTest; +import org.alfresco.rest.rm.community.model.record.Record; +import org.alfresco.rest.v0.RecordsAPI; +import org.alfresco.utility.Utility; +import org.alfresco.utility.constants.UserRole; +import org.alfresco.utility.model.FileModel; +import org.alfresco.utility.model.SiteModel; +import org.alfresco.utility.model.UserModel; +import org.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import static org.alfresco.utility.report.log.Step.STEP; +import static org.junit.Assert.assertNotNull; +import static org.springframework.http.HttpStatus.CREATED; +import static org.springframework.test.util.AssertionErrors.assertTrue; +import static org.testng.Assert.fail; + +public class InplaceRecordSearchTests extends BaseRMRestTest { + + private UserModel siteCollaborator, siteConsumer, nonSiteMember; + private SiteModel privateSite; + private Record uploadedDocRecordbyCollabUser; + private FileModel uploadedDocbyCollabUser; + @Autowired + private RecordsAPI recordsAPI; + + @BeforeClass(alwaysRun = true) + public void preConditions() { + + STEP("Create RM Site"); + createRMSiteIfNotExists(); + + // And a private collaboration site + privateSite = dataSite.usingAdmin().createPrivateRandomSite(); + + // And a site collaborator + siteCollaborator = getDataUser().createRandomTestUser(); + getDataUser().addUserToSite(siteCollaborator, privateSite, UserRole.SiteCollaborator); + + // And a site consumer + siteConsumer = getDataUser().createRandomTestUser(); + getDataUser().addUserToSite(siteConsumer, privateSite, UserRole.SiteConsumer); + + nonSiteMember = getDataUser().createRandomTestUser(); + } + + /** + * Given a RM site + * And a private collaboration site + * And a site collaborator + * And a site consumer + * And a user who is not a member of the site + * And a document that isn't a record + * When the collaborator declares it as a record + * Then the collaborator can browse to the record in the document library + * And can find the record using live search + * And can find the record using advanced search + * And the consumer can browse to the record in the document library + * And can find the record using live search + * And can find the record using advanced search + * And the user who is not a member of the site can't find the record using live search + * And can't find the record using advanced search + */ + @Test + public void searchForInplaceRecord() { + // And a document that isn't a record + uploadedDocbyCollabUser = dataContent.usingSite(privateSite) + .usingUser(siteCollaborator) + .createContent(CMISUtil.DocumentType.TEXT_PLAIN); + + assertNotNull(uploadedDocbyCollabUser.getNodeRef()); + + // declare uploadedDocument as record + uploadedDocRecordbyCollabUser = getRestAPIFactory().getFilesAPI(siteCollaborator) + .declareAsRecord(uploadedDocbyCollabUser.getNodeRefWithoutVersion()); + assertStatusCode(CREATED); + + assertNotNull(uploadedDocRecordbyCollabUser.getId()); + + STEP("Allow the Document to be index for it to be available"); + + try + { + Utility.sleep(1000, 40000, () -> + { + JSONObject siteConsumerSearchJson = getSearchApi().liveSearchForDocuments(siteConsumer.getUsername(), + siteConsumer.getPassword(), + uploadedDocbyCollabUser.getName()); + assertTrue("Site Consumer not able to find the document.",siteConsumerSearchJson.getJSONArray("items").length() != 0); + }); + } + catch (InterruptedException e) + { + fail("InterruptedException received while waiting for results."); + } + + try + { + Utility.sleep(1000, 40000, () -> + { + JSONObject siteCollaboratorSearchJson = getSearchApi().liveSearchForDocuments(siteCollaborator.getUsername(), + siteCollaborator.getPassword(), + uploadedDocbyCollabUser.getName()); + assertTrue("Site Collaborator not able to find the document.",siteCollaboratorSearchJson.getJSONArray("items").length() != 0); + }); + } + catch (InterruptedException e) + { + fail("InterruptedException received while waiting for results."); + } + + JSONObject nonSiteMemberSearchJson = getSearchApi().liveSearchForDocuments(nonSiteMember.getUsername(), + nonSiteMember.getPassword(), + uploadedDocbyCollabUser.getName()); + + assertTrue("Non Site Member is able to access restricted document.",nonSiteMemberSearchJson.getJSONArray("items").isEmpty()); + } + + /** + * Given @see {@link #searchForInplaceRecord()} + * When the collaboration user hides the record in the collaboration site + * Then the collaborator can not browse to the record in the document library + * And can't find the record using live search + * And can't find the record using advanced search + */ + @Test(dependsOnMethods = {"searchForInplaceRecord"}) + public void usersCantFindRecordAfterHide() { + recordsAPI.hideRecord(siteCollaborator.getUsername(),siteCollaborator.getPassword(),uploadedDocRecordbyCollabUser.getId()); + + JSONObject siteCollaboratorSearchJson = getSearchApi().liveSearchForDocuments(siteCollaborator.getUsername(), + siteCollaborator.getPassword(), + uploadedDocbyCollabUser.getName()); + assertTrue("Site Collaborator able to find the document after it is hidden.",siteCollaboratorSearchJson.getJSONArray("items").isEmpty()); + } + + @AfterClass + public void tearDown() { + // clean-up collab site + dataSite.usingAdmin().deleteSite(privateSite); + + // clean-up users siteCollaborator, siteConsumer, nonSiteMember + dataUser.deleteUser(siteCollaborator); + dataUser.deleteUser(siteConsumer); + dataUser.deleteUser(nonSiteMember); + } +} diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/SearchRecordsTests.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/SearchRecordsTests.java new file mode 100644 index 0000000000..7b260f668d --- /dev/null +++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/SearchRecordsTests.java @@ -0,0 +1,539 @@ +/* + * #%L + * Alfresco Records Management Module + * %% + * Copyright (C) 2005 - 2022 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * - + * If the software was purchased under a paid Alfresco license, the terms of + * 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% + */ + +package org.alfresco.rest.rm.community.records; + +import org.alfresco.dataprep.CMISUtil; +import org.alfresco.rest.core.v0.BaseAPI; +import org.alfresco.rest.rm.community.base.BaseRMRestTest; +import org.alfresco.rest.rm.community.model.record.RecordContent; +import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory; +import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild; +import org.alfresco.rest.rm.community.model.unfiledcontainer.UnfiledContainerChild; +import org.alfresco.rest.rm.community.requests.gscore.api.UnfiledContainerAPI; +import org.alfresco.rest.v0.RMRolesAndActionsAPI; +import org.alfresco.rest.v0.RecordsAPI; +import org.alfresco.rest.v0.SearchAPI; +import org.alfresco.utility.Utility; +import org.alfresco.utility.model.UserModel; +import org.apache.http.HttpResponse; +import org.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.json.JSONArray; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.HashMap; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import static org.alfresco.rest.rm.community.base.TestData.ELECTRONIC_RECORD_NAME; +import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.UNFILED_RECORDS_CONTAINER_ALIAS; +import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentType.CONTENT_TYPE; +import static org.alfresco.rest.rm.community.model.user.UserPermissions.*; +import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix; +import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.createTempFile; +import static org.alfresco.utility.report.log.Step.STEP; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.fail; +import static org.testng.Assert.assertTrue; +/** + * Tests the search of records in Records Search page + * @author Kavit Shah + */ +public class SearchRecordsTests extends BaseRMRestTest { + + private Optional nonRmSiteUser, rm_user_search, rm_manager, rm_admin_search; + + /** The default password used when creating test users. */ + public static final String ROLE_RM_MANAGER = "RecordsManager"; + private final String TEST_PREFIX = generateTestPrefix(SearchRecordsTests.class); + private final String CATEGORY_ALL = TEST_PREFIX + "everybody's category"; + private final String FOLDER_SEARCH = TEST_PREFIX + "basic search folder"; + private final String FOLDER_ADMIN_ONLY = TEST_PREFIX + "rm admin category"; + private final String CATEGORY_ADMIN_ONLY = TEST_PREFIX + "rm admin category"; + public static final String ROLE_RM_USER = "User"; + public static final String ADMIN = "Administrator"; + private final String ELECTRONIC_RECORD = TEST_PREFIX + " Electronic"; + private final String UNFILED_ELECTRONIC_RECORD = TEST_PREFIX + " Unfiled Electronic"; + private final String NON_ELECTRONIC_RECORD = TEST_PREFIX + " Non-Electronic"; + private final String ADMIN_ELECTRONIC_RECORD = TEST_PREFIX + " admin Electronic"; + public static final String TITLE = "Title"; + public static final String DESCRIPTION = "Description"; + public static final String TEST_CONTENT = "This is some test content"; + private RecordCategory categoryAll, category_Admin_Only; + @Autowired + private RMRolesAndActionsAPI rmRolesAndActionsAPI; + @Autowired + private SearchAPI searchAPI; + @Autowired + private RecordsAPI recordsAPI; + + @BeforeClass (alwaysRun = true) + public void createRecordsForSearch() + { + createRMSiteIfNotExists(); + nonRmSiteUser = Optional.ofNullable(getDataUser().createRandomTestUser()); + // create RM manager and RM user + createRMManager(); + createRMUser(); + createRMAdmin(); + categoryAll = createCategoryIfDoesNotExist(CATEGORY_ALL); + createRecordFolderInCategory(FOLDER_SEARCH, categoryAll); + + category_Admin_Only = createCategoryIfDoesNotExist(CATEGORY_ADMIN_ONLY); + createRecordFolderInCategory(FOLDER_ADMIN_ONLY,category_Admin_Only); + + // upload records in folder in category and in Unfiled Records + uploadElectronicRecordInContainer(ELECTRONIC_RECORD, FOLDER_SEARCH); + createNonElectronicRecordInContainer(NON_ELECTRONIC_RECORD, CATEGORY_ALL, FOLDER_SEARCH); + uploadElectronicRecordInContainer(ADMIN_ELECTRONIC_RECORD, FOLDER_ADMIN_ONLY); + + UnfiledContainerChild electronicRecord = UnfiledContainerChild.builder() + .name(UNFILED_ELECTRONIC_RECORD) + .nodeType(CONTENT_TYPE) + .content(RecordContent.builder().mimeType("text/plain").build()) + .build(); + getRecordsFromUnfiledRecordsContainer(electronicRecord); + } + + /** + * Given I have created record category X which contains record folder Y which contains record Z + * And I have selected to display record category id in the search results + * When I issue a record search whose results will contain record X + * Then record X is displayed in the results + * And the record category X's ID is also displayed in search result meta-data for record X + */ + @Test(priority = 1) + public void searchResultsWithRecordCategoryIdentifier() { + AtomicBoolean electronicRecordFound = new AtomicBoolean(false); + AtomicReference items = new AtomicReference<>(); + AtomicBoolean recordCategoryIdentifier = new AtomicBoolean(false); + + STEP("Open the record search page and search by the items created"); + try { + Utility.sleep(1000, 40000, () -> { + JSONObject searchResult = (searchAPI + .rmSearch(getDataUser().usingAdmin().getAdminUser().getUsername(), + getDataUser().usingAdmin().getAdminUser().getPassword(), + "rm", + "keywords:" + TEST_PREFIX + "*", + "records/true,undeclared/true,vital/false,folders/false,categories/false,frozen/false,cutoff/false", + "rma:identifier/asc")); + items.set((JSONArray) searchResult.get("items")); + assertFalse("Site Consumer not able to find the document.", ((JSONArray)searchResult.get("items")).isEmpty()); + }); + } + catch (InterruptedException e) { + fail("InterruptedException received while waiting for results."); + } + + STEP("Check that the records from file plan have the record category identifier displayed"); + List searchList = IntStream.range(0, items.get().length()).mapToObj(i-> items.get().get(i)).collect(Collectors.toList()); + + searchList.stream().forEach(x -> { + Map reconstructedUtilMap = Arrays.stream(x.toString().split(",")) + .map(s -> s.split(":")) + .collect(Collectors.toMap(s -> s[0], s -> s[1])); + if(reconstructedUtilMap.get("\"name\"").contains(TEST_PREFIX + " Electronic")) { + electronicRecordFound.set(true); + } + }); + assertFalse("The File Name with the Prefix " + TEST_PREFIX + " as Electronic Record was not found.", !electronicRecordFound.get()); + + STEP("Change the search filter to return only record folders and record categories"); + try { + Utility.sleep(1000, 40000, () -> { + JSONObject searchResult = (searchAPI + .rmSearch(getDataUser().usingAdmin().getAdminUser().getUsername(), + getDataUser().usingAdmin().getAdminUser().getPassword(), + "rm", + "keywords:" + TEST_PREFIX + "*", + "records/false,undeclared/true,vital/false,folders/true,categories/true,frozen/false,cutoff/false", + "rma:identifier/asc")); + items.set((JSONArray) searchResult.get("items")); + assertFalse("Site Consumer not able to find the document.", ((JSONArray)searchResult.get("items")).isEmpty()); + }); + } + catch (InterruptedException e) { + fail("InterruptedException received while waiting for results."); + } + STEP("Check that the records folders and categories don't have a record category identifier displayed"); + List recordFolderSearchList = IntStream.range(0, items.get().length()).mapToObj(i-> items.get().get(i)).collect(Collectors.toList()); + + recordFolderSearchList.stream().forEach(x -> { + Map reconstructedUtilMap = Arrays.stream(x.toString().split(",")) + .map(s -> s.split(":")) + .collect(Collectors.toMap(s -> s[0], s -> s[1])); + if(null != reconstructedUtilMap.get("\"rma_recordCategoryIdentifier\"")) { + recordCategoryIdentifier.set(true); + } + }); + assertFalse("Record Category Identifier displayed for " + TEST_PREFIX + ".", recordCategoryIdentifier.get()); + } + + /** + * User with RM User role can see the records he has permission over and all in Unfiled Records + *

+ * Given that I am a RM User + * I can see only the records in File Plan I have permission over and all in Unfiled Records + */ + @Test (priority = 2) + public void nonRMUserSearchResults() { + try { + Utility.sleep(1000, 40000, () -> { + List stringList = (searchAPI + .searchForDocumentsAsUser(nonRmSiteUser.get().getUsername(), + nonRmSiteUser.get().getPassword(), + ELECTRONIC_RECORD)); + assertFalse("The file with search term " + ELECTRONIC_RECORD + " was found using RM Not Site User "+ nonRmSiteUser.get().getUsername(),getResult(ELECTRONIC_RECORD,stringList)); + }); + } + catch (InterruptedException e) { + fail("InterruptedException received while waiting for results."); + } + + try { + Utility.sleep(1000, 40000, () -> { + List stringList = (searchAPI + .searchForDocumentsAsUser(nonRmSiteUser.get().getUsername(), + nonRmSiteUser.get().getPassword(), + UNFILED_ELECTRONIC_RECORD)); + assertFalse("The file with search term " + UNFILED_ELECTRONIC_RECORD + " was not found using RM Not Site User "+ nonRmSiteUser.get().getUsername(),getResult(UNFILED_ELECTRONIC_RECORD,stringList)); + }); + } + catch (InterruptedException e) { + fail("InterruptedException received while waiting for results."); + } + + try { + Utility.sleep(1000, 40000, () -> { + List stringList = (searchAPI + .searchForDocumentsAsUser(nonRmSiteUser.get().getUsername(), + nonRmSiteUser.get().getPassword(), + NON_ELECTRONIC_RECORD)); + assertFalse("The file with search term " + NON_ELECTRONIC_RECORD + " was not found using RM Not Site User "+ nonRmSiteUser.get().getUsername(),getResult(NON_ELECTRONIC_RECORD,stringList)); + }); + } + catch (InterruptedException e) { + fail("InterruptedException received while waiting for results."); + } + + try { + Utility.sleep(1000, 40000, () -> { + List stringList = searchAPI + .searchForDocumentsAsUser(nonRmSiteUser.get().getUsername(), + nonRmSiteUser.get().getPassword(), + ADMIN_ELECTRONIC_RECORD); + assertFalse("The file with search term " + ADMIN_ELECTRONIC_RECORD + " was not found using RM Not Site User "+ nonRmSiteUser.get().getUsername(),getResult(ADMIN_ELECTRONIC_RECORD,stringList)); + }); + } + catch (InterruptedException e) { + fail("InterruptedException received while waiting for results."); + } + } + + /** + * User with RM User role can see the records he has permission over and all in Unfiled Records + *

+ * Given that I am a RM User + * I can see only the records in File Plan I have permission over and all in Unfiled Records + */ + @Test (priority = 3) + public void rmUserSearchResults() { + getRestAPIFactory().getRMUserAPI().addUserPermission(categoryAll.getId(), rm_user_search.get(), PERMISSION_READ_RECORDS); + getRestAPIFactory().getRMUserAPI().addUserPermission(categoryAll.getId(), rm_user_search.get(), PERMISSION_FILE_RECORDS); + + try { + Utility.sleep(1000, 40000, () -> { + List stringList = (searchAPI + .searchForDocumentsAsUser(rm_user_search.get().getUsername(), + rm_user_search.get().getPassword(), + ELECTRONIC_RECORD)); + assertTrue(getResult(ELECTRONIC_RECORD,stringList),"The file with search term" + ELECTRONIC_RECORD + " was not found using RM User "+ rm_user_search.get().getUsername()); + }); + } + catch (InterruptedException e) { + fail("InterruptedException received while waiting for results."); + } + + try { + Utility.sleep(1000, 40000, () -> { + List stringList = (searchAPI + .searchForDocumentsAsUser(rm_user_search.get().getUsername(), + rm_user_search.get().getPassword(), + UNFILED_ELECTRONIC_RECORD)); + assertTrue(getResult(UNFILED_ELECTRONIC_RECORD,stringList),"The file with search term" + UNFILED_ELECTRONIC_RECORD + " was not found using RM User "+ rm_user_search.get().getUsername()); + }); + } + catch (InterruptedException e) { + fail("InterruptedException received while waiting for results."); + } + + try { + Utility.sleep(1000, 40000, () -> { + List stringList = (searchAPI + .searchForDocumentsAsUser(rm_user_search.get().getUsername(), + rm_user_search.get().getPassword(), + NON_ELECTRONIC_RECORD)); + assertTrue(getResult(NON_ELECTRONIC_RECORD,stringList),"The file with search term" + NON_ELECTRONIC_RECORD + " was not found using RM User "+ rm_user_search.get().getUsername()); + }); + } + catch (InterruptedException e) { + fail("InterruptedException received while waiting for results."); + } + + try { + Utility.sleep(1000, 40000, () -> { + List stringList = searchAPI + .searchForDocumentsAsUser(rm_user_search.get().getUsername(), + rm_user_search.get().getPassword(), + ADMIN_ELECTRONIC_RECORD); + assertFalse("The file with search term" + ADMIN_ELECTRONIC_RECORD + " was not found using RM User "+ rm_user_search.get().getUsername(),getResult(ADMIN_ELECTRONIC_RECORD,stringList)); + }); + } + catch (InterruptedException e) { + fail("InterruptedException received while waiting for results."); + } + } + + /** + * User with RM Manager role can see the records he has permission over and all in Unfiled Records + *

+ * Given that I am a RM Manager + * I can see only the records in File Plan I have permission over and all in Unfiled Records + */ + @Test (priority = 4) + public void rmManagerSearchResults() { + getRestAPIFactory().getRMUserAPI().addUserPermission(categoryAll.getId(), rm_manager.get(), PERMISSION_READ_RECORDS); + + try { + Utility.sleep(1000, 40000, () -> { + List stringList = (searchAPI + .searchForDocumentsAsUser(rm_manager.get().getUsername(), + rm_manager.get().getPassword(), + ELECTRONIC_RECORD)); + assertTrue(getResult(ELECTRONIC_RECORD,stringList),"The file with search term " + ELECTRONIC_RECORD + " was not found using RM manager User "+ rm_manager.get().getUsername()); + }); + } + catch (InterruptedException e) { + fail("InterruptedException received while waiting for results."); + } + + try { + Utility.sleep(1000, 40000, () -> { + List stringList = (searchAPI + .searchForDocumentsAsUser(rm_manager.get().getUsername(), + rm_manager.get().getPassword(), + UNFILED_ELECTRONIC_RECORD)); + assertTrue(getResult(UNFILED_ELECTRONIC_RECORD,stringList),"The file with search term " + UNFILED_ELECTRONIC_RECORD + " was not found using RM manager User "+ rm_manager.get().getUsername()); + }); + } + catch (InterruptedException e) { + fail("InterruptedException received while waiting for results."); + } + + try { + Utility.sleep(1000, 40000, () -> { + List stringList = (searchAPI + .searchForDocumentsAsUser(rm_manager.get().getUsername(), + rm_manager.get().getPassword(), + NON_ELECTRONIC_RECORD)); + assertTrue(getResult(NON_ELECTRONIC_RECORD,stringList),"The file with search term " + NON_ELECTRONIC_RECORD + " was not found using RM manager User "+ rm_manager.get().getUsername()); + }); + } + catch (InterruptedException e) { + fail("InterruptedException received while waiting for results."); + } + + try { + Utility.sleep(1000, 40000, () -> { + List stringList = searchAPI + .searchForDocumentsAsUser(rm_manager.get().getUsername(), + rm_manager.get().getPassword(), + ADMIN_ELECTRONIC_RECORD); + assertFalse("The file with search term" + ADMIN_ELECTRONIC_RECORD + " was found using RM manager User "+ rm_manager.get().getUsername(),getResult(ADMIN_ELECTRONIC_RECORD,stringList)); + }); + } + catch (InterruptedException e) { + fail("InterruptedException received while waiting for results."); + } + } + + /** + * User with RM Administrator role can see all the records + * + * Given that I am a RM Administrator + * I can see all the records in File Plan and Unfiled Records through RM Search and Advanced Search + */ + @Test(priority = 5) + public void rmAdminSearchResults() { + try { + Utility.sleep(1000, 40000, () -> { + List stringList = (searchAPI + .searchForDocumentsAsUser(rm_admin_search.get().getUsername(), + rm_admin_search.get().getPassword(), + ELECTRONIC_RECORD)); + assertTrue(getResult(ELECTRONIC_RECORD,stringList),"The file with search term " + ELECTRONIC_RECORD + " was not found using RM Admin User "+ rm_admin_search.get().getUsername()); + }); + } + catch (InterruptedException e) { + fail("InterruptedException received while waiting for results."); + } + + try { + Utility.sleep(1000, 40000, () -> { + List stringList = (searchAPI + .searchForDocumentsAsUser(rm_admin_search.get().getUsername(), + rm_admin_search.get().getPassword(), + UNFILED_ELECTRONIC_RECORD)); + assertTrue(getResult(UNFILED_ELECTRONIC_RECORD,stringList),"The file with search term " + UNFILED_ELECTRONIC_RECORD + " was not found using RM Admin User "+ rm_admin_search.get().getUsername()); + }); + } + catch (InterruptedException e) { + fail("InterruptedException received while waiting for results."); + } + + try { + Utility.sleep(1000, 40000, () -> { + List stringList = (searchAPI + .searchForDocumentsAsUser(rm_admin_search.get().getUsername(), + rm_admin_search.get().getPassword(), + NON_ELECTRONIC_RECORD)); + assertTrue(getResult(NON_ELECTRONIC_RECORD,stringList),"The file with search term " + NON_ELECTRONIC_RECORD + " was not found using RM Admin User "+ rm_admin_search.get().getUsername()); + }); + } + catch (InterruptedException e) { + fail("InterruptedException received while waiting for results."); + } + } + + private void createRMManager() { + // create RM manager + rm_manager = Optional.ofNullable(getDataUser().createRandomTestUser()); + rmRolesAndActionsAPI.assignRoleToUser( + getDataUser().usingAdmin().getAdminUser().getUsername(), + getDataUser().usingAdmin().getAdminUser().getPassword(), + rm_manager.get().getUsername(), + ROLE_RM_MANAGER + ); + } + + private void createRMUser() { + // create RM manager + rm_user_search = Optional.ofNullable(getDataUser().createRandomTestUser()); + rmRolesAndActionsAPI.assignRoleToUser( + getDataUser().usingAdmin().getAdminUser().getUsername(), + getDataUser().usingAdmin().getAdminUser().getPassword(), + rm_user_search.get().getUsername(), + ROLE_RM_USER + ); + } + + private void createRMAdmin() { + // create RM Admin + rm_admin_search = Optional.ofNullable(getDataUser().createRandomTestUser()); + rmRolesAndActionsAPI.assignRoleToUser( + getDataUser().usingAdmin().getAdminUser().getUsername(), + getDataUser().usingAdmin().getAdminUser().getPassword(), + rm_admin_search.get().getUsername(), + ADMIN + ); + } + + private RecordCategory createCategoryIfDoesNotExist(String CATEGORY_ALL) { + return createRootCategory(getDataUser().usingAdmin().getAdminUser(), CATEGORY_ALL); + } + + private RecordCategoryChild createRecordFolderInCategory(String FOLDER_SEARCH, RecordCategory recordCategory) { + return createFolder(getDataUser().usingAdmin().getAdminUser(), recordCategory.getId(), FOLDER_SEARCH); + } + + private void uploadElectronicRecordInContainer(String electronic_record, String folder_search) { + recordsAPI.uploadElectronicRecord(getDataUser().usingAdmin().getAdminUser().getUsername(), + getDataUser().usingAdmin().getAdminUser().getPassword(), + getDefaultElectronicRecordProperties(electronic_record), folder_search, CMISUtil.DocumentType.TEXT_PLAIN); + } + + + protected HttpResponse createNonElectronicRecordInContainer(String name, String categoryName, String folderName) { + Map defaultProperties = new HashMap<>(); + defaultProperties.put(BaseAPI.RMProperty.NAME, name); + defaultProperties.put(BaseAPI.RMProperty.TITLE, TITLE); + defaultProperties.put(BaseAPI.RMProperty.DESCRIPTION, DESCRIPTION); + + return recordsAPI.createNonElectronicRecord(getDataUser().usingAdmin().getAdminUser().getUsername(), + getDataUser().usingAdmin().getAdminUser().getPassword(), defaultProperties, categoryName, folderName); + } + + public Map getDefaultElectronicRecordProperties(String recordName) { + Map defaultProperties = new HashMap<>(); + defaultProperties.put(BaseAPI.RMProperty.NAME, recordName); + defaultProperties.put(BaseAPI.RMProperty.TITLE, TITLE); + defaultProperties.put(BaseAPI.RMProperty.DESCRIPTION, DESCRIPTION); + defaultProperties.put(BaseAPI.RMProperty.CONTENT, TEST_CONTENT); + return defaultProperties; + } + + @AfterClass(alwaysRun = true) + public void standardSearchTeardown() { + // delete categories + deleteRecordCategory(categoryAll.getId()); + deleteRecordCategory(category_Admin_Only.getId()); + + // delete users + Optional.of(nonRmSiteUser).ifPresent(x -> getDataUser().deleteUser(x.get())); + Optional.of(rm_user_search).ifPresent(x -> getDataUser().deleteUser(x.get())); + Optional.of(rm_manager).ifPresent(x -> getDataUser().deleteUser(x.get())); + Optional.of(rm_admin_search).ifPresent(x -> getDataUser().deleteUser(x.get())); + } + + private boolean getResult(String partialRecordName, List searchResults) { + if(null != searchResults) { + for (String searchResult : searchResults) { + if (searchResult.startsWith(partialRecordName)) { + return true; + } + } + } + return false; + } + + private Object[][] getRecordsFromUnfiledRecordsContainer(UnfiledContainerChild electronicRecord) + { + UnfiledContainerAPI unfiledContainersAPI = getRestAPIFactory().getUnfiledContainersAPI(); + return new String[][] { + { unfiledContainersAPI.uploadRecord(electronicRecord, UNFILED_RECORDS_CONTAINER_ALIAS, + createTempFile(ELECTRONIC_RECORD_NAME, ELECTRONIC_RECORD_NAME)).getId()} + }; + } +}