Tests for Add and Remove active content to/from hold using exiting API's

This commit is contained in:
Rodica Sutu
2019-08-20 08:50:58 +03:00
parent 5b0d068fb3
commit 883509629a
12 changed files with 1296 additions and 86 deletions

View File

@@ -81,7 +81,7 @@ public abstract class BaseAPI
protected static final String UPDATE_METADATA_API = "{0}node/{1}/formprocessor";
protected static final String ACTIONS_API = "{0}actionQueue";
protected static final String RM_ACTIONS_API = "{0}rma/actions/ExecutionQueue";
protected static final String RM_SITE_ID = "rm";
public static final String RM_SITE_ID = "rm";
protected static final String SHARE_ACTION_API = "{0}internal/shared/share/workspace/SpacesStore/{1}";
private static final String SLINGSHOT_PREFIX = "alfresco/s/slingshot/";

View File

@@ -0,0 +1,56 @@
/*-
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.rm.community.model.hold;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.alfresco.utility.model.TestModel;
/**
* POJO for hold entry
*
* @author Rodica Sutu
* @since 3.2
*/
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties (ignoreUnknown = true)
public class HoldEntry extends TestModel
{
@JsonProperty (required = true)
private String name;
@JsonProperty (required = true)
private String nodeRef;
}

View File

