diff --git a/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/core/v0/BaseAPI.java b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/core/v0/BaseAPI.java index 2306424f57..0785748fb5 100644 --- a/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/core/v0/BaseAPI.java +++ b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/core/v0/BaseAPI.java @@ -103,7 +103,7 @@ public abstract class BaseAPI */ protected List getPropertyValues(JSONObject result, String propertyName) { - ArrayList results = new ArrayList(); + ArrayList results = new ArrayList<>(); try { JSONArray items = result.getJSONArray("items"); @@ -541,7 +541,6 @@ public abstract class BaseAPI AlfrescoHttpClient client = alfrescoHttpClientFactory.getObject(); T request = requestType.newInstance(); - HttpResponse response = null; JSONObject responseBody = null; JSONObject returnValues = null; @@ -555,7 +554,7 @@ public abstract class BaseAPI } LOGGER.info("Sending {} request to {}", requestType.getSimpleName(), requestUrl); LOGGER.info("Request body: {}", requestParams); - response = client.execute(adminUser, adminPassword, request); + HttpResponse response = client.execute(adminUser, adminPassword, request); LOGGER.info("Response: {}", response.getStatusLine()); try @@ -587,13 +586,13 @@ public abstract class BaseAPI case HttpStatus.SC_UNPROCESSABLE_ENTITY: 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; } break; default: - LOGGER.error("Request returned unexpected HTTP status " + response.getStatusLine().getStatusCode()); + LOGGER.error("Request returned unexpected HTTP status {}", response.getStatusLine().getStatusCode()); break; } } diff --git a/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/rm/community/model/audit/AuditEvents.java b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/rm/community/model/audit/AuditEvents.java index 31d05ecece..37e89ee91d 100644 --- a/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/rm/community/model/audit/AuditEvents.java +++ b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/rm/community/model/audit/AuditEvents.java @@ -41,7 +41,11 @@ public enum AuditEvents DELETE_USER_GROUP("Delete User Group", "Delete 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"), - 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 */ public final String event; diff --git a/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/HoldsAPI.java b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/HoldsAPI.java index 113eb01cb5..c16fd352c2 100644 --- a/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/HoldsAPI.java +++ b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/HoldsAPI.java @@ -28,7 +28,6 @@ package org.alfresco.rest.v0; import static org.alfresco.rest.core.v0.APIUtils.convertHTTPResponseToJSON; import static org.apache.http.HttpStatus.SC_OK; -import static org.testng.AssertJUnit.assertNotNull; import java.text.MessageFormat; 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.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.alfresco.utility.model.UserModel; import org.apache.http.HttpResponse; import org.apache.http.ParseException; import org.json.JSONArray; @@ -81,18 +79,27 @@ public class HoldsAPI extends BaseAPI * @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). + * @return The HTTP response. */ - public HttpResponse createHold(String user, String password, - String holdName, String reason, String description) + public HttpResponse createHold(String user, String password, String holdName, String reason, String description) + { + return createHold(user, password, holdName, reason, description, SC_OK); + } + + /** + * 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) { - // 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); @@ -102,11 +109,7 @@ public class HoldsAPI extends BaseAPI 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; + return doPostJsonRequest(user, password, expectedStatusCode, requestParams, CREATE_HOLDS_API); } /** @@ -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 password its password @@ -179,7 +211,10 @@ public class HoldsAPI extends BaseAPI */ public HttpResponse addItemsToHolds(String user, String password, List itemNodeRefs, List holdNames) { - return addItemsToHolds(user, password, SC_OK, itemNodeRefs, holdNames); + final List 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 password the user's password * @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 */ public HttpResponse addItemsToHolds(String user, String password, int expectedStatus, List itemNodeRefs, - List holdNames) + List holdNodeRefs) { - final JSONObject requestParams = addOrRemoveToFromHoldJsonObject(user, password, itemNodeRefs, holdNames); + final JSONObject requestParams = addOrRemoveToFromHoldJsonObject(itemNodeRefs, holdNodeRefs); 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 password the user's password * @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 */ public String addToHoldAndGetMessage(String user, String password, int expectedStatus, String itemNodeRef, String - holdName) + holdNodeRef) { final HttpResponse httpResponse = addItemsToHolds(user, password, expectedStatus, Collections.singletonList(itemNodeRef), - Collections.singletonList(holdName)); + Collections.singletonList(holdNodeRef)); return APIUtils.extractErrorMessageFromHttpResponse(httpResponse); } /** * 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 holdNames list of hold names for add/remove items + * @param items list of items node refs to be added to holds + * @param holdNodeRefs list of hold node refs for add/remove items * @return JSONObject fo */ - private JSONObject addOrRemoveToFromHoldJsonObject(String user, String password, List items, List holdNames) + private JSONObject addOrRemoveToFromHoldJsonObject(List items, List holdNodeRefs) { final JSONArray nodeRefs = new JSONArray(); items.forEach(itemNodeRef -> nodeRefs.put(getNodeRefSpacesStore() + itemNodeRef)); - final List 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); + holdNodeRefs.forEach(holdNodeRef -> holds.put(getNodeRefSpacesStore() + holdNodeRef)); final JSONObject requestParams = new JSONObject(); requestParams.put("nodeRefs", nodeRefs); requestParams.put("holds", holds); @@ -264,7 +294,10 @@ public class HoldsAPI extends BaseAPI */ public HttpResponse removeItemsFromHolds(String user, String password, List itemNodeRefs, List holdNames) { - return removeItemsFromHolds(user, password, SC_OK, itemNodeRefs, holdNames); + final List 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 expectedStatus https status code expected * @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 */ public HttpResponse removeItemsFromHolds(String user, String password, int expectedStatus, List itemNodeRefs, - List holdNames) + List holdNodeRefs) { - final JSONObject requestParams = addOrRemoveToFromHoldJsonObject(user, password, itemNodeRefs, holdNames); + final JSONObject requestParams = addOrRemoveToFromHoldJsonObject(itemNodeRefs, holdNodeRefs); 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 password the user's password * @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 */ public String removeFromHoldAndGetMessage(String user, String password, int expectedStatus, String itemNodeRef, String - holdName) + holdNodeRef) { final HttpResponse httpResponse = removeItemsFromHolds(user, password, expectedStatus, Collections.singletonList(itemNodeRef), - Collections.singletonList(holdName)); + Collections.singletonList(holdNodeRef)); return APIUtils.extractErrorMessageFromHttpResponse(httpResponse); } diff --git a/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/service/RMAuditService.java b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/service/RMAuditService.java new file mode 100644 index 0000000000..3f9c303d0c --- /dev/null +++ b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/service/RMAuditService.java @@ -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 . + * #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 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 changedValues) + { + final Instant eventTimestamp = Instant.now(); + List 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 changedValues) + { + final Instant eventTimestamp = Instant.now(); + List 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)); + } +} diff --git a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditAddToHoldTests.java b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditAddToHoldTests.java new file mode 100644 index 0000000000..0d63ac5002 --- /dev/null +++ b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditAddToHoldTests.java @@ -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 . + * #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 auditEntries; + private List 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()); + } +} diff --git a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditCreateHoldTests.java b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditCreateHoldTests.java new file mode 100644 index 0000000000..a316ed2b7c --- /dev/null +++ b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditCreateHoldTests.java @@ -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 . + * #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 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 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)); + } +} diff --git a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditDeleteHoldTests.java b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditDeleteHoldTests.java new file mode 100644 index 0000000000..1118f66599 --- /dev/null +++ b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditDeleteHoldTests.java @@ -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 . + * #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)); + } +} diff --git a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditGroupEventsTests.java b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditGroupEventsTests.java index 3443630bb6..055f138650 100644 --- a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditGroupEventsTests.java +++ b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditGroupEventsTests.java @@ -26,20 +26,20 @@ */ 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.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.REMOVE_FROM_USER_GROUP; 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.model.audit.AuditEntry; -import org.alfresco.rest.v0.RMAuditAPI; +import org.alfresco.rest.v0.service.RMAuditService; import org.alfresco.test.AlfrescoTest; import org.alfresco.utility.model.GroupModel; import org.alfresco.utility.model.UserModel; @@ -57,16 +57,14 @@ import org.testng.annotations.Test; public class AuditGroupEventsTests extends BaseRMRestTest { @Autowired - private RMAuditAPI rmAuditAPI; - + private RMAuditService rmAuditService; private GroupModel testGroup; private UserModel testUser; @BeforeClass (alwaysRun = true) public void cleanAuditLogs() { - //clean audit logs - rmAuditAPI.clearAuditLog(getAdminUser().getUsername(), getAdminUser().getPassword()); + rmAuditService.clearAuditLog(); } /** @@ -79,17 +77,10 @@ public class AuditGroupEventsTests extends BaseRMRestTest { testGroup = dataGroup.createRandomGroup(); - STEP("Get the list of audit entries for the create group event."); - List auditEntries = rmAuditAPI.getRMAuditLog(getAdminUser().getUsername(), - getAdminUser().getPassword(), 100, CREATE_USER_GROUP.event); - - 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()))); + STEP("Check the audit log contains the entry for the created group."); + rmAuditService.checkAuditLogForEvent(getAdminUser(), CREATE_USER_GROUP, getAdminUser(), testGroup.getGroupIdentifier(), + Collections.singletonList(ImmutableMap.of("new", testGroup.getGroupIdentifier(), "previous", "", + "name", "authorityDisplayName"))); } /** @@ -104,19 +95,10 @@ public class AuditGroupEventsTests extends BaseRMRestTest testUser = getDataUser().createRandomTestUser(); dataGroup.usingUser(testUser).addUserToGroup(testGroup); - STEP("Get the list of audit entries for the add user to group event."); - List auditEntries = rmAuditAPI.getRMAuditLog(getAdminUser().getUsername(), - getAdminUser().getPassword(), 100, ADD_TO_USER_GROUP.event); - - 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")))); + STEP("Check the audit log contains the entry for the add user to group event."); + rmAuditService.checkAuditLogForEvent(getAdminUser(), ADD_TO_USER_GROUP, getAdminUser(), testGroup.getGroupIdentifier(), + asList(ImmutableMap.of("new", testUser.getUsername(), "previous", "", "name", "User Name"), + ImmutableMap.of("new", testGroup.getGroupIdentifier(), "previous", "", "name", "Parent Group"))); } /** @@ -132,19 +114,10 @@ public class AuditGroupEventsTests extends BaseRMRestTest dataGroup.usingUser(testUser).addUserToGroup(testGroup); dataGroup.removeUserFromGroup(testGroup, testUser); - STEP("Get the list of audit entries for the add user to group event."); - List auditEntries = rmAuditAPI.getRMAuditLog(getAdminUser().getUsername(), - getAdminUser().getPassword(), 100, REMOVE_FROM_USER_GROUP.event); - - 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")))); + STEP("Check the audit log contains the entry for the remove user from group event."); + rmAuditService.checkAuditLogForEvent(getAdminUser(), REMOVE_FROM_USER_GROUP, getAdminUser(), testGroup.getGroupIdentifier(), + asList(ImmutableMap.of("new", "", "previous", testUser.getUsername(), "name", "User Name"), + ImmutableMap.of("new", "","previous", testGroup.getGroupIdentifier(), "name", "Parent Group"))); } /** @@ -158,17 +131,9 @@ public class AuditGroupEventsTests extends BaseRMRestTest testGroup = dataGroup.createRandomGroup(); dataGroup.deleteGroup(testGroup); - STEP("Get the list of audit entries for the delete group event."); - List auditEntries = rmAuditAPI.getRMAuditLog(getAdminUser().getUsername(), - getAdminUser().getPassword(), 100, DELETE_USER_GROUP.event); - - 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")))); + STEP("Check the audit log contains the entry for the delete group event."); + rmAuditService.checkAuditLogForEvent(getAdminUser(), DELETE_USER_GROUP, getAdminUser(), testGroup.getGroupIdentifier(), + Collections.singletonList(ImmutableMap.of("new", "", "previous", testGroup.getGroupIdentifier(), + "name", "authorityDisplayName"))); } } diff --git a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditLoginEventsTests.java b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditLoginEventsTests.java index 12b445b3e3..5dcffe5347 100644 --- a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditLoginEventsTests.java +++ b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditLoginEventsTests.java @@ -34,11 +34,10 @@ import java.util.List; import org.alfresco.rest.rm.community.base.BaseRMRestTest; 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.utility.model.UserModel; import org.springframework.beans.factory.annotation.Autowired; -import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; /** @@ -51,14 +50,7 @@ import org.testng.annotations.Test; public class AuditLoginEventsTests extends BaseRMRestTest { @Autowired - private RMAuditAPI rmAuditAPI; - - @BeforeClass (alwaysRun = true) - public void cleanAuditLogs() - { - //clean audit logs - rmAuditAPI.clearAuditLog(getAdminUser().getUsername(), getAdminUser().getPassword()); - } + private RMAuditService rmAuditService; /** * Given I have tried to login using invalid credentials @@ -68,12 +60,13 @@ public class AuditLoginEventsTests extends BaseRMRestTest @Test public void filterByLoginUnsuccessful() throws Exception { + rmAuditService.clearAuditLog(); restClient.authenticateUser(new UserModel(getAdminUser().getUsername(), "InvalidPassword")); restClient.withCoreAPI().getSites(); STEP("Get the list of audit entries for the login unsuccessful event."); - List auditEntries = rmAuditAPI.getRMAuditLog(getAdminUser().getUsername(), - getAdminUser().getPassword(), 100, LOGIN_UNSUCCESSFUL.event); + List auditEntries = rmAuditService.getAuditEntriesFilteredByEvent(getAdminUser(), + LOGIN_UNSUCCESSFUL); 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, diff --git a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditRemoveFromHoldTests.java b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditRemoveFromHoldTests.java new file mode 100644 index 0000000000..7fa655f79b --- /dev/null +++ b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditRemoveFromHoldTests.java @@ -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 . + * #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 auditEntries; + private List 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()); + } +} diff --git a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditUserEventsTests.java b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditUserEventsTests.java index a71094bcd7..3f7b668a9a 100644 --- a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditUserEventsTests.java +++ b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditUserEventsTests.java @@ -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.util.CommonTestUtils.generateTestPrefix; 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.model.audit.AuditEntry; -import org.alfresco.rest.v0.RMAuditAPI; +import org.alfresco.rest.v0.service.RMAuditService; 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; /** @@ -52,10 +51,9 @@ import org.testng.annotations.Test; public class AuditUserEventsTests extends BaseRMRestTest { private final String PREFIX = generateTestPrefix(AuditUserEventsTests.class); - private UserModel createUser; @Autowired - private RMAuditAPI rmAuditAPI; + private RMAuditService rmAuditService; /** * Given I have created a new user @@ -66,30 +64,16 @@ public class AuditUserEventsTests extends BaseRMRestTest */ @Test @AlfrescoTest(jira = "RM-6223") - public void createUserEventIsAudited() throws Exception + public void createUserEventIsAudited() { + rmAuditService.clearAuditLog(); STEP("Create a new user."); String userName = "auditCreateUser" + PREFIX; createUser = getDataUser().createUser(userName); - STEP("Get the list of audit entries for the create person event."); - List auditEntries = rmAuditAPI.getRMAuditLog(getAdminUser().getUsername(), - getAdminUser().getPassword(), 100, CREATE_PERSON.event); - - 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()); + STEP("Check the audit log contains the entry for the created user event."); + rmAuditService.checkAuditLogForEvent(getAdminUser(), CREATE_PERSON, getAdminUser(), userName, + Collections.singletonList(ImmutableMap.of("new", userName, "previous", "", "name", "User Name"))); } @AfterClass (alwaysRun = true) diff --git a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/base/BaseRMRestTest.java b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/base/BaseRMRestTest.java index 96ddd592b2..037c6ce73d 100644 --- a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/base/BaseRMRestTest.java +++ b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/base/BaseRMRestTest.java @@ -615,37 +615,6 @@ public class BaseRMRestTest extends RestTest 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 * diff --git a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/files/DeclareAndFileDocumentAsRecordTests.java b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/files/DeclareAndFileDocumentAsRecordTests.java index e6bee2c556..26188acb08 100644 --- a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/files/DeclareAndFileDocumentAsRecordTests.java +++ b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/files/DeclareAndFileDocumentAsRecordTests.java @@ -26,6 +26,8 @@ */ 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.TRANSFERS_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 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 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 UserModel userFillingPermission, userReadOnlyPermission; @@ -411,8 +413,7 @@ public class DeclareAndFileDocumentAsRecordTests extends BaseRMRestTest public void declareAndFileToHeldRecordFolderUsingFilesAPI() throws Exception { RecordCategoryChild heldRecordFolder = createFolder(recordCategory.getId(), getRandomName("heldRecordFolder")); - holdsAPI.createHold(getAdminUser().getUsername(), getAdminUser().getPassword(), HOLD_NAME, "hold reason", - "hold description"); + holdsAPI.createHold(getAdminUser().getUsername(), getAdminUser().getPassword(), HOLD_NAME, HOLD_REASON, HOLD_DESCRIPTION); holdsAPI.addItemToHold(getAdminUser().getUsername(), getAdminUser().getPassword(), heldRecordFolder.getId(), HOLD_NAME); diff --git a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/hold/AddToHoldsTests.java b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/hold/AddToHoldsTests.java index 2476370482..3803749525 100644 --- a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/hold/AddToHoldsTests.java +++ b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/hold/AddToHoldsTests.java @@ -108,7 +108,7 @@ public class AddToHoldsTests extends BaseRMRestTest private ContentActions contentActions; @BeforeClass (alwaysRun = true) - public void preconditionForAddContentToHold() throws Exception + public void preconditionForAddContentToHold() { STEP("Create a hold."); holdNodeRef = holdsAPI.createHoldAndGetNodeRef(getAdminUser().getUsername(), getAdminUser().getUsername(), @@ -174,7 +174,7 @@ public class AddToHoldsTests extends BaseRMRestTest * Valid nodes to be added to hold */ @DataProvider (name = "validNodesForAddToHold") - public Object[][] getValidNodesForAddToHold() throws Exception + public Object[][] getValidNodesForAddToHold() { //create electronic and nonElectronic record in record folder RecordCategoryChild recordFolder = createCategoryFolderInFilePlan(); @@ -287,7 +287,7 @@ public class AddToHoldsTests extends BaseRMRestTest users.add(userModel); STEP("Add the node to the hold with user without permission."); 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)); STEP("Check the node is not frozen."); @@ -345,7 +345,7 @@ public class AddToHoldsTests extends BaseRMRestTest { STEP("Add the node to the hold "); String responseErrorMessage = holdsAPI.addToHoldAndGetMessage(getAdminUser().getUsername(), - getAdminUser().getPassword(), responseCode, itemNodeRef, HOLD); + getAdminUser().getPassword(), responseCode, itemNodeRef, holdNodeRef); assertTrue(responseErrorMessage.contains(errorMessage), "Actual error message " + responseErrorMessage + " expected " + errorMessage); @@ -354,7 +354,7 @@ public class AddToHoldsTests extends BaseRMRestTest } @AfterClass (alwaysRun = true) - public void cleanUpAddContentToHold() throws Exception + public void cleanUpAddContentToHold() { holdsAPI.deleteHold(getAdminUser().getUsername(), getAdminUser().getPassword(), HOLD); dataSite.usingAdmin().deleteSite(testSite); diff --git a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/hold/RemoveFromHoldsTests.java b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/hold/RemoveFromHoldsTests.java index c23b244b7d..78146056c3 100644 --- a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/hold/RemoveFromHoldsTests.java +++ b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/hold/RemoveFromHoldsTests.java @@ -95,12 +95,12 @@ public class RemoveFromHoldsTests extends BaseRMRestTest private RoleService roleService; @BeforeClass (alwaysRun = true) - public void preconditionForRemoveContentFromHold() throws Exception + public void preconditionForRemoveContentFromHold() { STEP("Create two holds."); holdNodeRefOne = holdsAPI.createHoldAndGetNodeRef(getAdminUser().getUsername(), getAdminUser().getUsername(), 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); 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"); 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)); STEP("Check node is frozen.");