Merge branch 'feature/RM-7033_AuditHoldTests_no' into 'master'

RM-7033 Audit hold tests

See merge request records-management/records-management!1294
This commit is contained in:
Claudia Agache
2019-11-22 06:17:59 +00:00
15 changed files with 1198 additions and 185 deletions

View File

@@ -103,7 +103,7 @@ public abstract class BaseAPI
*/ */
protected List<String> getPropertyValues(JSONObject result, String propertyName) protected List<String> getPropertyValues(JSONObject result, String propertyName)
{ {
ArrayList<String> results = new ArrayList<String>(); ArrayList<String> results = new ArrayList<>();
try try
{ {
JSONArray items = result.getJSONArray("items"); JSONArray items = result.getJSONArray("items");
@@ -541,7 +541,6 @@ public abstract class BaseAPI
AlfrescoHttpClient client = alfrescoHttpClientFactory.getObject(); AlfrescoHttpClient client = alfrescoHttpClientFactory.getObject();
T request = requestType.newInstance(); T request = requestType.newInstance();
HttpResponse response = null;
JSONObject responseBody = null; JSONObject responseBody = null;
JSONObject returnValues = null; JSONObject returnValues = null;
@@ -555,7 +554,7 @@ public abstract class BaseAPI
} }
LOGGER.info("Sending {} request to {}", requestType.getSimpleName(), requestUrl); LOGGER.info("Sending {} request to {}", requestType.getSimpleName(), requestUrl);
LOGGER.info("Request body: {}", requestParams); LOGGER.info("Request body: {}", requestParams);
response = client.execute(adminUser, adminPassword, request); HttpResponse response = client.execute(adminUser, adminPassword, request);
LOGGER.info("Response: {}", response.getStatusLine()); LOGGER.info("Response: {}", response.getStatusLine());
try try
@@ -587,13 +586,13 @@ public abstract class BaseAPI
case HttpStatus.SC_UNPROCESSABLE_ENTITY: case HttpStatus.SC_UNPROCESSABLE_ENTITY:
if (responseBody != null && responseBody.has(EXCEPTION_KEY)) if (responseBody != null && responseBody.has(EXCEPTION_KEY))
{ {
LOGGER.error("Request failed: " + responseBody.getString(EXCEPTION_KEY)); LOGGER.error("Request failed: {}", responseBody.getString(EXCEPTION_KEY));
returnValues = responseBody; returnValues = responseBody;
} }
break; break;
default: default:
LOGGER.error("Request returned unexpected HTTP status " + response.getStatusLine().getStatusCode()); LOGGER.error("Request returned unexpected HTTP status {}", response.getStatusLine().getStatusCode());
break; break;
} }
} }

View File

@@ -41,7 +41,11 @@ public enum AuditEvents
DELETE_USER_GROUP("Delete User Group", "Delete User Group"), DELETE_USER_GROUP("Delete User Group", "Delete User Group"),
ADD_TO_USER_GROUP("Add To User Group", "Add To User Group"), ADD_TO_USER_GROUP("Add To User Group", "Add To User Group"),
REMOVE_FROM_USER_GROUP("Remove From User Group", "Remove From User Group"), REMOVE_FROM_USER_GROUP("Remove From User Group", "Remove From User Group"),
LOGIN_UNSUCCESSFUL("Login.Failure", "Login Unsuccessful"); LOGIN_UNSUCCESSFUL("Login.Failure", "Login Unsuccessful"),
CREATE_HOLD("Create Hold", "Create Hold"),
DELETE_HOLD("Delete Hold", "Delete Hold"),
ADD_TO_HOLD("Add To Hold", "Add To Hold"),
REMOVE_FROM_HOLD("Remove From Hold", "Remove From Hold");
/** event audited */ /** event audited */
public final String event; public final String event;

View File