@@ -29,6 +29,7 @@ package org.alfresco.rest.rm.community.model.unfiledcontainer;
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentFields.PROPERTIES_IDENTIFIER;
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentFields.PROPERTIES_ROOT_NODE_REF;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.alfresco.utility.model.TestModel;
@@ -50,6 +51,7 @@ import lombok.NoArgsConstructor;
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties (ignoreUnknown = true)
public class UnfiledContainerProperties extends TestModel
{
/*************************/

View File

@@ -0,0 +1,323 @@
/*-
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.v0;
import static org.apache.http.HttpStatus.SC_OK;
import static org.testng.AssertJUnit.assertNotNull;
import javax.json.Json;
import javax.json.JsonReader;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.alfresco.rest.core.v0.BaseAPI;
import org.alfresco.rest.rm.community.model.hold.HoldEntry;
import org.alfresco.rest.rm.community.util.PojoUtility;
import org.alfresco.utility.Utility;
import org.apache.chemistry.opencmis.client.api.CmisObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.stereotype.Component;
/**
* Methods to make API requests using v0 API for generalized holds
*
* @author Rodica Sutu
* @since 3.2
*/
@Component
public class HoldsAPI extends BaseAPI
{
public static final String HOLDS_CONTAINER = "Holds";
private static final String CREATE_HOLDS_API = "{0}type/rma:hold/formprocessor";
/** The URI to add items to hold.*/
private static final String RM_HOLDS_API = "{0}rma/holds";
private static final String GET_RM_HOLDS = RM_HOLDS_API + "?{1}";
/**
* Util method to create a hold
*
* @param user the user creating the category
* @param password the user's password
* @param holdName the hold name
* @param reason hold reason
* @param description hold description
* @return The HTTP response (or null if no POST call was needed).
*/
public HttpResponse createHold(String user, String password,
String holdName, String reason, String description)
{
// if the hold already exists don't try to create it again
final String fullHoldPath = Utility.buildPath(getFilePlanPath(), HOLDS_CONTAINER) + holdName;
final CmisObject hold = getObjectByPath(user, password, fullHoldPath);
if (hold != null)
{
return null;
}
// retrieve the Holds container nodeRef
final String parentNodeRef = getItemNodeRef(user, password, "/" + HOLDS_CONTAINER);
final JSONObject requestParams = new JSONObject();
requestParams.put("alf_destination", getNodeRefSpacesStore() + parentNodeRef);
requestParams.put("prop_cm_name", holdName);
requestParams.put("prop_cm_description", description);
requestParams.put("prop_rma_holdReason", reason);
// Make the POST request and throw an assertion error if it fails.
final HttpResponse httpResponse = doPostJsonRequest(user, password, SC_OK, requestParams, CREATE_HOLDS_API);
assertNotNull("Expected object to have been created at " + fullHoldPath,
getObjectByPath(user, password, fullHoldPath));
return httpResponse;
}
/**
* Create a hold and get the node ref of the hold from the response body
*
* @param user
* @param password
* @param holdName
* @param reason
* @param description
* @return node ref of the hold created
*/
public String createHoldAndGetNodeRef(String user, String password,
String holdName, String reason, String description)
{
final HttpResponse httpResponse = createHold(user, password, holdName, reason, description);
try
{
return new JSONObject(EntityUtils.toString(httpResponse.getEntity()))
.getString("persistedObject")
.replaceAll(NODE_REF_WORKSPACE_SPACES_STORE, "");
}
catch(JSONException error)
{
LOGGER.error("Converting message body to JSON failed. Body: {}", httpResponse, error);
}
catch(ParseException | IOException error)
{
LOGGER.error("Parsing message body failed.", error);
}
return null;
}
/**
* Deletes hold
*
* @param username user's username
* @param password its password
* @param holdName the hold name
* @throws AssertionError if the deletion was unsuccessful.
*/
public void deleteHold( String username, String password, String holdName)
{
deleteItem(username, password, String.format("/%s/%s", HOLDS_CONTAINER, holdName));
}
/**
* Adds item (active content /record/ record folder) to the hold
*
* @param user the user who adds the item to the hold
* @param password the user's password
* @param itemNodeRef the nodeRef of the item to be added to hold
* @param holdName the hold name
* @return The HTTP response
*/
public HttpResponse addItemToHold(String user, String password, String itemNodeRef, String holdName)
{
return addItemToHold(user, password, SC_OK, itemNodeRef, holdName);
}
/**
* Adds item (record/ record folder) to the hold
*
* @param user the user who adds the item to the hold
* @param password the user's password
* @param itemNodeRef the nodeRef of the item to be added to hold
* @param holdName the hold name
* @return The HTTP response
*/
public HttpResponse addItemToHold(String user, String password, int expectedStatus, String itemNodeRef, String
holdName)
{
final JSONObject requestParams = createHoldJsonObject(user, password, itemNodeRef, holdName);
return doPostJsonRequest(user, password, expectedStatus, requestParams, RM_HOLDS_API);
}
/**
* Util method to add item (active content /record/ record folder) to the hold and gets the error message
*
* @param user the user who adds the item to the hold
* @param password the user's password
* @param itemNodeRef the nodeRef of the item to be added to hold
* @param holdName the hold name
* @return The error message
*/
public String addToHoldAndGetMessage(String user, String password, int expectedStatus, String itemNodeRef, String
holdName)
{
final HttpResponse httpResponse = addItemToHold(user, password, expectedStatus, itemNodeRef, holdName);
return extractErrorMessageFromHttpResponse(httpResponse);
}
/**
* Util method to create the request body for adding an item to hold
* @param user
* @param password
* @param itemNodeRef
* @param holdName
* @return JSONObject fo
*/
private JSONObject createHoldJsonObject(String user, String password, String itemNodeRef, String holdName)
{
final JSONArray nodeRefs = new JSONArray().put(getNodeRefSpacesStore() + itemNodeRef);
final List<String> holdNames = Arrays.asList(holdName.split(","));
final List<String> holdNoderefs = holdNames.stream().map(hold ->
getNodeRefSpacesStore() + getItemNodeRef(user, password, String.format("/%s/%s", HOLDS_CONTAINER, hold)))
.collect(Collectors.toList());
final JSONArray holds = new JSONArray();
holdNoderefs.forEach(holds::put);
final JSONObject requestParams = new JSONObject();
requestParams.put("nodeRefs", nodeRefs);
requestParams.put("holds", holds);
return requestParams;
}
/**
* Remove item (active content /record/ record folder) from the hold
*
* @param user the user who adds the item to the hold
* @param password the user's password
* @param itemNodeRef the nodeRef of the item to be added to hold
* @param holdName the hold name
* @return The HTTP response
*/
public HttpResponse removeItemFromHold(String user, String password, String itemNodeRef, String holdName)
{
return removeItemFromHold(user, password, SC_OK, itemNodeRef, holdName);
}
/**
* Adds item (record/ record folder) to the hold
*
* @param user the user who adds the item to the hold
* @param password the user's password
* @param itemNodeRef the nodeRef of the item to be added to hold
* @param holdName the hold name
* @return The HTTP response
*/
public HttpResponse removeItemFromHold(String user, String password, int expectedStatus, String itemNodeRef, String
holdName)
{
final JSONObject requestParams = createHoldJsonObject(user, password, itemNodeRef, holdName);
return doPutJsonRequest(user, password, expectedStatus, requestParams, RM_HOLDS_API);
}
/**
* Util method to add item (active content /record/ record folder) to the hold and gets the error message
*
* @param user the user who adds the item to the hold
* @param password the user's password
* @param itemNodeRef the nodeRef of the item to be added to hold
* @param holdName the hold name
* @return The error message
*/
public String removeFromHoldAndGetMessage(String user, String password, int expectedStatus, String itemNodeRef, String
holdName)
{
final HttpResponse httpResponse = removeItemFromHold(user, password, expectedStatus, itemNodeRef, holdName);
return extractErrorMessageFromHttpResponse(httpResponse);
}
/**
* Util method to extract the message string from the HTTP response
* @param httpResponse
* @return
*/
private String extractErrorMessageFromHttpResponse(HttpResponse httpResponse)
{
final HttpEntity entity = httpResponse.getEntity();
try(InputStream responseStream = entity.getContent(); JsonReader reader = Json.createReader(responseStream))
{
return reader.readObject().getString("message");
}
catch (JSONException error)
{
LOGGER.error("Converting message body to JSON failed. Body: {}", httpResponse, error);
}
catch (ParseException | IOException error)
{
LOGGER.error("Parsing message body failed.", error);
}
return null;
}
/**
* Get the list of the available holds which have the item node reference if includedInHold parameter is true
* otherwise a list of hold node references will be retrieved which do not include the given node reference.
*
* @param user The username of the user to use.
* @param password The password of the user.
* @param itemNodeRef
* @param includedInHold
* @param fileOnly
* @return return
*/
public List<HoldEntry> getHolds(String user, String password, final String itemNodeRef,
final Boolean includedInHold, final Boolean fileOnly)
{
final String parameters = (itemNodeRef != null ? "itemNodeRef=" + NODE_REF_WORKSPACE_SPACES_STORE + itemNodeRef : "")
+ (includedInHold != null ? "&includedInHold=" + includedInHold : "")
+ (fileOnly != null ? "&fileOnly=" + fileOnly : "");
final JSONArray holdEntries = doGetRequest(user, password,
MessageFormat.format(GET_RM_HOLDS, "{0}", parameters)).getJSONObject("data").getJSONArray("holds");
return PojoUtility.jsonToObject(holdEntries, HoldEntry.class);
}
}

View File

@@ -31,7 +31,6 @@ import static org.alfresco.rest.core.v0.APIUtils.ISO_INSTANT_FORMATTER;
import static org.apache.http.HttpStatus.SC_OK;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertNotNull;
import static org.testng.AssertJUnit.assertTrue;
import static org.testng.AssertJUnit.fail;
@@ -48,7 +47,6 @@ import org.alfresco.dataprep.AlfrescoHttpClientFactory;
import org.alfresco.dataprep.UserService;
import org.alfresco.rest.core.v0.BaseAPI;
import org.alfresco.rest.core.v0.RMEvents;
import org.alfresco.utility.Utility;
import org.apache.chemistry.opencmis.client.api.CmisObject;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.http.HttpResponse;
@@ -74,8 +72,6 @@ import org.springframework.stereotype.Component;
@Component
public class RMRolesAndActionsAPI extends BaseAPI
{
public static final String HOLDS_CONTAINER = "Holds";
/** The URI to view the configured roles and capabilities. */
private static final String RM_ROLES = "{0}rma/admin/rmroles";
/** The URI for REST requests about a particular configured role. */
@@ -85,9 +81,6 @@ public class RMRolesAndActionsAPI extends BaseAPI
// logger
private static final Logger LOGGER = LoggerFactory.getLogger(RMRolesAndActionsAPI.class);
private static final String MOVE_ACTIONS_API = "action/rm-move-to/site/rm/documentLibrary/{0}";
private static final String CREATE_HOLDS_API = "{0}type/rma:hold/formprocessor";
/** The URI to add items to hold.*/
private static final String RM_HOLDS_API = "{0}rma/holds";
/** http client factory */
@Autowired
@@ -439,75 +432,6 @@ public class RMRolesAndActionsAPI extends BaseAPI
contentService.getFolderObject(contentService.getCMISSession(username, password), siteId, containerName).getChildren().getHasMoreItems());
}
/**
* Deletes hold
*
* @param username user's username
* @param password its password
* @param holdName the hold name
* @throws AssertionError if the deletion was unsuccessful.
*/
public void deleteHold(String username, String password, String holdName)
{
deleteItem(username, password, String.format("/%s/%s", HOLDS_CONTAINER, holdName));
}
/**
* Util method to create a hold
*
* @param user the user creating the category
* @param password the user's password
* @param holdName the hold name
* @param reason hold reason
* @param description hold description
* @return The HTTP response (or null if no POST call was needed).
*/
public HttpResponse createHold(String user, String password, String holdName, String reason, String description)
{
// if the hold already exists don't try to create it again
final String fullHoldPath = Utility.buildPath(getFilePlanPath(), HOLDS_CONTAINER) + holdName;
final CmisObject hold = getObjectByPath(user, password, fullHoldPath);
if (hold != null)
{
return null;
}
// retrieve the Holds container nodeRef
final String parentNodeRef = getItemNodeRef(user, password, "/" + HOLDS_CONTAINER);
final JSONObject requestParams = new JSONObject();
requestParams.put("alf_destination", getNodeRefSpacesStore() + parentNodeRef);
requestParams.put("prop_cm_name", holdName);
requestParams.put("prop_cm_description", description);
requestParams.put("prop_rma_holdReason", reason);
// Make the POST request and throw an assertion error if it fails.
final HttpResponse httpResponse = doPostJsonRequest(user, password, SC_OK, requestParams, CREATE_HOLDS_API);
assertNotNull("Expected object to have been created at " + fullHoldPath,
getObjectByPath(user, password, fullHoldPath));
return httpResponse;
}
/**
* Adds item (record/ record folder) to the hold
*
* @param user the user who adds the item to the hold
* @param password the user's password
* @param itemNodeRef the nodeRef of the item to be added to hold
* @param holdName the hold name
* @return The HTTP response
*/
public HttpResponse addItemToHold(String user, String password, String itemNodeRef, String holdName)
{
final JSONArray nodeRefs = new JSONArray().put(getNodeRefSpacesStore() + itemNodeRef);
final String holdNodeRef = getItemNodeRef(user, password, String.format("/%s/%s", HOLDS_CONTAINER, holdName));
final JSONArray holds = new JSONArray().put(getNodeRefSpacesStore() + holdNodeRef);
final JSONObject requestParams = new JSONObject();
requestParams.put("nodeRefs", nodeRefs);
requestParams.put("holds", holds);
return doPostJsonRequest(user, password, SC_OK, requestParams, RM_HOLDS_API);
}
/**
* Updates metadata, can be used on records, folders and categories
*

View File

@@ -147,13 +147,26 @@ public class RoleService
*/
public UserModel createUserWithRMRoleAndCategoryPermission(String userRole, RecordCategory recordCategory,
UserPermissions userPermission)
{
return createUserWithRMRoleAndRMNodePermission(userRole, recordCategory.getId(),userPermission);
}
/**
* Helper method to create a test user with rm role and permissions on the node ref
*
* @param userRole the rm role
* @param userPermission the permissions over the record category
* @param componentId the component id to grant rm permission
* @return the created user model
*/
public UserModel createUserWithRMRoleAndRMNodePermission(String userRole, String componentId,
UserPermissions userPermission)
{
final UserModel rmUser = createUserWithRMRole(userRole);
getRestAPIFactory().getRMUserAPI().addUserPermission(recordCategory.getId(), rmUser, userPermission);
getRestAPIFactory().getRMUserAPI().addUserPermission(componentId, rmUser, userPermission);
getRestAPIFactory().getRmRestWrapper().assertStatusCodeIs(OK);
return rmUser;
}
/**
* Helper method to create a test user with rm role and permissions over the recordCategory and collaborator role
* in collaboration site
@@ -167,9 +180,28 @@ public class RoleService
public UserModel createCollaboratorWithRMRoleAndPermission(SiteModel siteModel, RecordCategory recordCategory,
UserRoles userRole, UserPermissions userPermission)
{
final UserModel rmUser = createUserWithRMRoleAndCategoryPermission(userRole.roleId, recordCategory,
return createUserWithSiteRoleRMRoleAndPermission(siteModel, UserRole.SiteCollaborator, recordCategory.getId(), userRole,
userPermission);
getDataUser().addUserToSite(rmUser, siteModel, UserRole.SiteCollaborator);
}
/**
* Helper method to create a test user with a rm role and permissions over a rm component and a role
* in collaboration site
*
* @param siteModel collaboration site
* @param recordCategory the category on which permission should be given
* @param userRole the rm role
* @param userPermission the permissions over the recordCategory
* @return the created user model
*/
public UserModel createUserWithSiteRoleRMRoleAndPermission(SiteModel siteModel, UserRole userSiteRoles,
String rmNodeId, UserRoles userRole,
UserPermissions userPermission)
{
final UserModel rmUser = createUserWithRMRoleAndRMNodePermission(userRole.roleId, rmNodeId,
userPermission);
getDataUser().addUserToSite(rmUser, siteModel, userSiteRoles);
return rmUser;
}
}

View File

@@ -97,4 +97,19 @@ public interface TestData
*/
public static final Set<String> RM_ROLES = newHashSet(ROLE_RM_ADMIN.roleId, ROLE_RM_MANAGER.roleId,
ROLE_RM_POWER_USER.roleId, ROLE_RM_SECURITY_OFFICER.roleId, ROLE_RM_USER.roleId);
/**
* The default hold description
*/
String HOLD_DESCRIPTION = "Generalized hold case for tests";
/**
* The default hold reason
*/
String HOLD_REASON = "Active content to be reviewed for the CASE McDermott, FINRA ";
/**
* Frozen aspect
*/
String FROZEN_ASPECT = "rma:frozen";
}

View File

@@ -34,7 +34,7 @@ import static org.alfresco.rest.rm.community.model.user.UserPermissions.PERMISSI
import static org.alfresco.rest.rm.community.model.user.UserPermissions.PERMISSION_READ_RECORDS;
import static org.alfresco.rest.rm.community.model.user.UserRoles.ROLE_RM_POWER_USER;
import static org.alfresco.rest.rm.community.requests.gscore.api.FilesAPI.PARENT_ID_PARAM;
import static org.alfresco.rest.v0.RMRolesAndActionsAPI.HOLDS_CONTAINER;
import static org.alfresco.rest.v0.HoldsAPI.HOLDS_CONTAINER;
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;
@@ -57,6 +57,7 @@ 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.util.DockerHelper;
import org.alfresco.rest.v0.HoldsAPI;
import org.alfresco.rest.v0.RMRolesAndActionsAPI;
import org.alfresco.rest.v0.service.RoleService;
import org.alfresco.test.AlfrescoTest;
@@ -106,6 +107,9 @@ public class DeclareAndFileDocumentAsRecordTests extends BaseRMRestTest
@Autowired
private RMRolesAndActionsAPI rmRolesAndActionsAPI;
@Autowired
private HoldsAPI holdsAPI;
/**
* Invalid destination paths where in-place records can't be filed
*/
@@ -407,10 +411,10 @@ public class DeclareAndFileDocumentAsRecordTests extends BaseRMRestTest
public void declareAndFileToHeldRecordFolderUsingFilesAPI() throws Exception
{
RecordCategoryChild heldRecordFolder = createFolder(recordCategory.getId(), getRandomName("heldRecordFolder"));
rmRolesAndActionsAPI.createHold(getAdminUser().getUsername(), getAdminUser().getPassword(), HOLD_NAME,
"hold reason", "hold description");
rmRolesAndActionsAPI.addItemToHold(getAdminUser().getUsername(), getAdminUser().getPassword(),
heldRecordFolder.getId(), HOLD_NAME);
holdsAPI.createHold(getAdminUser().getUsername(), getAdminUser().getPassword(), HOLD_NAME, "hold reason",
"hold description");
holdsAPI.addItemToHold(getAdminUser().getUsername(), getAdminUser().getPassword(), heldRecordFolder.getId(),
HOLD_NAME);
STEP("Declare document as record with a frozen location parameter value");
getRestAPIFactory().getFilesAPI()

View File

@@ -0,0 +1,355 @@
/*-
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.rm.community.hold;
import static org.alfresco.rest.rm.community.base.TestData.FROZEN_ASPECT;
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.model.fileplancomponents.FilePlanComponentAlias.FILE_PLAN_ALIAS;
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.TRANSFERS_ALIAS;
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.model.user.UserPermissions.PERMISSION_FILING;
import static org.alfresco.rest.rm.community.model.user.UserPermissions.PERMISSION_READ_RECORDS;
import static org.alfresco.rest.rm.community.model.user.UserRoles.ROLE_RM_MANAGER;
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
import static org.alfresco.rest.rm.community.utils.CoreUtil.toContentModel;
import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.IMAGE_FILE;
import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.createElectronicRecordModel;
import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.createNonElectronicRecordModel;
import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.getFile;
import static org.alfresco.utility.data.RandomData.getRandomAlphanumeric;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.apache.commons.httpclient.HttpStatus.SC_BAD_REQUEST;
import static org.apache.commons.httpclient.HttpStatus.SC_INTERNAL_SERVER_ERROR;
import static org.springframework.http.HttpStatus.CREATED;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.AssertJUnit.assertFalse;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.alfresco.dataprep.CMISUtil;
import org.alfresco.rest.model.RestNodeModel;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.hold.HoldEntry;
import org.alfresco.rest.rm.community.model.record.Record;
import org.alfresco.rest.rm.community.model.user.UserRoles;
import org.alfresco.rest.rm.community.requests.gscore.api.RecordFolderAPI;
import org.alfresco.rest.v0.HoldsAPI;
import org.alfresco.rest.v0.service.RoleService;
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.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/**
* API tests for adding content to holds
*
* @author Rodica Sutu
* @since 3.2
*/
@AlfrescoTest (jira = "RM-6874")
public class AddContentToHoldsTests extends BaseRMRestTest
{
private static final String HOLD = "HOLD" + generateTestPrefix(AddContentToHoldsTests.class);
private static final String ACCESS_DENIED_ERROR_MESSAGE = "Access Denied. You do not have the appropriate " +
"permissions to perform this operation.";
private static final String INVALID_TYPE_ERROR_MESSAGE = "Items added to a hold must be either a record, a " +
"record folder or active content.";
private SiteModel testSite;
private String holdNodeRef;
private FileModel document, contentToAddToHold, contentAddToHoldNoPermission;
private UserModel userAddHoldPermission;
private List<UserModel> users = new ArrayList<>();
@Autowired
private HoldsAPI holdsAPI;
@Autowired
private RoleService roleService;
@BeforeClass (alwaysRun = true)
public void preconditionForAddContentToHold() throws Exception
{
STEP("Create a hold.");
holdNodeRef = holdsAPI.createHoldAndGetNodeRef(getAdminUser().getUsername(), getAdminUser().getUsername(),
HOLD, HOLD_REASON, HOLD_DESCRIPTION);
STEP("Create test files.");
testSite = dataSite.usingAdmin().createPublicRandomSite();
document = dataContent.usingSite(testSite)
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
contentToAddToHold = dataContent.usingSite(testSite)
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
contentAddToHoldNoPermission = dataContent.usingSite(testSite)
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
STEP("Add the content to the hold.");
holdsAPI.addItemToHold(getAdminUser().getUsername(), getAdminUser().getPassword(), document
.getNodeRefWithoutVersion(), HOLD);
STEP("Create users");
userAddHoldPermission = roleService.createUserWithSiteRoleRMRoleAndPermission(testSite,
UserRole.SiteCollaborator, holdNodeRef, UserRoles.ROLE_RM_MANAGER, PERMISSION_FILING);
users.add(userAddHoldPermission);
}
/**
* Given a hold that contains at least one active content
* When I use the existing REST API to retrieve the contents of the hold
* Then I should see all the active content on hold
*/
@Test
public void retrieveTheContentOfTheHoldUsingV1API() throws Exception
{
STEP("Retrieve the list of children from the hold and collect the entries that have the name of the active " +
"content held");
List<RestNodeModel> documentsHeld = restClient.authenticateUser(getAdminUser()).withCoreAPI()
.usingNode(toContentModel(holdNodeRef))
.listChildren().getEntries().stream()
.filter(child -> child.onModel().getName().contains(document
.getName()))
.collect(Collectors.toList());
STEP("Check the list of active content");
assertEquals(documentsHeld.size(), 1, "The active content is not retrive when getting the children from the " +
"hold folder");
assertEquals(documentsHeld.get(0).onModel().getName(), document.getName());
}
/**
* Given a hold that contains at least one active content
* When I use the existing REST API to retrieve the holds the content is added
* Then the hold where the content held is returned
*/
@Test
public void retrieveTheHoldWhereTheContentIsAdded()
{
List<HoldEntry> holdEntries = holdsAPI.getHolds(getAdminUser().getUsername(), getAdminUser().getPassword(),
document.getNodeRefWithoutVersion(), true, null);
assertTrue(holdEntries.stream().anyMatch(holdEntry -> holdEntry.getName().contains(HOLD)), "Could not find " +
"hold with name " + HOLD);
}
/**
* Valid nodes to be added to hold
*/
@DataProvider (name = "validNodesForAddToHold")
public Object[][] getValidNodesForAddToHold() throws Exception
{
//create electronic and nonElectronic record in record folder
String recordFolderId = createCategoryFolderInFilePlan().getId();
RecordFolderAPI recordFolderAPI = getRestAPIFactory().getRecordFolderAPI();
Record electronicRecord = recordFolderAPI.createRecord(createElectronicRecordModel(), recordFolderId, getFile
(IMAGE_FILE));
assertStatusCode(CREATED);
Record nonElectronicRecord = recordFolderAPI.createRecord(createNonElectronicRecordModel(), recordFolderId);
assertStatusCode(CREATED);
getRestAPIFactory().getRMUserAPI().addUserPermission(recordFolderId, userAddHoldPermission, PERMISSION_FILING);
String folderToHold = createCategoryFolderInFilePlan().getId();
getRestAPIFactory().getRMUserAPI().addUserPermission(folderToHold, userAddHoldPermission, PERMISSION_FILING);
return new String[][]
{ // record folder
{ folderToHold },
//electronic record
{ electronicRecord.getId() },
// non electronic record
{ nonElectronicRecord.getId() },
// document from collaboration site
{ contentToAddToHold.getNodeRefWithoutVersion() },
};
}
/**
* Given active content not on hold
* And a hold
* And file permission on the hold
* And the appropriate capability to add to hold
* When I use the existing REST API to add the active content to the hold
* Then the active content is added to the hold
* And the active content is frozen
*
* @throws Exception
*/
@Test (dataProvider = "validNodesForAddToHold")
public void addValidNodesToHoldWithAllowedUser(String nodeId) throws Exception
{
STEP("Add the content to the hold with user with permission.");
holdsAPI.addItemToHold(userAddHoldPermission.getUsername(), userAddHoldPermission.getPassword(),
nodeId, HOLD);
STEP("Check active content is frozen.");
RestNodeModel heldActiveContent = restClient.authenticateUser(userAddHoldPermission)
.withCoreAPI().usingNode(toContentModel(nodeId)).getNode();
assertTrue(heldActiveContent.getAspectNames().contains(FROZEN_ASPECT));
}
/**
* Data provider with user without correct permission to add to hold and the node ref to be added to hold
* @return object with user model and the node ref to be added to hold
*/
@DataProvider (name = "userWithoutPermissionForAddToHold")
public Object[][] getUserWithoutPermissionForAddToHold() throws Exception
{
//create electronic and nonElectronic record in record folder
String recordFolderId = createCategoryFolderInFilePlan().getId();
UserModel user = roleService.createUserWithRMRoleAndRMNodePermission(ROLE_RM_MANAGER.roleId, recordFolderId,
PERMISSION_READ_RECORDS);
getRestAPIFactory().getRMUserAPI().addUserPermission(holdNodeRef, user, PERMISSION_FILING);
return new Object[][]
{ // user without write permission on the content
{
roleService.createUserWithSiteRoleRMRoleAndPermission(testSite, UserRole.SiteConsumer,
holdNodeRef, UserRoles.ROLE_RM_MANAGER, PERMISSION_FILING),
contentAddToHoldNoPermission.getNodeRefWithoutVersion()
},
// user with write permission on the content and without filling permission on a hold
{
roleService.createUserWithSiteRoleRMRoleAndPermission(testSite, UserRole
.SiteCollaborator,
holdNodeRef, UserRoles.ROLE_RM_MANAGER, PERMISSION_READ_RECORDS),
contentAddToHoldNoPermission.getNodeRefWithoutVersion()
},
// user with write permission on the content, filling permission on a hold without add to
// hold capability
{
roleService.createUserWithSiteRoleRMRoleAndPermission(testSite, UserRole
.SiteCollaborator,
holdNodeRef, UserRoles.ROLE_RM_POWER_USER, PERMISSION_READ_RECORDS),
contentAddToHoldNoPermission.getNodeRefWithoutVersion()
},
//user without write permission on RM record folder
{
user, recordFolderId
},
};
}
/**
* Given active content not on hold
* And a hold
* And user without right permission to add to hold
* When I use the existing REST API to add the active content to the hold
* Then the active content is not added to the hold
* And the active content is frozen
*
* @throws Exception
*/
@Test (dataProvider = "userWithoutPermissionForAddToHold")
public void addContentToHoldWithUserWithoutHoldPermission(UserModel userModel, String nodeToBeAddedToHold) throws
Exception
{
users.add(userModel);
STEP("Add the content to the hold with user with permission.");
String response = holdsAPI.addToHoldAndGetMessage(userModel.getUsername(),
userModel.getPassword(), SC_INTERNAL_SERVER_ERROR, nodeToBeAddedToHold, HOLD);
assertTrue(response.contains(ACCESS_DENIED_ERROR_MESSAGE));
STEP("Check active content is not frozen.");
RestNodeModel heldActiveContent = restClient.authenticateUser(getAdminUser())
.withCoreAPI().usingNode(toContentModel(nodeToBeAddedToHold))
.getNode();
assertFalse(heldActiveContent.getAspectNames().contains(FROZEN_ASPECT));
}
/**
* Data provider withh invalid item types that can be added to a hold
*/
@DataProvider (name = "invalidNodesForAddToHold")
public Object[][] getInvalidNodesForAddToHold() throws Exception
{
return new Object[][]
{ // file plan node id
{ getFilePlan(FILE_PLAN_ALIAS).getId(), SC_BAD_REQUEST, INVALID_TYPE_ERROR_MESSAGE },
//transfer container
{ getTransferContainer(TRANSFERS_ALIAS).getId(), SC_BAD_REQUEST, INVALID_TYPE_ERROR_MESSAGE },
// an arbitrary record category
{ createRootCategory(getRandomAlphanumeric()).getId(), SC_INTERNAL_SERVER_ERROR, ACCESS_DENIED_ERROR_MESSAGE },
// unfiled records root
{ getUnfiledContainer(UNFILED_RECORDS_CONTAINER_ALIAS).getId(), SC_BAD_REQUEST, INVALID_TYPE_ERROR_MESSAGE },
// an arbitrary unfiled records folder
{ createUnfiledContainerChild(UNFILED_RECORDS_CONTAINER_ALIAS, "Unfiled Folder " +
getRandomAlphanumeric(), UNFILED_RECORD_FOLDER_TYPE).getId(), SC_BAD_REQUEST, INVALID_TYPE_ERROR_MESSAGE },
//folder,
{ dataContent.usingAdmin().usingSite(testSite).createFolder().getNodeRef(), SC_BAD_REQUEST, INVALID_TYPE_ERROR_MESSAGE }
};
}
/**
* unfiled container
* unfiled folder
* folder
* category
* fileplan
*
* @throws Exception
*/
@Test (dataProvider = "invalidNodesForAddToHold")
public void addInvalidNodesToHold(String itemNodeRef, int responseCode, String errorMessage) throws Exception
{
STEP("Add the item to the hold ");
String responseErrorMessage = holdsAPI.addToHoldAndGetMessage(userAddHoldPermission.getUsername(),
userAddHoldPermission.getPassword(), responseCode, itemNodeRef, HOLD);
assertTrue(responseErrorMessage.contains(errorMessage),
"Actual message " + responseErrorMessage);
STEP("Check active content is not frozen.");
RestNodeModel heldActiveContent = restClient.authenticateUser(getAdminUser())
.withCoreAPI().usingNode(toContentModel(itemNodeRef)).getNode();
assertFalse(heldActiveContent.getAspectNames().contains(FROZEN_ASPECT));
}
@AfterClass (alwaysRun = true)
public void cleanUpAddContentToHold() throws Exception
{
holdsAPI.deleteHold(getAdminUser().getUsername(), getAdminUser().getPassword(), HOLD);
dataSite.usingAdmin().deleteSite(testSite);
users.forEach(user -> getDataUser().usingAdmin().deleteUser(user));
}
}

View File

@@ -0,0 +1,188 @@
/*-
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.rm.community.hold;
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 static org.alfresco.rest.rm.community.utils.CoreUtil.createBodyForMoveCopy;
import static org.alfresco.utility.report.log.Step.STEP;
import javax.json.Json;
import javax.json.JsonObject;
import java.io.File;
import org.alfresco.dataprep.CMISUtil;
import org.alfresco.rest.core.JsonBodyGenerator;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.v0.HoldsAPI;
import org.alfresco.utility.Utility;
import org.alfresco.utility.model.FileModel;
import org.alfresco.utility.model.FolderModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
* API tests to check actions on frozen content
*
* @author Rodica Sutu
* @since 3.2
*/
public class PreventActionsOnFrozenContentTests extends BaseRMRestTest
{
private static final String HOLD_ONE = "HOLD" + generateTestPrefix(PreventActionsOnFrozenContentTests.class);
private static String holdNodeRef;
private static FileModel contentHeld;
private static File updatedFile;
private static FolderModel folderModel;
@Autowired
private HoldsAPI holdsAPI;
@BeforeClass (alwaysRun = true)
public void preconditionForRemoveContentFromHold() throws Exception
{
STEP("Create a hold.");
holdNodeRef = holdsAPI.createHoldAndGetNodeRef(getAdminUser().getUsername(), getAdminUser().getUsername(),
HOLD_ONE, HOLD_REASON, HOLD_DESCRIPTION);
STEP("Create a test file and add to hold");
testSite = dataSite.usingAdmin().createPublicRandomSite();
contentHeld = dataContent.usingAdmin().usingSite(testSite)
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
STEP("Add the content to the hold.");
holdsAPI.addItemToHold(getAdminUser().getUsername(), getAdminUser().getPassword(), contentHeld
.getNodeRefWithoutVersion(), HOLD_ONE);
STEP("Get a file resource.");
updatedFile = Utility.getResourceTestDataFile("SampleTextFile_10kb.txt");
STEP("Create a folder withing the test site .");
folderModel = dataContent.usingAdmin().usingSite(testSite)
.createFolder();
}
/**
* Given active content on hold
* When I try to edit the properties
* Or perform an action that edits the properties
* Then I am not successful
*
*/
@Test
public void editPropertiesForContentHeld() throws Exception
{
STEP("Update name property of the held content");
JsonObject nameUpdated = Json.createObjectBuilder().add("name","HeldNameUpdated").build();
restClient.authenticateUser(getAdminUser()).withCoreAPI().usingNode(contentHeld).updateNode(nameUpdated.toString());
STEP("Check the request failed.");
restClient.assertStatusCodeIs(HttpStatus.FORBIDDEN);
restClient.assertLastError().containsSummary("Frozen nodes can not be updated.");
}
/*
* Given active content on hold
* When I try to update the content
* Then I am not successful
*/
@Test
public void updateContentForFrozenFile() throws Exception
{
STEP("Update content of the held file");
restClient.authenticateUser(getAdminUser()).withCoreAPI().usingNode(contentHeld).updateNodeContent(updatedFile);
STEP("Check the request failed.");
restClient.assertStatusCodeIs(HttpStatus.INTERNAL_SERVER_ERROR);
restClient.assertLastError().containsSummary("Frozen nodes can not be updated.");
}
/*
* Given active content on hold
* When I try to delete the content
* Then I am not successful
*/
@Test
public void deleteFrozenFile() throws Exception
{
STEP("Delete frozen file");
restClient.authenticateUser(getAdminUser()).withCoreAPI().usingNode(contentHeld).deleteNode(contentHeld.getNodeRefWithoutVersion());
STEP("Check the request failed.");
restClient.assertStatusCodeIs(HttpStatus.FORBIDDEN);
restClient.assertLastError().containsSummary("Frozen nodes can not be updated.");
}
/**
* Given active content on hold
* When I try to copy the content
* Then I am not successful
*/
@Test
public void copyFrozenFile() throws Exception
{
STEP("Copy frozen file");
String postBody = JsonBodyGenerator.keyValueJson("targetParentId",folderModel.getNodeRef());
getRestAPIFactory().getNodeAPI(contentHeld).copyNode(postBody);
STEP("Check the request failed.");
assertStatusCode(HttpStatus.FORBIDDEN);
restClient.assertLastError().containsSummary("Frozen nodes can not be copied.");
}
/**
* Given active content on hold
* When I try to move the content
* Then I am not successful
*
*/
@Test
public void moveFrozenFile() throws Exception
{
STEP("Move frozen file");
getRestAPIFactory().getNodeAPI(contentHeld).move(createBodyForMoveCopy(folderModel.getNodeRef()));
STEP("Check the request failed.");
restClient.assertStatusCodeIs(HttpStatus.FORBIDDEN);
restClient.assertLastError().containsSummary("Frozen nodes can not be copied.");
}
@AfterClass (alwaysRun = true)
public void cleanUpAddContentToHold() throws Exception
{
holdsAPI.deleteHold(getAdminUser().getUsername(), getAdminUser().getPassword(), HOLD_ONE);
dataSite.usingAdmin().deleteSite(testSite);
}
}

View File

@@ -0,0 +1,284 @@
/*-
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.rm.community.hold;
import static org.alfresco.rest.rm.community.base.TestData.FROZEN_ASPECT;
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.model.user.UserPermissions.PERMISSION_FILING;
import static org.alfresco.rest.rm.community.model.user.UserPermissions.PERMISSION_READ_RECORDS;
import static org.alfresco.rest.rm.community.model.user.UserRoles.ROLE_RM_MANAGER;
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
import static org.alfresco.rest.rm.community.utils.CoreUtil.toContentModel;
import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.IMAGE_FILE;
import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.createElectronicRecordModel;
import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.createNonElectronicRecordModel;
import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.getFile;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.apache.commons.httpclient.HttpStatus.SC_INTERNAL_SERVER_ERROR;
import static org.springframework.http.HttpStatus.CREATED;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import java.util.Arrays;
import java.util.List;
import org.alfresco.dataprep.CMISUtil;
import org.alfresco.rest.model.RestNodeModel;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.hold.HoldEntry;
import org.alfresco.rest.rm.community.model.record.Record;
import org.alfresco.rest.rm.community.model.user.UserRoles;
import org.alfresco.rest.rm.community.requests.gscore.api.RecordFolderAPI;
import org.alfresco.rest.v0.HoldsAPI;
import org.alfresco.rest.v0.service.RoleService;
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.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/**
* API tests for removing content from holds
*
* @author Rodica Sutu
* @since 3.2
*/
@AlfrescoTest (jira = "RM-6874, RM-6873")
public class RemoveContentFromHoldsTests extends BaseRMRestTest
{
private static final String HOLD_ONE = "HOLD_ONE" + generateTestPrefix(RemoveContentFromHoldsTests.class);
private static final String HOLD_TWO = "HOLD_TWO" + generateTestPrefix(RemoveContentFromHoldsTests.class);
private static final String ACCESS_DENIED_ERROR_MESSAGE = "Access Denied. You do not have the appropriate " +
"permissions to perform this operation.";
private SiteModel testSite;
private String holdNodeRefOne;
private FileModel contentHeld, contentAddToManyHolds;
@Autowired
private HoldsAPI holdsAPI;
@Autowired
private RoleService roleService;
@BeforeClass (alwaysRun = true)
public void preconditionForRemoveContentFromHold() throws Exception
{
STEP("Create two holds.");
holdNodeRefOne = holdsAPI.createHoldAndGetNodeRef(getAdminUser().getUsername(), getAdminUser().getUsername(),
HOLD_ONE, HOLD_REASON, HOLD_DESCRIPTION);
String holdNodeRefTwo = holdsAPI.createHoldAndGetNodeRef(getAdminUser().getUsername(), getAdminUser()
.getUsername(), HOLD_TWO, HOLD_REASON, HOLD_DESCRIPTION);
STEP("Create test files and add them to hold");
testSite = dataSite.usingAdmin().createPublicRandomSite();
contentHeld = dataContent.usingSite(testSite)
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
contentAddToManyHolds = dataContent.usingSite(testSite)
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
STEP("Add the content to the hold.");
holdsAPI.addItemToHold(getAdminUser().getUsername(), getAdminUser().getPassword(), contentHeld
.getNodeRefWithoutVersion(), HOLD_ONE);
holdsAPI.addItemToHold(getAdminUser().getUsername(), getAdminUser().getPassword(), contentAddToManyHolds
.getNodeRefWithoutVersion(), String.format("%s,%s", HOLD_ONE, HOLD_TWO));
}
/**
* Valid nodes to be removed from hold
*/
@DataProvider (name = "validNodesToRemoveFromHold")
public Object[][] getValidNodesToRemoveFromHold() throws Exception
{
//create electronic and nonElectronic record in record folder
String recordFolderId = createCategoryFolderInFilePlan().getId();
RecordFolderAPI recordFolderAPI = getRestAPIFactory().getRecordFolderAPI();
Record electronicRecord = recordFolderAPI.createRecord(createElectronicRecordModel(), recordFolderId, getFile
(IMAGE_FILE));
assertStatusCode(CREATED);
Record nonElectronicRecord = recordFolderAPI.createRecord(createNonElectronicRecordModel(), recordFolderId);
assertStatusCode(CREATED);
String folderToHeld = createCategoryFolderInFilePlan().getId();
Arrays.asList(electronicRecord.getId(), nonElectronicRecord.getId(), folderToHeld).forEach(item ->
holdsAPI.addItemToHold(getAdminUser().getUsername(), getAdminUser().getPassword(), item, HOLD_ONE));
return new String[][]
{ // record folder
{ folderToHeld },
//electronic record
{ electronicRecord.getId() },
// non electronic record
{ nonElectronicRecord.getId() },
// document from collaboration site
{ contentHeld.getNodeRefWithoutVersion() },
};
}
/**
* Given active content that is held
* And the corresponding hold
* When I use the existing REST API to remove the active content from the hold
* Then the active content is removed from the hold
* And is no longer frozen
*/
@Test(dataProvider = "validNodesToRemoveFromHold")
public void removeContentFromHold(String nodeId) throws Exception
{
STEP("Remove content from hold");
holdsAPI.removeItemFromHold(getAdminUser().getUsername(), getAdminUser().getPassword(), nodeId, HOLD_ONE);
STEP("Check the content is not held");
RestNodeModel heldActiveContent = restClient.authenticateUser(getAdminUser())
.withCoreAPI().usingNode(toContentModel(nodeId)).getNode();
assertFalse(heldActiveContent.getAspectNames().contains(FROZEN_ASPECT));
STEP("Check node is not in any hold");
List<HoldEntry> holdEntries = holdsAPI.getHolds(getAdminUser().getUsername(), getAdminUser().getPassword(),
nodeId, true, null);
assertTrue(holdEntries.isEmpty(), "Content held is still added to a hold.");
}
/**
* Given active content that is held on many holds
* When I use the existing REST API to remove the active content from one hold
* Then the active content is removed from the specific hold
* And is frozen
* And in the other holds
*/
@Test
public void removeContentAddedToManyHolds() throws Exception
{
STEP("Remove content from hold");
holdsAPI.removeItemFromHold(getAdminUser().getUsername(), getAdminUser().getPassword(), contentAddToManyHolds
.getNodeRefWithoutVersion(), HOLD_ONE);
STEP("Check the content is held");
RestNodeModel heldActiveContent = restClient.authenticateUser(getAdminUser())
.withCoreAPI().usingNode(contentAddToManyHolds).getNode();
assertTrue(heldActiveContent.getAspectNames().contains(FROZEN_ASPECT));
STEP("Check node is not in any hold");
List<HoldEntry> holdEntries = holdsAPI.getHolds(getAdminUser().getUsername(), getAdminUser().getPassword(),
contentAddToManyHolds.getNodeRefWithoutVersion(), true, null);
assertFalse(holdEntries.isEmpty(), "Content held is not held after removing from one hold.");
assertTrue(holdEntries.stream().anyMatch(holdEntry -> holdEntry.getName().contains(HOLD_TWO)), "Content held is " +
"not held after removing from one hold.");
}
/**
*
* @return
* @throws Exception
*/
@DataProvider (name = "userWithoutPermissionForRemoveFromHold")
public Object[][] getUserWithoutPermissionForAddToHold() throws Exception
{
//create electronic and nonElectronic record in record folder
String recordFolderId = createCategoryFolderInFilePlan().getId();
UserModel user = roleService.createUserWithRMRoleAndRMNodePermission(ROLE_RM_MANAGER.roleId, recordFolderId,
PERMISSION_READ_RECORDS);
getRestAPIFactory().getRMUserAPI().addUserPermission(holdNodeRefOne, user, PERMISSION_FILING);
//create files that will be removed from hold
FileModel contentNoPermission = dataContent.usingSite(testSite).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
FileModel contentNoHoldPerm = dataContent.usingSite(testSite).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
FileModel contentNoHoldCap = dataContent.usingSite(testSite).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
//add files to hold
Arrays.asList(recordFolderId, contentNoHoldCap.getNodeRefWithoutVersion(),
contentNoHoldPerm.getNodeRefWithoutVersion(), contentNoPermission.getNodeRefWithoutVersion()).forEach(
node -> holdsAPI.addItemToHold(getAdminUser().getUsername(), getAdminUser().getPassword(), node,
HOLD_ONE)
);
return new Object[][]
{
// user without write permission on the content
{
roleService.createUserWithSiteRoleRMRoleAndPermission(testSite, UserRole.SiteConsumer,
holdNodeRefOne, UserRoles.ROLE_RM_MANAGER, PERMISSION_FILING),
contentNoPermission.getNodeRefWithoutVersion()
},
// user with write permission on the content and without filling permission on a hold
{
roleService.createUserWithSiteRoleRMRoleAndPermission(testSite, UserRole.SiteCollaborator,
holdNodeRefOne, UserRoles.ROLE_RM_MANAGER, PERMISSION_READ_RECORDS),
contentNoHoldPerm.getNodeRefWithoutVersion()
},
// user with write permission on the content, filling permission on a hold without remove from
// hold capability
{
roleService.createUserWithSiteRoleRMRoleAndPermission(testSite, UserRole
.SiteCollaborator,
holdNodeRefOne, UserRoles.ROLE_RM_POWER_USER, PERMISSION_READ_RECORDS),
contentNoHoldCap.getNodeRefWithoutVersion()
},
//user without write permission on RM record folder
{
user, recordFolderId
},
};
}
/**
* Given active content on hold in a single hold location
* And the user does not have sufficient permissions or capabilities to remove the active content from the hold
* When the user tries to remove the active content from the hold
* Then they are unsuccessful
* @throws Exception
*/
@Test (dataProvider = "userWithoutPermissionForRemoveFromHold")
public void removeFromHoldWithUserWithoutPermission(UserModel userModel, String nodeIdToBeRemoved) throws Exception
{
STEP("Remove content from hold with user without right permission or capability");
String responseNoHoldPermission = holdsAPI.removeFromHoldAndGetMessage(userModel.getUsername(),
userModel.getPassword(), SC_INTERNAL_SERVER_ERROR, nodeIdToBeRemoved, HOLD_ONE);
assertTrue(responseNoHoldPermission.contains(ACCESS_DENIED_ERROR_MESSAGE));
STEP("Check active content is frozen.");
RestNodeModel heldActiveContent = restClient.authenticateUser(getAdminUser())
.withCoreAPI().usingNode(toContentModel(nodeIdToBeRemoved))
.getNode();
assertTrue(heldActiveContent.getAspectNames().contains(FROZEN_ASPECT));
}
@AfterClass (alwaysRun = true)
public void cleanUpRemoveContentFromHold() throws Exception
{
holdsAPI.deleteHold(getAdminUser().getUsername(), getAdminUser().getPassword(), HOLD_ONE);
holdsAPI.deleteHold(getAdminUser().getUsername(), getAdminUser().getPassword(), HOLD_TWO);
dataSite.usingAdmin().deleteSite(testSite);
}
}

View File

@@ -0,0 +1,27 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus condimentum sagittis lacus, laoreet luctus ligula laoreet ut. Vestibulum ullamcorper accumsan velit vel vehicula. Proin tempor lacus arcu. Nunc at elit condimentum, semper nisi et, condimentum mi. In venenatis blandit nibh at sollicitudin. Vestibulum dapibus mauris at orci maximus pellentesque. Nullam id elementum ipsum. Suspendisse cursus lobortis viverra. Proin et erat at mauris tincidunt porttitor vitae ac dui.
Donec vulputate lorem tortor, nec fermentum nibh bibendum vel. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent dictum luctus massa, non euismod lacus. Pellentesque condimentum dolor est, ut dapibus lectus luctus ac. Ut sagittis commodo arcu. Integer nisi nulla, facilisis sit amet nulla quis, eleifend suscipit purus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aliquam euismod ultrices lorem, sit amet imperdiet est tincidunt vel. Phasellus dictum justo sit amet ligula varius aliquet auctor et metus. Fusce vitae tortor et nisi pulvinar vestibulum eget in risus. Donec ante ex, placerat a lorem eget, ultricies bibendum purus. Nam sit amet neque non ante laoreet rutrum. Nullam aliquet commodo urna, sed ullamcorper odio feugiat id. Mauris nisi sapien, porttitor in condimentum nec, venenatis eu urna. Pellentesque feugiat diam est, at rhoncus orci porttitor non.
Nulla luctus sem sit amet nisi consequat, id ornare ipsum dignissim. Sed elementum elit nibh, eu condimentum orci viverra quis. Aenean suscipit vitae felis non suscipit. Suspendisse pharetra turpis non eros semper dictum. Etiam tincidunt venenatis venenatis. Praesent eget gravida lorem, ut congue diam. Etiam facilisis elit at porttitor egestas. Praesent consequat, velit non vulputate convallis, ligula diam sagittis urna, in venenatis nisi justo ut mauris. Vestibulum posuere sollicitudin mi, et vulputate nisl fringilla non. Nulla ornare pretium velit a euismod. Nunc sagittis venenatis vestibulum. Nunc sodales libero a est ornare ultricies. Sed sed leo sed orci pellentesque ultrices. Mauris sollicitudin, sem quis placerat ornare, velit arcu convallis ligula, pretium finibus nisl sapien vel sem. Vivamus sit amet tortor id lorem consequat hendrerit. Nullam at dui risus.
Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed feugiat semper velit consequat facilisis. Etiam facilisis justo non iaculis dictum. Fusce turpis neque, pharetra ut odio eu, hendrerit rhoncus lacus. Nunc orci felis, imperdiet vel interdum quis, porta eu ipsum. Pellentesque dictum sem lacinia, auctor dui in, malesuada nunc. Maecenas sit amet mollis eros. Proin fringilla viverra ligula, sollicitudin viverra ante sollicitudin congue. Donec mollis felis eu libero malesuada, et lacinia risus interdum.
Etiam vitae accumsan augue. Ut urna orci, malesuada ut nisi a, condimentum gravida magna. Nulla bibendum ex in vulputate sagittis. Nulla facilisi. Nullam faucibus et metus ac consequat. Quisque tempor eros velit, id mattis nibh aliquet a. Aenean tempor elit ut finibus auctor. Sed at imperdiet mauris. Vestibulum pharetra non lacus sed pulvinar. Sed pellentesque magna a eros volutpat ullamcorper. In hac habitasse platea dictumst. Donec ipsum mi, feugiat in eros sed, varius lacinia turpis. Donec vulputate tincidunt dui ac laoreet. Sed in eros dui. Pellentesque placerat tristique ligula eu finibus. Proin nec faucibus felis, eu commodo ipsum.
Integer eu hendrerit diam, sed consectetur nunc. Aliquam a sem vitae leo fermentum faucibus quis at sem. Etiam blandit, quam quis fermentum varius, ante urna ultricies lectus, vel pellentesque ligula arcu nec elit. Donec placerat ante in enim scelerisque pretium. Donec et rhoncus erat. Aenean tempor nisi vitae augue tincidunt luctus. Nam condimentum dictum ante, et laoreet neque pellentesque id. Curabitur consectetur cursus neque aliquam porta. Ut interdum nunc nec nibh vestibulum, in sagittis metus facilisis. Pellentesque feugiat condimentum metus. Etiam venenatis quam at ante rhoncus vestibulum. Maecenas suscipit congue pellentesque. Vestibulum suscipit scelerisque fermentum. Nulla iaculis risus ac vulputate porttitor.
Mauris nec metus vel dolor blandit faucibus et vel magna. Ut tincidunt ipsum non nunc dapibus, sed blandit mi condimentum. Quisque pharetra interdum quam nec feugiat. Sed pellentesque nulla et turpis blandit interdum. Curabitur at metus vitae augue elementum viverra. Sed mattis lorem non enim fermentum finibus. Sed at dui in magna dignissim accumsan. Proin tincidunt ultricies cursus. Maecenas tincidunt magna at urna faucibus lacinia.
Quisque venenatis justo sit amet tortor condimentum, nec tincidunt tellus viverra. Morbi risus ipsum, consequat convallis malesuada non, fermentum non velit. Nulla facilisis orci eget ligula mattis fermentum. Aliquam vel velit ultricies, sollicitudin nibh eu, congue velit. Donec nulla lorem, euismod id cursus at, sollicitudin et arcu. Proin vitae tincidunt ipsum. Vivamus elementum eleifend justo, placerat interdum nulla rutrum id.
Phasellus fringilla luctus magna, a finibus justo dapibus a. Nam risus felis, rhoncus eget diam sit amet, congue facilisis nibh. Interdum et malesuada fames ac ante ipsum primis in faucibus. Praesent consequat euismod diam, eget volutpat magna convallis at. Mauris placerat pellentesque imperdiet. Nulla porta scelerisque enim, et scelerisque neque bibendum in. Proin eget turpis nisi. Suspendisse ut est a erat egestas eleifend at euismod arcu. Donec aliquet, nisi sed faucibus condimentum, nisi metus dictum eros, nec dignissim justo odio id nulla. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Maecenas sollicitudin, justo id elementum eleifend, justo neque aliquet nibh, finibus malesuada metus erat eget neque. Suspendisse nec auctor orci. Aenean et vestibulum nulla. Nullam hendrerit augue tristique, commodo metus id, sodales lorem. Etiam feugiat dui est, vitae auctor risus convallis non.
Maecenas turpis enim, consectetur eget lectus eu, hendrerit posuere lacus. Praesent efficitur, felis eget dapibus consectetur, nisi massa dignissim enim, nec semper dolor est eu urna. Nullam ut sodales lorem. Aliquam dapibus faucibus diam. Vestibulum vel magna et dolor gravida imperdiet ut sit amet sem. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur elementum metus tincidunt nulla euismod ultricies. Duis elementum nec neque in porttitor. Nulla sagittis lorem elit, et consectetur ante laoreet eu. Maecenas nulla tellus, scelerisque ac erat sed, fermentum dapibus metus. Donec tincidunt fermentum molestie.
Sed consequat mi at maximus faucibus. Pellentesque aliquet tincidunt sapien vel auctor. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Praesent accumsan nunc eget leo aliquam, facilisis hendrerit turpis egestas. Morbi in ultricies mauris, a eleifend turpis. Quisque fringilla massa iaculis risus ultrices, sit amet tincidunt dui varius. Quisque maximus porta tristique. Proin tincidunt, turpis ut tempor pretium, lectus ipsum ullamcorper leo, ac tincidunt felis dui non leo. Aenean porta augue ligula, non consequat ipsum aliquet et. Suspendisse ut suscipit ex. Pellentesque vitae lacinia arcu. Curabitur eget tincidunt nulla, non bibendum metus. Nullam mi ipsum, eleifend vitae tortor pulvinar, facilisis sollicitudin ipsum.
Vestibulum molestie risus lorem, at feugiat lorem congue sed. Phasellus ullamcorper laoreet enim, nec aliquam turpis scelerisque et. Etiam dictum metus in elit aliquam dapibus. Vivamus vel lectus velit. Nam sed purus luctus, commodo dui quis, malesuada dui. Nulla porttitor aliquet elit sit amet viverra. Proin tempor nulla urna, non aliquet metus maximus quis. Aliquam ac lectus nec mi aliquam sagittis. Quisque venenatis quam eget nisl tempor, egestas rutrum eros eleifend. Nullam venenatis commodo velit, non tempor mauris fermentum ut. In a metus quis erat cursus sagittis. Donec congue nisl in viverra egestas.
Vestibulum facilisis ligula magna, eu ornare lectus varius et. Mauris facilisis faucibus quam, quis mollis eros convallis non. Interdum et malesuada fames ac ante ipsum primis in faucibus. Praesent sit amet rutrum erat. Suspendisse potenti. Donec lorem mi, sagittis a fringilla sit amet, sagittis bibendum mauris. In in diam et lorem rutrum eleifend a et felis. Sed ac magna quis enim faucibus dictum. Suspendisse blandit enim eu ex laoreet gravida.
Suspendisse sed semper felis. Etiam mattis magna mi, suscipit ullamcorper tellus euismod sed. Aenean congue scelerisque ligula id sodales. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nunc sem lectus, gravida ac dui non, pharetra posuere leo. Maecenas lacus libero, facilisis et elit vitae, commodo facilisis sem. Vivamus id nisl nulla. Integer at maximus dui. Ut a tincidunt lorem. Vivamus vitae ligula vel lacus cursus condimentum. Phasellus quis mauris lobortis, finibus lorem in, vulputate ex. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed faucibus aliquam metus, quis varius elit porttitor id. Vivamus dignissim sollicitudin scelerisque. Morbi tincidunt, dolor quis vehicula consequat, dui diam condimentum nunc, vitae scelerisque odio libero nec ligula. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;