@@ -28,7 +28,6 @@ package org.alfresco.rest.v0;
import static org.alfresco.rest.core.v0.APIUtils.convertHTTPResponseToJSON; import static org.alfresco.rest.core.v0.APIUtils.convertHTTPResponseToJSON;
import static org.apache.http.HttpStatus.SC_OK; import static org.apache.http.HttpStatus.SC_OK;
import static org.testng.AssertJUnit.assertNotNull;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.Collections; import java.util.Collections;
@@ -39,8 +38,7 @@ import org.alfresco.rest.core.v0.APIUtils;
import org.alfresco.rest.core.v0.BaseAPI; import org.alfresco.rest.core.v0.BaseAPI;
import org.alfresco.rest.rm.community.model.hold.HoldEntry; import org.alfresco.rest.rm.community.model.hold.HoldEntry;
import org.alfresco.rest.rm.community.util.PojoUtility; import org.alfresco.rest.rm.community.util.PojoUtility;
import org.alfresco.utility.Utility; import org.alfresco.utility.model.UserModel;
import org.apache.chemistry.opencmis.client.api.CmisObject;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
import org.apache.http.ParseException; import org.apache.http.ParseException;
import org.json.JSONArray; import org.json.JSONArray;
@@ -81,18 +79,27 @@ public class HoldsAPI extends BaseAPI
* @param holdName the hold name * @param holdName the hold name
* @param reason hold reason * @param reason hold reason
* @param description hold description * @param description hold description
* @return The HTTP response (or null if no POST call was needed). * @return The HTTP response.
*/ */
public HttpResponse createHold(String user, String password, public HttpResponse createHold(String user, String password, String holdName, String reason, String description)
String holdName, String reason, String description)
{ {
// if the hold already exists don't try to create it again return createHold(user, password, holdName, reason, description, SC_OK);
final String fullHoldPath = Utility.buildPath(getFilePlanPath(), HOLDS_CONTAINER) + holdName;
final CmisObject hold = getObjectByPath(user, password, fullHoldPath);
if (hold != null)
{
return null;
} }
/**
* Util method to create a hold
*
* @param user the user creating the hold
* @param password the user's password
* @param holdName the hold name
* @param reason hold reason
* @param description hold description
* @param expectedStatusCode The expected return status code.
* @return The HTTP response or throws AssertionError if the returned status code is not as expected.
*/
public HttpResponse createHold(String user, String password, String holdName, String reason, String description,
int expectedStatusCode)
{
// retrieve the Holds container nodeRef // retrieve the Holds container nodeRef
final String parentNodeRef = getItemNodeRef(user, password, "/" + HOLDS_CONTAINER); final String parentNodeRef = getItemNodeRef(user, password, "/" + HOLDS_CONTAINER);
@@ -102,11 +109,7 @@ public class HoldsAPI extends BaseAPI
requestParams.put("prop_cm_description", description); requestParams.put("prop_cm_description", description);
requestParams.put("prop_rma_holdReason", reason); requestParams.put("prop_rma_holdReason", reason);
// Make the POST request and throw an assertion error if it fails. return doPostJsonRequest(user, password, expectedStatusCode, requestParams, CREATE_HOLDS_API);
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;
} }
/** /**
@@ -142,7 +145,36 @@ public class HoldsAPI extends BaseAPI
} }
/** /**
* Deletes hold * Deletes hold using RM Actions API and expect action to be successful
*
* @param user the user who does the request
* @param holdNodeRef the hold node ref
* @return The HTTP Response or throws AssertionError if the request is not successful.
*/
public HttpResponse deleteHold(UserModel user, String holdNodeRef)
{
return deleteHold(user.getUsername(), user.getPassword(), holdNodeRef, SC_OK);
}
/**
* Deletes hold using RM Actions API and expect a specific status code
*
* @param username user's username
* @param password its password
* @param holdNodeRef the hold node ref
* @return The HTTP Response or throws AssertionError if the returned status code is not as expected.
*/
public HttpResponse deleteHold(String username, String password, String holdNodeRef, int expectedStatusCode)
{
JSONObject requestParams = new JSONObject();
requestParams.put("name", "deleteHold");
requestParams.put("nodeRef", getNodeRefSpacesStore() + holdNodeRef);
return doPostJsonRequest(username, password, expectedStatusCode, requestParams, RM_ACTIONS_API);
}
/**
* Deletes hold using cmis
* *
* @param username user's username * @param username user's username
* @param password its password * @param password its password
@@ -179,7 +211,10 @@ public class HoldsAPI extends BaseAPI
*/ */
public HttpResponse addItemsToHolds(String user, String password, List<String> itemNodeRefs, List<String> holdNames) public HttpResponse addItemsToHolds(String user, String password, List<String> itemNodeRefs, List<String> holdNames)
{ {
return addItemsToHolds(user, password, SC_OK, itemNodeRefs, holdNames); final List<String> holdNodeRefs = holdNames.stream()
.map(hold -> getItemNodeRef(user, password, String.format("/%s/%s", HOLDS_CONTAINER, hold)))
.collect(Collectors.toList());
return addItemsToHolds(user, password, SC_OK, itemNodeRefs, holdNodeRefs);
} }
/** /**
@@ -188,13 +223,13 @@ public class HoldsAPI extends BaseAPI
* @param user the user who adds the items to the holds * @param user the user who adds the items to the holds
* @param password the user's password * @param password the user's password
* @param itemNodeRefs the list of items nodeRefs to be added to holds * @param itemNodeRefs the list of items nodeRefs to be added to holds
* @param holdNames the list of holds * @param holdNodeRefs the list of holds
* @return The HTTP response * @return The HTTP response
*/ */
public HttpResponse addItemsToHolds(String user, String password, int expectedStatus, List<String> itemNodeRefs, public HttpResponse addItemsToHolds(String user, String password, int expectedStatus, List<String> itemNodeRefs,
List<String> holdNames) List<String> holdNodeRefs)
{ {
final JSONObject requestParams = addOrRemoveToFromHoldJsonObject(user, password, itemNodeRefs, holdNames); final JSONObject requestParams = addOrRemoveToFromHoldJsonObject(itemNodeRefs, holdNodeRefs);
return doPostJsonRequest(user, password, expectedStatus, requestParams, RM_HOLDS_API); return doPostJsonRequest(user, password, expectedStatus, requestParams, RM_HOLDS_API);
} }
@@ -204,35 +239,30 @@ public class HoldsAPI extends BaseAPI
* @param user the user who adds the item to the hold * @param user the user who adds the item to the hold
* @param password the user's password * @param password the user's password
* @param itemNodeRef the nodeRef of the item to be added to hold * @param itemNodeRef the nodeRef of the item to be added to hold
* @param holdName the hold name * @param holdNodeRef the hold node ref
* @return The error message * @return The error message
*/ */
public String addToHoldAndGetMessage(String user, String password, int expectedStatus, String itemNodeRef, String public String addToHoldAndGetMessage(String user, String password, int expectedStatus, String itemNodeRef, String
holdName) holdNodeRef)
{ {
final HttpResponse httpResponse = addItemsToHolds(user, password, expectedStatus, Collections.singletonList(itemNodeRef), final HttpResponse httpResponse = addItemsToHolds(user, password, expectedStatus, Collections.singletonList(itemNodeRef),
Collections.singletonList(holdName)); Collections.singletonList(holdNodeRef));
return APIUtils.extractErrorMessageFromHttpResponse(httpResponse); return APIUtils.extractErrorMessageFromHttpResponse(httpResponse);
} }
/** /**
* Util method to create the request body used when adding items to holds or when removing items from holds * Util method to create the request body used when adding items to holds or when removing items from holds
* *
* @param user user to create the request body for add/remove an item to/from hold
* @param password the user's password
* @param items list of items node refs to be added to holds * @param items list of items node refs to be added to holds
* @param holdNames list of hold names for add/remove items * @param holdNodeRefs list of hold node refs for add/remove items
* @return JSONObject fo * @return JSONObject fo
*/ */
private JSONObject addOrRemoveToFromHoldJsonObject(String user, String password, List<String> items, List<String> holdNames) private JSONObject addOrRemoveToFromHoldJsonObject(List<String> items, List<String> holdNodeRefs)
{ {
final JSONArray nodeRefs = new JSONArray(); final JSONArray nodeRefs = new JSONArray();
items.forEach(itemNodeRef -> nodeRefs.put(getNodeRefSpacesStore() + itemNodeRef)); items.forEach(itemNodeRef -> nodeRefs.put(getNodeRefSpacesStore() + itemNodeRef));
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(); final JSONArray holds = new JSONArray();
holdNodeRefs.forEach(holds::put); holdNodeRefs.forEach(holdNodeRef -> holds.put(getNodeRefSpacesStore() + holdNodeRef));
final JSONObject requestParams = new JSONObject(); final JSONObject requestParams = new JSONObject();
requestParams.put("nodeRefs", nodeRefs); requestParams.put("nodeRefs", nodeRefs);
requestParams.put("holds", holds); requestParams.put("holds", holds);
@@ -264,7 +294,10 @@ public class HoldsAPI extends BaseAPI
*/ */
public HttpResponse removeItemsFromHolds(String user, String password, List<String> itemNodeRefs, List<String> holdNames) public HttpResponse removeItemsFromHolds(String user, String password, List<String> itemNodeRefs, List<String> holdNames)
{ {
return removeItemsFromHolds(user, password, SC_OK, itemNodeRefs, holdNames); final List<String> holdNodeRefs = holdNames.stream()
.map(hold -> getItemNodeRef(user, password, String.format("/%s/%s", HOLDS_CONTAINER, hold)))
.collect(Collectors.toList());
return removeItemsFromHolds(user, password, SC_OK, itemNodeRefs, holdNodeRefs);
} }
/** /**
@@ -274,13 +307,13 @@ public class HoldsAPI extends BaseAPI
* @param password the user's password * @param password the user's password
* @param expectedStatus https status code expected * @param expectedStatus https status code expected
* @param itemNodeRefs the list of items nodeRefs to be removed from hold * @param itemNodeRefs the list of items nodeRefs to be removed from hold
* @param holdNames the list of hold names * @param holdNodeRefs the list of hold node refs
* @return The HTTP response * @return The HTTP response
*/ */
public HttpResponse removeItemsFromHolds(String user, String password, int expectedStatus, List<String> itemNodeRefs, public HttpResponse removeItemsFromHolds(String user, String password, int expectedStatus, List<String> itemNodeRefs,
List<String> holdNames) List<String> holdNodeRefs)
{ {
final JSONObject requestParams = addOrRemoveToFromHoldJsonObject(user, password, itemNodeRefs, holdNames); final JSONObject requestParams = addOrRemoveToFromHoldJsonObject(itemNodeRefs, holdNodeRefs);
return doPutJsonRequest(user, password, expectedStatus, requestParams, RM_HOLDS_API); return doPutJsonRequest(user, password, expectedStatus, requestParams, RM_HOLDS_API);
} }
@@ -290,14 +323,14 @@ public class HoldsAPI extends BaseAPI
* @param user the user who removes the item from hold * @param user the user who removes the item from hold
* @param password the user's password * @param password the user's password
* @param itemNodeRef the nodeRef of the item to be removed from hold * @param itemNodeRef the nodeRef of the item to be removed from hold
* @param holdName the hold name * @param holdNodeRef the hold node ref
* @return The error message * @return The error message
*/ */
public String removeFromHoldAndGetMessage(String user, String password, int expectedStatus, String itemNodeRef, String public String removeFromHoldAndGetMessage(String user, String password, int expectedStatus, String itemNodeRef, String
holdName) holdNodeRef)
{ {
final HttpResponse httpResponse = removeItemsFromHolds(user, password, expectedStatus, Collections.singletonList(itemNodeRef), final HttpResponse httpResponse = removeItemsFromHolds(user, password, expectedStatus, Collections.singletonList(itemNodeRef),
Collections.singletonList(holdName)); Collections.singletonList(holdNodeRef));
return APIUtils.extractErrorMessageFromHttpResponse(httpResponse); return APIUtils.extractErrorMessageFromHttpResponse(httpResponse);
} }

View File

@@ -0,0 +1,130 @@
/*
* #%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.service;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.testng.AssertJUnit.assertTrue;
import java.time.Instant;
import java.util.List;
import org.alfresco.rest.rm.community.model.audit.AuditEntry;
import org.alfresco.rest.rm.community.model.audit.AuditEvents;
import org.alfresco.rest.v0.RMAuditAPI;
import org.alfresco.utility.data.DataUser;
import org.alfresco.utility.model.UserModel;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* Produces processed results from RM Audit REST API calls
*
* @author Claudia Agache
* @since 3.3
*/
@Service
public class RMAuditService
{
@Autowired
private RMAuditAPI rmAuditAPI;
@Autowired
private DataUser dataUser;
/**
* Clear the list of audit entries as admin user.
*/
public void clearAuditLog()
{
STEP("Clean audit logs.");
rmAuditAPI.clearAuditLog(dataUser.getAdminUser().getUsername(), dataUser.getAdminUser().getPassword());
}
/**
* Returns a list of rm audit entries filtered by given event
*
* @param user the user who requests the list of rm audit entries
* @param auditEvent the event
* @return the list of audit entries matching the event
*/
public List<AuditEntry> getAuditEntriesFilteredByEvent(UserModel user, AuditEvents auditEvent)
{
STEP("Get the list of audit entries for the " + auditEvent.eventDisplayName + " event.");
return rmAuditAPI.getRMAuditLog(user.getUsername(), user.getPassword(), 100, auditEvent.event);
}
/**
* Checks the rm audit log contains the entry for the given event.
*
* @param user the user who checks the audit log
* @param auditEvent the audited event
* @param auditUser the user who did the audited event
* @param nodeName the audited node name if exists or empty string
* @param changedValues the values changed by event if exist or empty list
*/
public void checkAuditLogForEvent(UserModel user, AuditEvents auditEvent, UserModel auditUser,
String nodeName, List<Object> changedValues)
{
final Instant eventTimestamp = Instant.now();
List<AuditEntry> auditEntries = getAuditEntriesFilteredByEvent(user, auditEvent);
assertTrue("The list of events is not filtered by " + auditEvent.event,
auditEntries.stream().allMatch(auditEntry -> auditEntry.getEvent().equals(auditEvent.eventDisplayName)));
assertTrue("The event details are not audited",
auditEntries.stream().anyMatch(auditEntry -> auditEntry.getNodeName().equals(nodeName) &&
auditEntry.getUserName().equals(auditUser.getUsername()) &&
CollectionUtils.isEqualCollection(auditEntry.getChangedValues(), changedValues) &&
!auditEntry.getTimestamp().isEmpty() &&
Instant.parse(auditEntry.getTimestamp()).compareTo(eventTimestamp) <= 0));
}
/**
* Checks the rm audit log contains the entry for the given event.
*
* @param user the user who checks the audit log
* @param auditEvent the audited event
* @param auditUser the user who did the audited event
* @param nodeName the audited node name if exists or empty string
* @param nodePath the path of the audited node if exists or empty string
* @param changedValues the values changed by event if exist or empty list
*/
public void checkAuditLogForEvent(UserModel user, AuditEvents auditEvent, UserModel auditUser,
String nodeName, String nodePath, List<Object> changedValues)
{
final Instant eventTimestamp = Instant.now();
List<AuditEntry> auditEntries = getAuditEntriesFilteredByEvent(user, auditEvent);
assertTrue("The list of events is not filtered by " + auditEvent.event,
auditEntries.stream().allMatch(auditEntry -> auditEntry.getEvent().equals(auditEvent.eventDisplayName)));
assertTrue("The event details are not audited",
auditEntries.stream().anyMatch(auditEntry -> auditEntry.getNodeName().equals(nodeName) &&
auditEntry.getUserName().equals(auditUser.getUsername()) &&
auditEntry.getPath().equals(nodePath) &&
CollectionUtils.isEqualCollection(auditEntry.getChangedValues(), changedValues) &&
!auditEntry.getTimestamp().isEmpty() &&
Instant.parse(auditEntry.getTimestamp()).compareTo(eventTimestamp) <= 0));
}
}

View File

@@ -0,0 +1,299 @@
/*
* #%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.audit;
import static java.util.Arrays.asList;
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.audit.AuditEvents.ADD_TO_HOLD;
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
import static org.alfresco.utility.Utility.buildPath;
import static org.alfresco.utility.Utility.removeLastSlash;
import static org.alfresco.utility.data.RandomData.getRandomName;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.apache.commons.httpclient.HttpStatus.SC_INTERNAL_SERVER_ERROR;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertTrue;
import java.util.Collections;
import java.util.List;
import com.google.common.collect.ImmutableMap;
import org.alfresco.dataprep.CMISUtil;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.audit.AuditEntry;
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.model.user.UserPermissions;
import org.alfresco.rest.rm.community.model.user.UserRoles;
import org.alfresco.rest.v0.HoldsAPI;
import org.alfresco.rest.v0.service.RMAuditService;
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;
/**
* This class contains the tests that check the add to hold event is audited
*
* @author Claudia Agache
* @since 3.3
*/
@AlfrescoTest (jira = "RM-6859")
public class AuditAddToHoldTests extends BaseRMRestTest
{
private final String PREFIX = generateTestPrefix(AuditAddToHoldTests.class);
private final String HOLD1 = PREFIX + "hold1";
private final String HOLD2 = PREFIX + "hold2";
@Autowired
private RMAuditService rmAuditService;
@Autowired
private HoldsAPI holdsAPI;
@Autowired
private RoleService roleService;
private UserModel rmAdmin, rmManagerNoReadOnHold, rmManagerNoReadOnNode;
private SiteModel privateSite;
private RecordCategory recordCategory;
private RecordCategoryChild recordFolder;
private List<AuditEntry> auditEntries;
private List<String> holdsList = asList(HOLD1, HOLD2);
private String hold1NodeRef;
@BeforeClass (alwaysRun = true)
public void preconditionForAuditAddToHoldTests() throws Exception
{
STEP("Create 2 holds.");
hold1NodeRef = holdsAPI.createHoldAndGetNodeRef(getAdminUser().getUsername(),
getAdminUser().getPassword(), HOLD1, HOLD_REASON, HOLD_DESCRIPTION);
holdsAPI.createHold(getAdminUser().getUsername(), getAdminUser().getPassword(), HOLD2, HOLD_REASON, HOLD_DESCRIPTION);
STEP("Create a new record category with a record folder.");
recordCategory = createRootCategory(getRandomName("recordCategory"));
recordFolder = createRecordFolder(recordCategory.getId(), PREFIX + "recFolder");
STEP("Create an user with full rights to add content to a hold.");
rmAdmin = roleService.createUserWithRMRole(UserRoles.ROLE_RM_ADMIN.roleId);
STEP("Create a collaboration site.");
privateSite = dataSite.usingUser(rmAdmin).createPrivateRandomSite();
STEP("Create users without rights to add content to a hold.");
rmManagerNoReadOnHold = roleService.createUserWithSiteRoleRMRoleAndPermission(privateSite,
UserRole.SiteManager, recordCategory.getId(), UserRoles.ROLE_RM_MANAGER, UserPermissions.PERMISSION_FILING);
rmManagerNoReadOnNode = roleService.createUserWithRMRoleAndRMNodePermission(UserRoles.ROLE_RM_MANAGER.roleId,
hold1NodeRef, UserPermissions.PERMISSION_FILING);
}
/**
* Data provider with valid nodes that can be added to a hold
*
* @return the node id, the node name and the node path
* @throws Exception
*/
@DataProvider (name = "validNodesForAddToHold")
public Object[][] getValidNodesForAddToHold() throws Exception
{
String documentLibrary = "/documentLibrary";
FileModel contentToBeAdded = dataContent.usingAdmin().usingSite(privateSite)
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
RecordCategoryChild recordFolderToBeAdded = createRecordFolder(recordCategory.getId(), PREFIX + "recFolderToBeAdded");
Record recordToBeAdded = createElectronicRecord(recordFolder.getId(), PREFIX + "record");
String recordFolderPath = removeLastSlash(buildPath(documentLibrary, recordCategory.getName(),
recordFolderToBeAdded.getName()));
String recordPath = removeLastSlash(buildPath(documentLibrary, recordCategory.getName(),
recordFolder.getName(), recordToBeAdded.getName()));
String contentPath = "/Company Home" + contentToBeAdded.getCmisLocation();
return new String[][]
{
// a record folder
{ recordFolderToBeAdded.getId(), recordFolderToBeAdded.getName(), recordFolderPath },
// a record
{ recordToBeAdded.getId(), recordToBeAdded.getName(), recordPath },
//an active content,
{ contentToBeAdded.getNodeRefWithoutVersion(), contentToBeAdded.getName(), contentPath }
};
}
/**
* Data provider with invalid users that can not add content to a hold
*
* @return the userModel
*/
@DataProvider (name = "invalidUsersForAddToHold")
public Object[][] getInvalidUsersForAddToHold()
{
return new UserModel[][]
{
{ rmManagerNoReadOnHold },
{ rmManagerNoReadOnNode }
};
}
/**
* Given a document/record/record folder is added to a hold
* When I view the audit log
* Then an entry has been created in the audit log that contains the following:
* name of the hold
* name of the document/record/record folder added
* user who added the content
* date the content was added
* path of the node
*/
@Test (dataProvider = "validNodesForAddToHold")
public void addToHoldEventIsAudited(String nodeId, String nodeName, String nodePath)
{
rmAuditService.clearAuditLog();
STEP("Add node to hold.");
holdsAPI.addItemToHold(rmAdmin.getUsername(), rmAdmin.getPassword(), nodeId, HOLD1);
STEP("Check the audit log contains the entry for the add to hold event.");
rmAuditService.checkAuditLogForEvent(getAdminUser(), ADD_TO_HOLD, rmAdmin, nodeName, nodePath,
asList(ImmutableMap.of("new", nodeName, "previous", "", "name", "Name"),
ImmutableMap.of("new", HOLD1, "previous", "", "name", "Hold Name")));
}
/**
* Given an unsuccessful add to hold action
* When I view the audit log
* Then the add to hold event isn't audited
*/
@Test
public void unsuccessfulAddToHoldIsNotAudited() throws Exception
{
STEP("Create a new record");
Record recordToBeAdded = createElectronicRecord(recordFolder.getId(), PREFIX + "record");
rmAuditService.clearAuditLog();
STEP("Try to add the record to a hold by an user with no rights.");
holdsAPI.addItemsToHolds(rmManagerNoReadOnHold.getUsername(), rmManagerNoReadOnHold.getPassword(),
SC_INTERNAL_SERVER_ERROR, Collections.singletonList(recordToBeAdded.getId()),
Collections.singletonList(hold1NodeRef));
STEP("Check the audit log doesn't contain the entry for the unsuccessful add to hold.");
assertTrue("The list of events should not contain Add to Hold entry ",
rmAuditService.getAuditEntriesFilteredByEvent(getAdminUser(), ADD_TO_HOLD).isEmpty());
}
/**
* Given a not empty record folder is added to a hold
* When I view the audit log
* Then only an entry has been created in the audit log for the record folder added
*/
@Test
public void addToHoldIsNotAuditedForRecordFolderChildren() throws Exception
{
STEP("Create a new record folder with a record inside");
RecordCategoryChild notEmptyRecFolder = createRecordFolder(recordCategory.getId(), PREFIX + "notEmptyRecFolder");
Record record = createElectronicRecord(notEmptyRecFolder.getId(), PREFIX + "record");
rmAuditService.clearAuditLog();
STEP("Add record folder to hold.");
holdsAPI.addItemToHold(rmAdmin.getUsername(), rmAdmin.getPassword(), notEmptyRecFolder.getId(), HOLD1);
auditEntries = rmAuditService.getAuditEntriesFilteredByEvent(getAdminUser(), ADD_TO_HOLD);
STEP("Check the audit log contains only an entry for add to hold.");
assertEquals("The list of events should contain only an entry", 1, auditEntries.size());
assertTrue("The list of events should not contain Add to Hold entry for the record",
auditEntries.stream().noneMatch(entry -> entry.getNodeName().equals(record.getName())));
}
/**
* Given a record is added to multiple holds
* When I view the audit log
* Then multiple entries have been created in the audit log for each add to hold event
*/
@Test
public void addToHoldIsAuditedInBulkAddition() throws Exception
{
STEP("Create a new record");
Record recordToBeAdded = createElectronicRecord(recordFolder.getId(), PREFIX + "record");
rmAuditService.clearAuditLog();
STEP("Add record to multiple holds.");
holdsAPI.addItemsToHolds(rmAdmin.getUsername(), rmAdmin.getPassword(),
Collections.singletonList(recordToBeAdded.getId()), holdsList);
auditEntries = rmAuditService.getAuditEntriesFilteredByEvent(getAdminUser(), ADD_TO_HOLD);
STEP("Check the audit log contains entries for both additions.");
assertEquals("The list of events should contain Add to Hold entries for both holds", 2, auditEntries.size());
assertTrue("The hold name value for the first add to hold is not audited.",
auditEntries.stream().anyMatch(entry -> entry.getChangedValues().contains(
ImmutableMap.of("new", HOLD1, "previous", "", "name", "Hold Name"))));
assertTrue("The hold name value for the second add to hold is not audited.",
auditEntries.stream().anyMatch(entry -> entry.getChangedValues().contains(
ImmutableMap.of("new", HOLD2, "previous", "", "name", "Hold Name"))));
}
/**
* Given a document is added to a hold
* When I view the audit log as an user with no Read permissions over the hold or the document
* Then the add to hold entry isn't visible
*/
@Test (dataProvider = "invalidUsersForAddToHold")
public void addToHoldAuditEntryNotVisible(UserModel user)
{
STEP("Create a new file");
FileModel contentToBeAdded = dataContent.usingAdmin().usingSite(privateSite)
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
rmAuditService.clearAuditLog();
STEP("Add file to hold.");
holdsAPI.addItemToHold(rmAdmin.getUsername(), rmAdmin.getPassword(), contentToBeAdded.getNodeRefWithoutVersion(), HOLD1);
STEP("Check that an user with no Read permissions can't see the entry for the add to hold event.");
assertTrue("The list of events should not contain Add to Hold entry ",
rmAuditService.getAuditEntriesFilteredByEvent(user, ADD_TO_HOLD).isEmpty());
}
@AfterClass (alwaysRun = true)
public void cleanUpAuditAddToHoldTests()
{
holdsList.forEach(hold -> holdsAPI.deleteHold(getAdminUser().getUsername(), getAdminUser().getPassword(), hold));
dataSite.usingAdmin().deleteSite(privateSite);
asList(rmAdmin, rmManagerNoReadOnHold, rmManagerNoReadOnNode).forEach(user -> getDataUser().usingAdmin().deleteUser(user));
getRestAPIFactory().getRecordCategoryAPI().deleteRecordCategory(recordCategory.getId());
}
}

View File

@@ -0,0 +1,185 @@
/*
* #%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.audit;
import static java.util.Arrays.asList;
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.audit.AuditEvents.CREATE_HOLD;
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.apache.commons.httpclient.HttpStatus.SC_INTERNAL_SERVER_ERROR;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertTrue;
import java.util.List;
import com.google.common.collect.ImmutableMap;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.audit.AuditEntry;
import org.alfresco.rest.rm.community.model.user.UserRoles;
import org.alfresco.rest.v0.HoldsAPI;
import org.alfresco.rest.v0.service.RMAuditService;
import org.alfresco.rest.v0.service.RoleService;
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;
/**
* This class contains the tests that check the create hold event is audited
*
* @author Claudia Agache
* @since 3.3
*/
@AlfrescoTest (jira = "RM-6859")
public class AuditCreateHoldTests extends BaseRMRestTest
{
private final String PREFIX = generateTestPrefix(AuditCreateHoldTests.class);
private final String HOLD1 = PREFIX + "createHold";
private final String HOLD2 = PREFIX + "createHold2";
private final String HOLD3 = PREFIX + "createHold3";
@Autowired
private RMAuditService rmAuditService;
@Autowired
private HoldsAPI holdsAPI;
@Autowired
private RoleService roleService;
private UserModel rmAdmin, rmManager;
@BeforeClass (alwaysRun = true)
public void preconditionForAuditCreateHoldTests()
{
STEP("Create test users.");
rmAdmin = roleService.createUserWithRMRole(UserRoles.ROLE_RM_ADMIN.roleId);
rmManager = roleService.createUserWithRMRole(UserRoles.ROLE_RM_MANAGER.roleId);
}
/**
* Given a new hold is created
* When I view the audit log
* Then an entry has been created in the audit log which contains the following:
* name of the hold
* reason for hold
* user who created the hold
* date the creation occurred
*/
@Test
public void createHoldEventIsAuditedForNewHold()
{
rmAuditService.clearAuditLog();
STEP("Create a new hold.");
holdsAPI.createHold(rmAdmin.getUsername(), rmAdmin.getPassword(), HOLD1, HOLD_REASON, HOLD_DESCRIPTION);
STEP("Check the audit log contains the entry for the created hold with the hold details.");
rmAuditService.checkAuditLogForEvent(getAdminUser(), CREATE_HOLD, rmAdmin, HOLD1,
asList(ImmutableMap.of("new", HOLD_REASON, "previous", "", "name", "Hold Reason"),
ImmutableMap.of("new", HOLD1, "previous", "", "name", "Hold Name")));
}
/**
* Given an unsuccessful create hold action
* When I view the audit log
* Then the create hold event isn't audited
*/
@Test
public void createHoldEventIsNotAuditedForExistingHold()
{
STEP("Create a new hold.");
holdsAPI.createHold(rmAdmin.getUsername(), rmAdmin.getPassword(), HOLD2, HOLD_REASON, HOLD_DESCRIPTION);
rmAuditService.clearAuditLog();
STEP("Try to create again the same hold and expect action to fail.");
holdsAPI.createHold(rmAdmin.getUsername(), rmAdmin.getPassword(), HOLD2, HOLD_REASON, HOLD_DESCRIPTION,
SC_INTERNAL_SERVER_ERROR);
STEP("Check the audit log doesn't contain the entry for the second create hold event.");
assertTrue("The list of events should not contain Create Hold entry ",
rmAuditService.getAuditEntriesFilteredByEvent(getAdminUser(), CREATE_HOLD).isEmpty());
}
/**
* Given a new hold is created and then deleted
* When I view the audit log
* Then the create hold entry still contains the initial details
*/
@Test
public void createHoldAuditEntryIsNotLost()
{
final String holdName = PREFIX + "holdToBeDeleted";
rmAuditService.clearAuditLog();
STEP("Create a new hold.");
holdsAPI.createHold(rmAdmin.getUsername(), rmAdmin.getPassword(), holdName, HOLD_REASON, HOLD_DESCRIPTION);
STEP("Get the list of audit entries for the create hold event.");
List<AuditEntry> auditEntries = rmAuditService.getAuditEntriesFilteredByEvent(getAdminUser(), CREATE_HOLD);
STEP("Delete the created hold.");
holdsAPI.deleteHold(rmAdmin.getUsername(), rmAdmin.getPassword(), holdName);
STEP("Get again the list of audit entries for the create hold event.");
List<AuditEntry> auditEntriesAfterDelete = rmAuditService.getAuditEntriesFilteredByEvent(getAdminUser(), CREATE_HOLD);
STEP("Check that the audit entry for the created hold didn't change after hold deletion.");
assertEquals("The audit entry for Create Hold has been changed", auditEntries, auditEntriesAfterDelete);
}
/**
* Given a new hold is created
* When I view the audit log as an user with no Read permissions over the created hold
* Then the create hold entry isn't visible
*/
@Test
public void createHoldAuditEntryNotVisible()
{
rmAuditService.clearAuditLog();
STEP("Create a new hold.");
holdsAPI.createHold(rmAdmin.getUsername(), rmAdmin.getPassword(), HOLD3, HOLD_REASON, HOLD_DESCRIPTION);
STEP("Check that an user with no Read permissions over the hold can't see the entry for the create hold event");
assertTrue("The list of events should not contain Create Hold entry ",
rmAuditService.getAuditEntriesFilteredByEvent(rmManager, CREATE_HOLD).isEmpty());
}
@AfterClass (alwaysRun = true)
public void cleanUpAuditCreateHoldTests()
{
asList(HOLD1, HOLD2, HOLD3).forEach(hold ->
holdsAPI.deleteHold(getAdminUser().getUsername(), getAdminUser().getPassword(), hold));
asList(rmAdmin, rmManager).forEach(user -> getDataUser().usingAdmin().deleteUser(user));
}
}

View File

@@ -0,0 +1,139 @@
/*
* #%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.audit;
import static java.util.Arrays.asList;
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.audit.AuditEvents.DELETE_HOLD;
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.apache.commons.httpclient.HttpStatus.SC_INTERNAL_SERVER_ERROR;
import static org.testng.AssertJUnit.assertTrue;
import java.util.Collections;
import com.google.common.collect.ImmutableMap;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.user.UserRoles;
import org.alfresco.rest.v0.HoldsAPI;
import org.alfresco.rest.v0.service.RMAuditService;
import org.alfresco.rest.v0.service.RoleService;
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;
/**
* This class contains the tests that check the delete hold event is audited
*
* @author Claudia Agache
* @since 3.3
*/
@AlfrescoTest (jira = "RM-6859")
public class AuditDeleteHoldTests extends BaseRMRestTest
{
private final String PREFIX = generateTestPrefix(AuditDeleteHoldTests.class);
private final String HOLD = PREFIX + "holdToBeDeleted";
private final String HOLD2 = PREFIX + "deleteHold";
@Autowired
private RMAuditService rmAuditService;
@Autowired
private HoldsAPI holdsAPI;
@Autowired
private RoleService roleService;
private UserModel rmAdmin, rmManager;
private String holdNodeRef;
@BeforeClass (alwaysRun = true)
public void preconditionForAuditDeleteHoldTests()
{
STEP("Create a new hold.");
holdNodeRef = holdsAPI.createHoldAndGetNodeRef(getAdminUser().getUsername(), getAdminUser().getPassword(), HOLD,
HOLD_REASON, HOLD_DESCRIPTION);
STEP("Create 2 users with different permissions for the created hold.");
rmAdmin = roleService.createUserWithRMRole(UserRoles.ROLE_RM_ADMIN.roleId);
rmManager = roleService.createUserWithRMRole(UserRoles.ROLE_RM_MANAGER.roleId);
}
/**
* Given a hold is deleted
* When I view the audit log
* Then an entry has been created in the audit log which contains the following:
* name of the hold
* user who deleted the hold
* date the delete occurred
*/
@Test
public void deleteHoldEventIsAudited()
{
STEP("Create a new hold.");
String holdRef = holdsAPI.createHoldAndGetNodeRef(rmAdmin.getUsername(), rmAdmin.getPassword(), HOLD2,
HOLD_REASON, HOLD_DESCRIPTION);
rmAuditService.clearAuditLog();
STEP("Delete the created hold.");
holdsAPI.deleteHold(rmAdmin, holdRef);
STEP("Check the audit log contains the entry for the deleted hold with the hold details.");
rmAuditService.checkAuditLogForEvent(getAdminUser(), DELETE_HOLD, rmAdmin, HOLD2,
Collections.singletonList(ImmutableMap.of("new", "", "previous", HOLD2, "name", "Hold Name")));
}
/**
* Given an unsuccessful delete hold action
* When I view the audit log
* Then the delete hold event isn't audited
*/
@Test
public void unsuccessfulDeleteHoldIsNotAudited()
{
rmAuditService.clearAuditLog();
STEP("Try to delete a hold by an user with no Read permissions over the hold.");
holdsAPI.deleteHold(rmManager.getUsername(), rmManager.getPassword(), holdNodeRef, SC_INTERNAL_SERVER_ERROR);
STEP("Check the audit log doesn't contain the entry for the unsuccessful delete hold.");
assertTrue("The list of events should not contain Delete Hold entry ",
rmAuditService.getAuditEntriesFilteredByEvent(getAdminUser(), DELETE_HOLD).isEmpty());
}
@AfterClass (alwaysRun = true)
public void cleanUpAuditDeleteHoldTests()
{
holdsAPI.deleteHold(getAdminUser().getUsername(), getAdminUser().getPassword(), HOLD);
asList(rmAdmin, rmManager).forEach(user -> getDataUser().usingAdmin().deleteUser(user));
}
}

View File

@@ -26,20 +26,20 @@
*/ */
package org.alfresco.rest.rm.community.audit; package org.alfresco.rest.rm.community.audit;
import static java.util.Arrays.asList;
import static org.alfresco.rest.rm.community.model.audit.AuditEvents.ADD_TO_USER_GROUP; import static org.alfresco.rest.rm.community.model.audit.AuditEvents.ADD_TO_USER_GROUP;
import static org.alfresco.rest.rm.community.model.audit.AuditEvents.CREATE_USER_GROUP; import static org.alfresco.rest.rm.community.model.audit.AuditEvents.CREATE_USER_GROUP;
import static org.alfresco.rest.rm.community.model.audit.AuditEvents.DELETE_USER_GROUP; import static org.alfresco.rest.rm.community.model.audit.AuditEvents.DELETE_USER_GROUP;
import static org.alfresco.rest.rm.community.model.audit.AuditEvents.REMOVE_FROM_USER_GROUP; import static org.alfresco.rest.rm.community.model.audit.AuditEvents.REMOVE_FROM_USER_GROUP;
import static org.alfresco.utility.report.log.Step.STEP; import static org.alfresco.utility.report.log.Step.STEP;
import static org.testng.AssertJUnit.assertTrue;
import java.util.List; import java.util.Collections;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import org.alfresco.rest.rm.community.base.BaseRMRestTest; import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.audit.AuditEntry; import org.alfresco.rest.v0.service.RMAuditService;
import org.alfresco.rest.v0.RMAuditAPI;
import org.alfresco.test.AlfrescoTest; import org.alfresco.test.AlfrescoTest;
import org.alfresco.utility.model.GroupModel; import org.alfresco.utility.model.GroupModel;
import org.alfresco.utility.model.UserModel; import org.alfresco.utility.model.UserModel;
@@ -57,16 +57,14 @@ import org.testng.annotations.Test;
public class AuditGroupEventsTests extends BaseRMRestTest public class AuditGroupEventsTests extends BaseRMRestTest
{ {
@Autowired @Autowired
private RMAuditAPI rmAuditAPI; private RMAuditService rmAuditService;
private GroupModel testGroup; private GroupModel testGroup;
private UserModel testUser; private UserModel testUser;
@BeforeClass (alwaysRun = true) @BeforeClass (alwaysRun = true)
public void cleanAuditLogs() public void cleanAuditLogs()
{ {
//clean audit logs rmAuditService.clearAuditLog();
rmAuditAPI.clearAuditLog(getAdminUser().getUsername(), getAdminUser().getPassword());
} }
/** /**
@@ -79,17 +77,10 @@ public class AuditGroupEventsTests extends BaseRMRestTest
{ {
testGroup = dataGroup.createRandomGroup(); testGroup = dataGroup.createRandomGroup();
STEP("Get the list of audit entries for the create group event."); STEP("Check the audit log contains the entry for the created group.");
List<AuditEntry> auditEntries = rmAuditAPI.getRMAuditLog(getAdminUser().getUsername(), rmAuditService.checkAuditLogForEvent(getAdminUser(), CREATE_USER_GROUP, getAdminUser(), testGroup.getGroupIdentifier(),
getAdminUser().getPassword(), 100, CREATE_USER_GROUP.event); Collections.singletonList(ImmutableMap.of("new", testGroup.getGroupIdentifier(), "previous", "",
"name", "authorityDisplayName")));
STEP("Check the audit log contains only the entries for the created group.");
assertTrue("The list of events is not filtered by " + CREATE_USER_GROUP.event,
auditEntries.stream().allMatch(auditEntry -> auditEntry.getEvent().equals(CREATE_USER_GROUP.eventDisplayName)));
assertTrue("The group name for the new group created is not audited.",
auditEntries.stream().filter(auditEntry -> auditEntry.getEvent().equals(CREATE_USER_GROUP.eventDisplayName))
.anyMatch(auditEntry -> auditEntry.getNodeName().equals(testGroup.getGroupIdentifier())));
} }
/** /**
@@ -104,19 +95,10 @@ public class AuditGroupEventsTests extends BaseRMRestTest
testUser = getDataUser().createRandomTestUser(); testUser = getDataUser().createRandomTestUser();
dataGroup.usingUser(testUser).addUserToGroup(testGroup); dataGroup.usingUser(testUser).addUserToGroup(testGroup);
STEP("Get the list of audit entries for the add user to group event."); STEP("Check the audit log contains the entry for the add user to group event.");
List<AuditEntry> auditEntries = rmAuditAPI.getRMAuditLog(getAdminUser().getUsername(), rmAuditService.checkAuditLogForEvent(getAdminUser(), ADD_TO_USER_GROUP, getAdminUser(), testGroup.getGroupIdentifier(),
getAdminUser().getPassword(), 100, ADD_TO_USER_GROUP.event); asList(ImmutableMap.of("new", testUser.getUsername(), "previous", "", "name", "User Name"),
ImmutableMap.of("new", testGroup.getGroupIdentifier(), "previous", "", "name", "Parent Group")));
STEP("Check the audit log contains only the entries for the add user to group event.");
assertTrue("The list of events is not filtered by " + ADD_TO_USER_GROUP.event,
auditEntries.stream().allMatch(auditEntry -> auditEntry.getEvent().equals(ADD_TO_USER_GROUP.eventDisplayName)));
assertTrue("The username and destination group are not audited.",
auditEntries.stream().filter(auditEntry -> auditEntry.getEvent().equals(ADD_TO_USER_GROUP.eventDisplayName))
.anyMatch(auditEntry -> auditEntry.getNodeName().equals(testGroup.getGroupIdentifier())
&& auditEntry.getChangedValues().contains(ImmutableMap.of("new", testUser.getUsername(), "previous", "", "name", "User Name"))
&& auditEntry.getChangedValues().contains(ImmutableMap.of("new", testGroup.getGroupIdentifier(), "previous", "", "name", "Parent Group"))));
} }
/** /**
@@ -132,19 +114,10 @@ public class AuditGroupEventsTests extends BaseRMRestTest
dataGroup.usingUser(testUser).addUserToGroup(testGroup); dataGroup.usingUser(testUser).addUserToGroup(testGroup);
dataGroup.removeUserFromGroup(testGroup, testUser); dataGroup.removeUserFromGroup(testGroup, testUser);
STEP("Get the list of audit entries for the add user to group event."); STEP("Check the audit log contains the entry for the remove user from group event.");
List<AuditEntry> auditEntries = rmAuditAPI.getRMAuditLog(getAdminUser().getUsername(), rmAuditService.checkAuditLogForEvent(getAdminUser(), REMOVE_FROM_USER_GROUP, getAdminUser(), testGroup.getGroupIdentifier(),
getAdminUser().getPassword(), 100, REMOVE_FROM_USER_GROUP.event); asList(ImmutableMap.of("new", "", "previous", testUser.getUsername(), "name", "User Name"),
ImmutableMap.of("new", "","previous", testGroup.getGroupIdentifier(), "name", "Parent Group")));
STEP("Check the audit log contains only the entries for the remove user from group event.");
assertTrue("The list of events is not filtered by " + REMOVE_FROM_USER_GROUP.event,
auditEntries.stream().allMatch(auditEntry -> auditEntry.getEvent().equals(REMOVE_FROM_USER_GROUP.eventDisplayName)));
assertTrue("The username and previous parent group are not audited.",
auditEntries.stream().filter(auditEntry -> auditEntry.getEvent().equals(REMOVE_FROM_USER_GROUP.eventDisplayName))
.anyMatch(auditEntry -> auditEntry.getNodeName().equals(testGroup.getGroupIdentifier())
&& auditEntry.getChangedValues().contains(ImmutableMap.of("new", "", "previous", testUser.getUsername(), "name", "User Name"))
&& auditEntry.getChangedValues().contains(ImmutableMap.of("new", "","previous", testGroup.getGroupIdentifier(), "name", "Parent Group"))));
} }
/** /**
@@ -158,17 +131,9 @@ public class AuditGroupEventsTests extends BaseRMRestTest
testGroup = dataGroup.createRandomGroup(); testGroup = dataGroup.createRandomGroup();
dataGroup.deleteGroup(testGroup); dataGroup.deleteGroup(testGroup);
STEP("Get the list of audit entries for the delete group event."); STEP("Check the audit log contains the entry for the delete group event.");
List<AuditEntry> auditEntries = rmAuditAPI.getRMAuditLog(getAdminUser().getUsername(), rmAuditService.checkAuditLogForEvent(getAdminUser(), DELETE_USER_GROUP, getAdminUser(), testGroup.getGroupIdentifier(),
getAdminUser().getPassword(), 100, DELETE_USER_GROUP.event); Collections.singletonList(ImmutableMap.of("new", "", "previous", testGroup.getGroupIdentifier(),
"name", "authorityDisplayName")));
STEP("Check the audit log contains only the entries for the created group.");
assertTrue("The list of events is not filtered by " + DELETE_USER_GROUP.event,
auditEntries.stream().allMatch(auditEntry -> auditEntry.getEvent().equals(DELETE_USER_GROUP.eventDisplayName)));
assertTrue("The group name for the deleted group is not audited.",
auditEntries.stream().filter(auditEntry -> auditEntry.getEvent().equals(DELETE_USER_GROUP.eventDisplayName))
.anyMatch(auditEntry -> auditEntry.getNodeName().equals(testGroup.getGroupIdentifier())
&& auditEntry.getChangedValues().contains(ImmutableMap.of("new", "", "previous", testGroup.getGroupIdentifier(), "name", "authorityDisplayName"))));
} }
} }

View File

@@ -34,11 +34,10 @@ import java.util.List;
import org.alfresco.rest.rm.community.base.BaseRMRestTest; import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.audit.AuditEntry; import org.alfresco.rest.rm.community.model.audit.AuditEntry;
import org.alfresco.rest.v0.RMAuditAPI; import org.alfresco.rest.v0.service.RMAuditService;
import org.alfresco.test.AlfrescoTest; import org.alfresco.test.AlfrescoTest;
import org.alfresco.utility.model.UserModel; import org.alfresco.utility.model.UserModel;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
/** /**
@@ -51,14 +50,7 @@ import org.testng.annotations.Test;
public class AuditLoginEventsTests extends BaseRMRestTest public class AuditLoginEventsTests extends BaseRMRestTest
{ {
@Autowired @Autowired
private RMAuditAPI rmAuditAPI; private RMAuditService rmAuditService;
@BeforeClass (alwaysRun = true)
public void cleanAuditLogs()
{
//clean audit logs
rmAuditAPI.clearAuditLog(getAdminUser().getUsername(), getAdminUser().getPassword());
}
/** /**
* Given I have tried to login using invalid credentials * Given I have tried to login using invalid credentials
@@ -68,12 +60,13 @@ public class AuditLoginEventsTests extends BaseRMRestTest
@Test @Test
public void filterByLoginUnsuccessful() throws Exception public void filterByLoginUnsuccessful() throws Exception
{ {
rmAuditService.clearAuditLog();
restClient.authenticateUser(new UserModel(getAdminUser().getUsername(), "InvalidPassword")); restClient.authenticateUser(new UserModel(getAdminUser().getUsername(), "InvalidPassword"));
restClient.withCoreAPI().getSites(); restClient.withCoreAPI().getSites();
STEP("Get the list of audit entries for the login unsuccessful event."); STEP("Get the list of audit entries for the login unsuccessful event.");
List<AuditEntry> auditEntries = rmAuditAPI.getRMAuditLog(getAdminUser().getUsername(), List<AuditEntry> auditEntries = rmAuditService.getAuditEntriesFilteredByEvent(getAdminUser(),
getAdminUser().getPassword(), 100, LOGIN_UNSUCCESSFUL.event); LOGIN_UNSUCCESSFUL);
STEP("Check the audit log contains only the entries for the login unsuccessful event."); STEP("Check the audit log contains only the entries for the login unsuccessful event.");
assertTrue("The list of events is not filtered by " + LOGIN_UNSUCCESSFUL.event, assertTrue("The list of events is not filtered by " + LOGIN_UNSUCCESSFUL.event,

View File

@@ -0,0 +1,312 @@
/*
* #%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.audit;
import static java.util.Arrays.asList;
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.audit.AuditEvents.REMOVE_FROM_HOLD;
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
import static org.alfresco.utility.Utility.buildPath;
import static org.alfresco.utility.Utility.removeLastSlash;
import static org.alfresco.utility.data.RandomData.getRandomName;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.apache.commons.httpclient.HttpStatus.SC_INTERNAL_SERVER_ERROR;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertTrue;
import java.util.Collections;
import java.util.List;
import com.google.common.collect.ImmutableMap;
import org.alfresco.dataprep.CMISUtil;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.audit.AuditEntry;
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.model.user.UserPermissions;
import org.alfresco.rest.rm.community.model.user.UserRoles;
import org.alfresco.rest.v0.HoldsAPI;
import org.alfresco.rest.v0.service.RMAuditService;
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;
/**
* This class contains the tests that check the remove from hold event is audited
*
* @author Claudia Agache
* @since 3.3
*/
@AlfrescoTest (jira = "RM-6859")
public class AuditRemoveFromHoldTests extends BaseRMRestTest
{
private final String PREFIX = generateTestPrefix(AuditRemoveFromHoldTests.class);
private final String HOLD1 = PREFIX + "hold1";
private final String HOLD2 = PREFIX + "hold2";
private final String HOLD3 = PREFIX + "hold3";
private final String DELETED_HOLD = PREFIX + "deletedHold";
@Autowired
private RMAuditService rmAuditService;
@Autowired
private HoldsAPI holdsAPI;
@Autowired
private RoleService roleService;
private UserModel rmAdmin, rmManagerNoReadOnHold, rmManagerNoReadOnNode;
private SiteModel privateSite;
private RecordCategory recordCategory;
private RecordCategoryChild recordFolder, heldRecordFolder;
private Record heldRecord;
private List<AuditEntry> auditEntries;
private List<String> holdsList = asList(HOLD1, HOLD2, HOLD3);
private FileModel heldContent;
private String hold1NodeRef;
@BeforeClass (alwaysRun = true)
public void preconditionForAuditRemoveFromHoldTests() throws Exception
{
STEP("Create an user with full rights to remove content from a hold.");
rmAdmin = roleService.createUserWithRMRole(UserRoles.ROLE_RM_ADMIN.roleId);
STEP("Create a collaboration site.");
privateSite = dataSite.usingUser(rmAdmin).createPrivateRandomSite();
STEP("Create new holds.");
hold1NodeRef = holdsAPI.createHoldAndGetNodeRef(getAdminUser().getUsername(), getAdminUser().getPassword(),
HOLD1, HOLD_REASON, HOLD_DESCRIPTION);
holdsAPI.createHold(getAdminUser().getUsername(), getAdminUser().getPassword(), HOLD2, HOLD_REASON, HOLD_DESCRIPTION);
holdsAPI.createHold(getAdminUser().getUsername(), getAdminUser().getPassword(), HOLD3, HOLD_REASON, HOLD_DESCRIPTION);
holdsAPI.createHold(getAdminUser().getUsername(), getAdminUser().getPassword(), DELETED_HOLD, HOLD_REASON, HOLD_DESCRIPTION);
STEP("Create a new record category with a record folder.");
recordCategory = createRootCategory(getRandomName("recordCategory"));
recordFolder = createRecordFolder(recordCategory.getId(), getRandomName("recFolder"));
STEP("Create some held items");
heldContent = dataContent.usingAdmin().usingSite(privateSite)
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
heldRecordFolder = createRecordFolder(recordCategory.getId(), PREFIX + "heldRecFolder");
heldRecord = createElectronicRecord(recordFolder.getId(), PREFIX + "record");
holdsAPI.addItemsToHolds(getAdminUser().getUsername(), getAdminUser().getPassword(),
asList(heldContent.getNodeRefWithoutVersion(), heldRecordFolder.getId(), heldRecord.getId()),
holdsList);
STEP("Create users without rights to remove content from a hold.");
rmManagerNoReadOnHold = roleService.createUserWithSiteRoleRMRoleAndPermission(privateSite,
UserRole.SiteManager, recordCategory.getId(), UserRoles.ROLE_RM_MANAGER, UserPermissions.PERMISSION_FILING);
rmManagerNoReadOnNode = roleService.createUserWithRMRoleAndRMNodePermission(UserRoles.ROLE_RM_MANAGER.roleId,
hold1NodeRef, UserPermissions.PERMISSION_FILING);
}
/**
* Data provider with valid nodes that can be removed from a hold
*
* @return the node id, the node name and the node path
*/
@DataProvider (name = "validNodesForRemoveFromHold")
public Object[][] getValidNodesForRemoveFromHold()
{
String documentLibrary = "/documentLibrary";
String recordFolderPath = removeLastSlash(buildPath(documentLibrary, recordCategory.getName(),
heldRecordFolder.getName()));
String recordPath = removeLastSlash(buildPath(documentLibrary, recordCategory.getName(),
recordFolder.getName(), heldRecord.getName()));
String contentPath = "/Company Home" + heldContent.getCmisLocation();
return new String[][]
{
// a record folder
{ heldRecordFolder.getId(), heldRecordFolder.getName(), recordFolderPath },
// a record
{ heldRecord.getId(), heldRecord.getName(), recordPath },
//an active content,
{ heldContent.getNodeRefWithoutVersion(), heldContent.getName(), contentPath }
};
}
/**
* Data provider with invalid users that can not remove content from a hold
*
* @return the userModel
*/
@DataProvider (name = "invalidUsersForRemoveFromHold")
public Object[][] getInvalidUsersForRemoveFromHold()
{
return new UserModel[][]
{
{ rmManagerNoReadOnHold },
{ rmManagerNoReadOnNode }
};
}
/**
* Given a document/record/record folder is removed from a hold
* When I view the audit log
* Then an entry has been created in the audit log that contains the following:
* name of the hold
* name of the document/record/record folder removed
* user who removed the content
* date the content was removed
* path of the node
*/
@Test (dataProvider = "validNodesForRemoveFromHold")
public void removeFromHoldEventIsAudited(String nodeId, String nodeName, String nodePath)
{
rmAuditService.clearAuditLog();
STEP("Remove node from hold.");
holdsAPI.removeItemFromHold(rmAdmin.getUsername(), rmAdmin.getPassword(), nodeId, HOLD3);
STEP("Check the audit log contains the entry for the remove from hold event.");
rmAuditService.checkAuditLogForEvent(getAdminUser(), REMOVE_FROM_HOLD, rmAdmin, nodeName, nodePath,
asList(ImmutableMap.of("new", "", "previous", nodeName, "name", "Name"),
ImmutableMap.of("new", "", "previous", HOLD3, "name", "Hold Name")));
}
/**
* Given an unsuccessful remove from hold action
* When I view the audit log
* Then the remove from hold event isn't audited
*/
@Test
public void unsuccessfulRemoveFromHoldIsNotAudited()
{
rmAuditService.clearAuditLog();
STEP("Try to remove the record from a hold by an user with no rights.");
holdsAPI.removeItemsFromHolds(rmManagerNoReadOnHold.getUsername(), rmManagerNoReadOnHold.getPassword(),
SC_INTERNAL_SERVER_ERROR, Collections.singletonList(heldRecord.getId()),
Collections.singletonList(hold1NodeRef));
STEP("Check the audit log doesn't contain the entry for the unsuccessful remove from hold.");
assertTrue("The list of events should not contain remove from hold entry ",
rmAuditService.getAuditEntriesFilteredByEvent(getAdminUser(), REMOVE_FROM_HOLD).isEmpty());
}
/**
* Given a not empty record folder is removed from a hold
* When I view the audit log
* Then only an entry has been created in the audit log for the record folder removed
*/
@Test
public void removeFromHoldNotAuditedForRecordFolderChildren() throws Exception
{
STEP("Create a new record folder with a record inside");
RecordCategoryChild notEmptyRecFolder = createRecordFolder(recordCategory.getId(), PREFIX + "notEmptyRecFolder");
Record record = createElectronicRecord(notEmptyRecFolder.getId(), PREFIX + "record");
STEP("Add the record folder to a hold.");
holdsAPI.addItemToHold(rmAdmin.getUsername(), rmAdmin.getPassword(), notEmptyRecFolder.getId(), HOLD1);
rmAuditService.clearAuditLog();
STEP("Remove record folder from hold.");
holdsAPI.removeItemFromHold(rmAdmin.getUsername(), rmAdmin.getPassword(), notEmptyRecFolder.getId(), HOLD1);
STEP("Get the list of audit entries for the remove from hold event.");
auditEntries = rmAuditService.getAuditEntriesFilteredByEvent(getAdminUser(), REMOVE_FROM_HOLD);
STEP("Check the audit log contains only an entry for remove from hold.");
assertEquals("The list of events should contain only an entry", 1, auditEntries.size());
assertTrue("The list of events should not contain Remove from Hold entry for the record",
auditEntries.stream().noneMatch(entry -> entry.getNodeName().equals(record.getName())));
}
/**
* Given a record folder is removed from multiple holds
* When I view the audit log
* Then multiple entries have been created in the audit log for each remove from hold event
*/
@Test
public void removeFromHoldIsAuditedInBulkRemoval()
{
rmAuditService.clearAuditLog();
STEP("Remove record folder from multiple holds.");
holdsAPI.removeItemsFromHolds(rmAdmin.getUsername(), rmAdmin.getPassword(),
Collections.singletonList(heldRecordFolder.getId()), asList(HOLD1, HOLD2));
STEP("Get the list of audit entries for the remove from hold event.");
auditEntries = rmAuditService.getAuditEntriesFilteredByEvent(getAdminUser(), REMOVE_FROM_HOLD);
STEP("Check the audit log contains entries for both removal.");
assertEquals("The list of events should contain remove from Hold entries for both holds", 2,
auditEntries.size());
assertTrue("The hold name value for the first remove from hold is not audited.",
auditEntries.stream().anyMatch(entry -> entry.getChangedValues().contains(
ImmutableMap.of("new", "", "previous", HOLD1, "name", "Hold Name"))));
assertTrue("The hold name value for the second remove from hold is not audited.",
auditEntries.stream().anyMatch(entry -> entry.getChangedValues().contains(
ImmutableMap.of("new", "", "previous", HOLD2, "name", "Hold Name"))));
}
/**
* Given a document/record/record folder is removed from a hold
* When I view the audit log as an user with no Read permissions over the hold or the node
* Then the remove from hold entry isn't visible
*/
@Test (dataProvider = "invalidUsersForRemoveFromHold")
public void removeFromHoldAuditEntryNotVisible(UserModel user)
{
STEP("Add content to a hold.");
FileModel heldFile = dataContent.usingAdmin().usingSite(privateSite)
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
holdsAPI.addItemToHold(rmAdmin.getUsername(), rmAdmin.getPassword(), heldFile.getNodeRefWithoutVersion(), HOLD1);
rmAuditService.clearAuditLog();
STEP("Remove held content from the hold.");
holdsAPI.removeItemFromHold(rmAdmin.getUsername(), rmAdmin.getPassword(), heldFile.getNodeRefWithoutVersion(), HOLD1);
STEP("Check that an user with no Read permissions can't see the entry for the remove from hold event.");
assertTrue("The list of events should not contain Remove from Hold entry ",
rmAuditService.getAuditEntriesFilteredByEvent(user, REMOVE_FROM_HOLD).isEmpty());
}
@AfterClass (alwaysRun = true)
public void cleanUpAuditRemoveFromHoldTests()
{
holdsList.forEach(hold -> holdsAPI.deleteHold(getAdminUser().getUsername(), getAdminUser().getPassword(), hold));
dataSite.usingAdmin().deleteSite(privateSite);
asList(rmAdmin, rmManagerNoReadOnHold, rmManagerNoReadOnNode).forEach(user -> getDataUser().usingAdmin().deleteUser(user));
getRestAPIFactory().getRecordCategoryAPI().deleteRecordCategory(recordCategory.getId());
}
}

View File

@@ -29,18 +29,17 @@ package org.alfresco.rest.rm.community.audit;
import static org.alfresco.rest.rm.community.model.audit.AuditEvents.CREATE_PERSON; import static org.alfresco.rest.rm.community.model.audit.AuditEvents.CREATE_PERSON;
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix; import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
import static org.alfresco.utility.report.log.Step.STEP; import static org.alfresco.utility.report.log.Step.STEP;
import static org.testng.AssertJUnit.assertTrue;
import java.util.List; import java.util.Collections;
import com.google.common.collect.ImmutableMap;
import org.alfresco.rest.rm.community.base.BaseRMRestTest; import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.audit.AuditEntry; import org.alfresco.rest.v0.service.RMAuditService;
import org.alfresco.rest.v0.RMAuditAPI;
import org.alfresco.test.AlfrescoTest; import org.alfresco.test.AlfrescoTest;
import org.alfresco.utility.model.UserModel; import org.alfresco.utility.model.UserModel;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.AfterClass; import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
/** /**
@@ -52,10 +51,9 @@ import org.testng.annotations.Test;
public class AuditUserEventsTests extends BaseRMRestTest public class AuditUserEventsTests extends BaseRMRestTest
{ {
private final String PREFIX = generateTestPrefix(AuditUserEventsTests.class); private final String PREFIX = generateTestPrefix(AuditUserEventsTests.class);
private UserModel createUser; private UserModel createUser;
@Autowired @Autowired
private RMAuditAPI rmAuditAPI; private RMAuditService rmAuditService;
/** /**
* Given I have created a new user * Given I have created a new user
@@ -66,30 +64,16 @@ public class AuditUserEventsTests extends BaseRMRestTest
*/ */
@Test @Test
@AlfrescoTest(jira = "RM-6223") @AlfrescoTest(jira = "RM-6223")
public void createUserEventIsAudited() throws Exception public void createUserEventIsAudited()
{ {
rmAuditService.clearAuditLog();
STEP("Create a new user."); STEP("Create a new user.");
String userName = "auditCreateUser" + PREFIX; String userName = "auditCreateUser" + PREFIX;
createUser = getDataUser().createUser(userName); createUser = getDataUser().createUser(userName);
STEP("Get the list of audit entries for the create person event."); STEP("Check the audit log contains the entry for the created user event.");
List<AuditEntry> auditEntries = rmAuditAPI.getRMAuditLog(getAdminUser().getUsername(), rmAuditService.checkAuditLogForEvent(getAdminUser(), CREATE_PERSON, getAdminUser(), userName,
getAdminUser().getPassword(), 100, CREATE_PERSON.event); Collections.singletonList(ImmutableMap.of("new", userName, "previous", "", "name", "User Name")));
STEP("Check the audit log contains only the entries for the created user.");
assertTrue("The list of events is not filtered by " + CREATE_PERSON.event,
auditEntries.stream().allMatch(auditEntry -> auditEntry.getEvent().equals(CREATE_PERSON.eventDisplayName)));
assertTrue("The username value for the user created is not audited.",
auditEntries.stream().filter(auditEntry -> auditEntry.getEvent().equals(CREATE_PERSON.eventDisplayName))
.allMatch(auditEntry -> auditEntry.getNodeName().equals(userName)));
}
@BeforeClass (alwaysRun = true)
public void cleanAuditLogs()
{
//clean audit logs
rmAuditAPI.clearAuditLog(getAdminUser().getUsername(), getAdminUser().getPassword());
} }
@AfterClass (alwaysRun = true) @AfterClass (alwaysRun = true)

View File

@@ -615,37 +615,6 @@ public class BaseRMRestTest extends RestTest
recordCategoryAPI.deleteRecordCategory(recordCategoryId); recordCategoryAPI.deleteRecordCategory(recordCategoryId);
} }
/**
* Helper method to create a test user with rm role
*
* @param userRole the rm role
* @return the created user model
*/
protected UserModel createUserWithRMRole(String userRole)
{
UserModel rmUser = getDataUser().createRandomTestUser();
getRestAPIFactory().getRMUserAPI().assignRoleToUser(rmUser.getUsername(), userRole);
assertStatusCode(OK);
return rmUser;
}
/**
* Helper method to create a test user with rm role and permissions over the record category
*
* @param userRole the rm role
* @param userPermission the permissions over the record category
* @param recordCategory the category on which user has permissions
* @return the created user model
*/
protected UserModel createUserWithRMRoleAndCategoryPermission(String userRole, RecordCategory recordCategory,
UserPermissions userPermission)
{
UserModel rmUser = createUserWithRMRole(userRole);
getRestAPIFactory().getRMUserAPI().addUserPermission(recordCategory.getId(), rmUser, userPermission);
assertStatusCode(OK);
return rmUser;
}
/** /**
* Returns search results for the given search term * Returns search results for the given search term
* *

View File

@@ -26,6 +26,8 @@
*/ */
package org.alfresco.rest.rm.community.files; package org.alfresco.rest.rm.community.files;
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.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.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.FilePlanComponentAlias.UNFILED_RECORDS_CONTAINER_ALIAS;
@@ -87,7 +89,7 @@ public class DeclareAndFileDocumentAsRecordTests extends BaseRMRestTest
private final static String INVALID_DESTINATION_PATH_EXC = "Unable to execute create-record action, because the destination path is invalid."; private final static String INVALID_DESTINATION_PATH_EXC = "Unable to execute create-record action, because the destination path is invalid.";
private final static String DESTINATION_PATH_NOT_RECORD_FOLDER_EXC = "Unable to execute create-record action, because the destination path is not a record folder."; private final static String DESTINATION_PATH_NOT_RECORD_FOLDER_EXC = "Unable to execute create-record action, because the destination path is not a record folder.";
private final static String CLOSED_RECORD_FOLDER_EXC = "You can't add new items to a closed record folder."; private final static String CLOSED_RECORD_FOLDER_EXC = "You can't add new items to a closed record folder.";
private final static String HOLD_NAME = "holdName"; private final static String HOLD_NAME = getRandomName("holdName");
private final static String RECORD_FOLDER_NAME_WITH_SPACE = "Folder With Spaces In Name"; private final static String RECORD_FOLDER_NAME_WITH_SPACE = "Folder With Spaces In Name";
private UserModel userFillingPermission, userReadOnlyPermission; private UserModel userFillingPermission, userReadOnlyPermission;
@@ -411,8 +413,7 @@ public class DeclareAndFileDocumentAsRecordTests extends BaseRMRestTest
public void declareAndFileToHeldRecordFolderUsingFilesAPI() throws Exception public void declareAndFileToHeldRecordFolderUsingFilesAPI() throws Exception
{ {
RecordCategoryChild heldRecordFolder = createFolder(recordCategory.getId(), getRandomName("heldRecordFolder")); RecordCategoryChild heldRecordFolder = createFolder(recordCategory.getId(), getRandomName("heldRecordFolder"));
holdsAPI.createHold(getAdminUser().getUsername(), getAdminUser().getPassword(), HOLD_NAME, "hold reason", holdsAPI.createHold(getAdminUser().getUsername(), getAdminUser().getPassword(), HOLD_NAME, HOLD_REASON, HOLD_DESCRIPTION);
"hold description");
holdsAPI.addItemToHold(getAdminUser().getUsername(), getAdminUser().getPassword(), heldRecordFolder.getId(), holdsAPI.addItemToHold(getAdminUser().getUsername(), getAdminUser().getPassword(), heldRecordFolder.getId(),
HOLD_NAME); HOLD_NAME);

View File

@@ -108,7 +108,7 @@ public class AddToHoldsTests extends BaseRMRestTest
private ContentActions contentActions; private ContentActions contentActions;
@BeforeClass (alwaysRun = true) @BeforeClass (alwaysRun = true)
public void preconditionForAddContentToHold() throws Exception public void preconditionForAddContentToHold()
{ {
STEP("Create a hold."); STEP("Create a hold.");
holdNodeRef = holdsAPI.createHoldAndGetNodeRef(getAdminUser().getUsername(), getAdminUser().getUsername(), holdNodeRef = holdsAPI.createHoldAndGetNodeRef(getAdminUser().getUsername(), getAdminUser().getUsername(),
@@ -174,7 +174,7 @@ public class AddToHoldsTests extends BaseRMRestTest
* Valid nodes to be added to hold * Valid nodes to be added to hold
*/ */
@DataProvider (name = "validNodesForAddToHold") @DataProvider (name = "validNodesForAddToHold")
public Object[][] getValidNodesForAddToHold() throws Exception public Object[][] getValidNodesForAddToHold()
{ {
//create electronic and nonElectronic record in record folder //create electronic and nonElectronic record in record folder
RecordCategoryChild recordFolder = createCategoryFolderInFilePlan(); RecordCategoryChild recordFolder = createCategoryFolderInFilePlan();
@@ -287,7 +287,7 @@ public class AddToHoldsTests extends BaseRMRestTest
users.add(userModel); users.add(userModel);
STEP("Add the node to the hold with user without permission."); STEP("Add the node to the hold with user without permission.");
String response = holdsAPI.addToHoldAndGetMessage(userModel.getUsername(), userModel.getPassword(), String response = holdsAPI.addToHoldAndGetMessage(userModel.getUsername(), userModel.getPassword(),
SC_INTERNAL_SERVER_ERROR, nodeToBeAddedToHold, HOLD); SC_INTERNAL_SERVER_ERROR, nodeToBeAddedToHold, holdNodeRef);
assertTrue(response.contains(ACCESS_DENIED_ERROR_MESSAGE)); assertTrue(response.contains(ACCESS_DENIED_ERROR_MESSAGE));
STEP("Check the node is not frozen."); STEP("Check the node is not frozen.");
@@ -345,7 +345,7 @@ public class AddToHoldsTests extends BaseRMRestTest
{ {
STEP("Add the node to the hold "); STEP("Add the node to the hold ");
String responseErrorMessage = holdsAPI.addToHoldAndGetMessage(getAdminUser().getUsername(), String responseErrorMessage = holdsAPI.addToHoldAndGetMessage(getAdminUser().getUsername(),
getAdminUser().getPassword(), responseCode, itemNodeRef, HOLD); getAdminUser().getPassword(), responseCode, itemNodeRef, holdNodeRef);
assertTrue(responseErrorMessage.contains(errorMessage), assertTrue(responseErrorMessage.contains(errorMessage),
"Actual error message " + responseErrorMessage + " expected " + errorMessage); "Actual error message " + responseErrorMessage + " expected " + errorMessage);
@@ -354,7 +354,7 @@ public class AddToHoldsTests extends BaseRMRestTest
} }
@AfterClass (alwaysRun = true) @AfterClass (alwaysRun = true)
public void cleanUpAddContentToHold() throws Exception public void cleanUpAddContentToHold()
{ {
holdsAPI.deleteHold(getAdminUser().getUsername(), getAdminUser().getPassword(), HOLD); holdsAPI.deleteHold(getAdminUser().getUsername(), getAdminUser().getPassword(), HOLD);
dataSite.usingAdmin().deleteSite(testSite); dataSite.usingAdmin().deleteSite(testSite);

View File

@@ -95,12 +95,12 @@ public class RemoveFromHoldsTests extends BaseRMRestTest
private RoleService roleService; private RoleService roleService;
@BeforeClass (alwaysRun = true) @BeforeClass (alwaysRun = true)
public void preconditionForRemoveContentFromHold() throws Exception public void preconditionForRemoveContentFromHold()
{ {
STEP("Create two holds."); STEP("Create two holds.");
holdNodeRefOne = holdsAPI.createHoldAndGetNodeRef(getAdminUser().getUsername(), getAdminUser().getUsername(), holdNodeRefOne = holdsAPI.createHoldAndGetNodeRef(getAdminUser().getUsername(), getAdminUser().getUsername(),
HOLD_ONE, HOLD_REASON, HOLD_DESCRIPTION); HOLD_ONE, HOLD_REASON, HOLD_DESCRIPTION);
String holdNodeRefTwo = holdsAPI.createHoldAndGetNodeRef(getAdminUser().getUsername(), getAdminUser() holdsAPI.createHoldAndGetNodeRef(getAdminUser().getUsername(), getAdminUser()
.getUsername(), HOLD_TWO, HOLD_REASON, HOLD_DESCRIPTION); .getUsername(), HOLD_TWO, HOLD_REASON, HOLD_DESCRIPTION);
STEP("Create test files."); STEP("Create test files.");
@@ -265,7 +265,7 @@ public class RemoveFromHoldsTests extends BaseRMRestTest
STEP("Remove node from hold with user without right permission or capability"); STEP("Remove node from hold with user without right permission or capability");
String responseNoHoldPermission = holdsAPI.removeFromHoldAndGetMessage(userModel.getUsername(), String responseNoHoldPermission = holdsAPI.removeFromHoldAndGetMessage(userModel.getUsername(),
userModel.getPassword(), SC_INTERNAL_SERVER_ERROR, nodeIdToBeRemoved, HOLD_ONE); userModel.getPassword(), SC_INTERNAL_SERVER_ERROR, nodeIdToBeRemoved, holdNodeRefOne);
assertTrue(responseNoHoldPermission.contains(ACCESS_DENIED_ERROR_MESSAGE)); assertTrue(responseNoHoldPermission.contains(ACCESS_DENIED_ERROR_MESSAGE));
STEP("Check node is frozen."); STEP("Check node is frozen.");