From 37ff2cb2af47b24bd1656ff99575bade2a83060b Mon Sep 17 00:00:00 2001 From: Alex Mukha Date: Mon, 21 Aug 2017 23:50:22 +0100 Subject: [PATCH] REPO-2669 - REST API: Retrieve Node (alfresco-access) Audit Entries - add detailed JUnit tests (+ve & -ve): - refactored the tests to minimize code duplication --- .../alfresco/rest/api/tests/AuditAppTest.java | 654 +++++++++++++++--- 1 file changed, 575 insertions(+), 79 deletions(-) diff --git a/src/test/java/org/alfresco/rest/api/tests/AuditAppTest.java b/src/test/java/org/alfresco/rest/api/tests/AuditAppTest.java index c7fbc2e97a..3991b2cbb3 100644 --- a/src/test/java/org/alfresco/rest/api/tests/AuditAppTest.java +++ b/src/test/java/org/alfresco/rest/api/tests/AuditAppTest.java @@ -27,74 +27,88 @@ package org.alfresco.rest.api.tests; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.net.URL; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Random; import javax.servlet.http.HttpServletResponse; +import org.alfresco.repo.audit.model.AuditModelRegistryImpl; import org.alfresco.repo.security.authentication.AuthenticationException; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; import org.alfresco.rest.AbstractSingleNetworkSiteTest; -import org.alfresco.rest.api.tests.client.PublicApiException; -import org.alfresco.rest.api.tests.client.data.AuditEntry; +import org.alfresco.rest.api.tests.RepoService.TestSite; import org.alfresco.rest.api.tests.client.PublicApiClient; import org.alfresco.rest.api.tests.client.PublicApiClient.AuditApps; import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse; import org.alfresco.rest.api.tests.client.PublicApiClient.Paging; +import org.alfresco.rest.api.tests.client.PublicApiException; import org.alfresco.rest.api.tests.client.data.AuditApp; +import org.alfresco.rest.api.tests.client.data.AuditEntry; +import org.alfresco.rest.framework.resource.parameters.SortColumn; import org.alfresco.service.cmr.audit.AuditService; +import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.security.AuthorityService; import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.cmr.site.SiteVisibility; +import org.alfresco.util.ISO8601DateFormat; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.springframework.util.ResourceUtils; -public class AuditAppTest extends AbstractSingleNetworkSiteTest +/** + * @author anechifor, aforascu, eknizat + */ +public class AuditAppTest extends AbstractSingleNetworkSiteTest { - protected PermissionService permissionService; protected AuthorityService authorityService; protected AuditService auditService; + protected static String AUDIT_APP_ID = "alfresco-access"; @Before - public void setup() throws Exception + public void setup() throws Exception { super.setup(); permissionService = applicationContext.getBean("permissionService", PermissionService.class); authorityService = (AuthorityService) applicationContext.getBean("AuthorityService"); auditService = applicationContext.getBean("AuditService", AuditService.class); + + AuditModelRegistryImpl auditModelRegistry = (AuditModelRegistryImpl) applicationContext.getBean("auditModel.modelRegistry"); + + // Register the test model + URL testModelUrl = ResourceUtils.getURL("classpath:alfresco/audit/alfresco-audit-access.xml"); + auditModelRegistry.registerModel(testModelUrl); + auditModelRegistry.loadAuditModels(); } @After - public void tearDown() throws Exception + public void tearDown() throws Exception { super.tearDown(); } @Test - public void testGetAuditApps() throws Exception + public void testGetAuditApps() throws Exception { - try - { - - setRequestContext(networkOne.getId(), networkAdmin, DEFAULT_ADMIN_PWD); - testGetAuditAppsSkipPaging(); - - } - finally - { - - } + setRequestContext(networkOne.getId(), networkAdmin, DEFAULT_ADMIN_PWD); + testGetAuditAppsSkipPaging(); } @Test - public void testGetAuditApp() throws Exception + public void testGetAuditApp() throws Exception { final AuditApps auditAppsProxy = publicApiClient.auditApps(); @@ -118,7 +132,8 @@ public class AuditAppTest extends AbstractSingleNetworkSiteTest auditAppsProxy.getAuditApp("randomAuditId", HttpServletResponse.SC_FORBIDDEN); } - // Check that response code 501 is received when system audit is disabled + // Check that response code 501 is received when system audit is + // disabled { // Get an enabled audit application setRequestContext(networkOne.getId(), networkAdmin, DEFAULT_ADMIN_PWD); @@ -144,11 +159,10 @@ public class AuditAppTest extends AbstractSingleNetworkSiteTest } } - private void testGetAuditAppsSkipPaging() throws Exception + private void testGetAuditAppsSkipPaging() throws Exception { // +ve: check skip count. { - // Paging and list auditApp int skipCount = 0; @@ -176,27 +190,28 @@ public class AuditAppTest extends AbstractSingleNetworkSiteTest } - private ListResponse getAuditApps(final PublicApiClient.Paging paging, String errorMessage, int expectedStatus) throws Exception + private ListResponse getAuditApps(final PublicApiClient.Paging paging, String errorMessage, + int expectedStatus) throws Exception { final AuditApps auditAppsProxy = publicApiClient.auditApps(); return auditAppsProxy.getAuditApps(createParams(paging), errorMessage, expectedStatus); } - private ListResponse getAuditApps(final PublicApiClient.Paging paging) throws Exception + private ListResponse getAuditApps(final PublicApiClient.Paging paging) throws Exception { return getAuditApps(paging, "Failed to get audit applications", HttpServletResponse.SC_OK); } - protected Map createParams(Paging paging) + protected Map createParams(Paging paging) { Map params = new HashMap(2); - if (paging != null) + if (paging != null) { - if (paging.getSkipCount() != null) + if (paging.getSkipCount() != null) { params.put("skipCount", String.valueOf(paging.getSkipCount())); } - if (paging.getMaxItems() != null) + if (paging.getMaxItems() != null) { params.put("maxItems", String.valueOf(paging.getMaxItems())); } @@ -205,7 +220,7 @@ public class AuditAppTest extends AbstractSingleNetworkSiteTest return params; } - private void validateAuditApplicationFields(AuditApp auditApp) + private void validateAuditApplicationFields(AuditApp auditApp) { assertNotNull(auditApp); assertNotNull(auditApp.getId()); @@ -216,7 +231,7 @@ public class AuditAppTest extends AbstractSingleNetworkSiteTest assertTrue(auditApp.getIsEnabled()); } - private void validateAuditEntryFields(AuditEntry auditEntry, AuditApp auditApp) + private void validateAuditEntryFields(AuditEntry auditEntry, AuditApp auditApp) { String auditAppid = auditApp.getId(); @@ -228,17 +243,19 @@ public class AuditAppTest extends AbstractSingleNetworkSiteTest assertFalse(auditEntry.getId().toString().isEmpty()); assertFalse(auditEntry.getAuditApplicationId().isEmpty()); - if (auditApp.getId().equals("alfresco-access")) + if (auditApp.getId().equals(AUDIT_APP_ID)) { assertTrue(auditEntry.getAuditApplicationId().toString().equals(auditAppid)); } } - - private String getFirstAuditAppId() throws PublicApiException + + private String getFirstAuditAppId() throws PublicApiException { - // Get one of the audit app ids ( fail test if there are no audit apps in the system ) - ListResponse apps = publicApiClient.auditApps().getAuditApps(null, "Getting audit apps error ", HttpServletResponse.SC_OK); - if (apps.getList().size() == 0) + // Get one of the audit app ids ( fail test if there are no audit apps + // in the system ) + ListResponse apps = publicApiClient.auditApps().getAuditApps(null, "Getting audit apps error ", + HttpServletResponse.SC_OK); + if (apps.getList().size() == 0) { fail("There are no audit applications to run this test against."); } @@ -246,7 +263,7 @@ public class AuditAppTest extends AbstractSingleNetworkSiteTest } @Test - public void testEnableDisableAuditApplication() throws Exception + public void testEnableDisableAuditApplication() throws Exception { AuditApp requestAuditApp = new AuditApp(); AuditApp responseAuditApp = null; @@ -257,97 +274,98 @@ public class AuditAppTest extends AbstractSingleNetworkSiteTest // +ve // Disable audit app requestAuditApp.setIsEnabled(false); - responseAuditApp = publicApiClient.auditApps().updateAuditApp(appId,requestAuditApp,null, HttpServletResponse.SC_OK); + responseAuditApp = publicApiClient.auditApps().updateAuditApp(appId, requestAuditApp, null, + HttpServletResponse.SC_OK); assertFalse("Wrong response for request to disable audit app.", responseAuditApp.getIsEnabled()); assertFalse("Disable audit app test failed.", publicApiClient.auditApps().getAuditApp(appId).getIsEnabled()); // Enable audit app requestAuditApp.setIsEnabled(true); - responseAuditApp = publicApiClient.auditApps().updateAuditApp(appId,requestAuditApp,null, HttpServletResponse.SC_OK); + responseAuditApp = publicApiClient.auditApps().updateAuditApp(appId, requestAuditApp, null, + HttpServletResponse.SC_OK); assertTrue("Wrong response for request to enable audit app.", responseAuditApp.getIsEnabled()); assertTrue("Enable audit app test failed.", publicApiClient.auditApps().getAuditApp(appId).getIsEnabled()); // -ve // 400 - publicApiClient.auditApps().update("audit-applications",appId,null,null,"badBody",null,"Was expecting error 400",HttpServletResponse.SC_BAD_REQUEST); + publicApiClient.auditApps().update("audit-applications", appId, null, null, "badBody", null, + "Was expecting error 400", HttpServletResponse.SC_BAD_REQUEST); // 401 setRequestContext(networkOne.getId(), networkAdmin, "fakepswd"); - publicApiClient.auditApps().updateAuditApp(appId,requestAuditApp,null, HttpServletResponse.SC_UNAUTHORIZED); + publicApiClient.auditApps().updateAuditApp(appId, requestAuditApp, null, HttpServletResponse.SC_UNAUTHORIZED); // 403 setRequestContext(networkOne.getId(), user1, null); - publicApiClient.auditApps().updateAuditApp(appId,requestAuditApp,null, HttpServletResponse.SC_FORBIDDEN); + publicApiClient.auditApps().updateAuditApp(appId, requestAuditApp, null, HttpServletResponse.SC_FORBIDDEN); // 404 setRequestContext(networkOne.getId(), networkAdmin, DEFAULT_ADMIN_PWD); - publicApiClient.auditApps().updateAuditApp("fakeid",requestAuditApp,null, HttpServletResponse.SC_NOT_FOUND); + publicApiClient.auditApps().updateAuditApp("fakeid", requestAuditApp, null, HttpServletResponse.SC_NOT_FOUND); // 501 AuthenticationUtil.setFullyAuthenticatedUser(networkAdmin); disableSystemAudit(); - publicApiClient.auditApps().updateAuditApp(appId,requestAuditApp,null, HttpServletResponse.SC_NOT_IMPLEMENTED); + publicApiClient.auditApps().updateAuditApp(appId, requestAuditApp, null, + HttpServletResponse.SC_NOT_IMPLEMENTED); enableSystemAudit(); } - protected void enableSystemAudit() + protected void enableSystemAudit() { boolean isEnabled = auditService.isAuditEnabled(); - if (!isEnabled) + if (!isEnabled) { auditService.setAuditEnabled(true); isEnabled = auditService.isAuditEnabled(); - if (!isEnabled) + if (!isEnabled) { fail("Failed to enable system audit for testing"); } } - } - protected void disableSystemAudit() + protected void disableSystemAudit() { boolean isEnabled = auditService.isAuditEnabled(); - if (isEnabled) + if (isEnabled) { auditService.setAuditEnabled(false); isEnabled = auditService.isAuditEnabled(); - if (isEnabled) + if (isEnabled) { fail("Failed to disable system audit for testing"); } } - } @Test - public void testGetAuditEntries() throws Exception + public void testAuditEntries() throws Exception { final AuditApps auditAppsProxy = publicApiClient.auditApps(); // Get and enable audit app setRequestContext(networkOne.getId(), networkAdmin, DEFAULT_ADMIN_PWD); + AuditApp auditApp = auditAppsProxy.getAuditApp("alfresco-access"); - // TODO note "alfresco-access" apparently fails on build m/c - is it enabled by default (will also be required later for "retrieve node audit entries" ? - //AuditApp auditApp = auditAppsProxy.getAuditApp("alfresco-access"); - AuditApp auditApp = auditAppsProxy.getAuditApp(getFirstAuditAppId()); - - // TODO - make sure we've have recorded audit entries - // TODO - test filtering, sorting, paging, include values .. etc (note: need audit entries to be recorded) + testGetAuditEntries(auditAppsProxy, auditApp); + testAuditEntriesSorting(auditAppsProxy, auditApp); + testAuditEntriesWhereDate(auditAppsProxy, auditApp); + testAuditEntriesWhereId(auditAppsProxy, auditApp); + testAuditEntriesWithInclude(auditAppsProxy, auditApp); + testAuditEntriesSkipCount(auditAppsProxy, auditApp); + testRetrieveAuditEntry(auditAppsProxy, auditApp); + testDeleteAuditEntry(auditAppsProxy, auditApp); + testDeleteAuditEntries(auditAppsProxy, auditApp); + } + private void testGetAuditEntries(AuditApps auditAppsProxy, AuditApp auditApp) throws Exception + { // Positive tests - ListResponse auditEntries = auditAppsProxy.getAuditAppEntries(auditApp.getId(), null, HttpServletResponse.SC_OK); - // assertTrue(auditEntries.getList().size() > 0); // TODO - for (AuditEntry ae : auditEntries.getList()) + ListResponse auditEntries = auditAppsProxy.getAuditAppEntries(auditApp.getId(), null, + HttpServletResponse.SC_OK); + for (AuditEntry ae : auditEntries.getList()) { validateAuditEntryFields(ae, auditApp); } // Negative tests - // 400 - // TODO - remove comment after fix is done - //Map wrongParams = new HashMap(); - //wrongParams.put("wrongkey", "wrongvalue"); - //wrongParams.put("wrongkey1", "wrongvalue1"); - - //setRequestContext(networkOne.getId(), networkAdmin, DEFAULT_ADMIN_PWD); - //auditAppsProxy.getAuditAppEntries(auditApp.getId(), wrongParams, HttpServletResponse.SC_BAD_REQUEST); // 401 setRequestContext(networkOne.getId(), networkAdmin, "wrongPassword"); auditAppsProxy.getAuditAppEntries(auditApp.getId(), null, HttpServletResponse.SC_UNAUTHORIZED); @@ -355,9 +373,8 @@ public class AuditAppTest extends AbstractSingleNetworkSiteTest setRequestContext(networkOne.getId(), user1, null); auditAppsProxy.getAuditAppEntries(auditApp.getId(), null, HttpServletResponse.SC_FORBIDDEN); // 404 - // TODO - remove comment after fix is done - //setRequestContext(networkOne.getId(), networkAdmin, DEFAULT_ADMIN_PWD); - //auditAppsProxy.getAuditAppEntries("randomId", null, HttpServletResponse.SC_NOT_FOUND); + setRequestContext(networkOne.getId(), networkAdmin, DEFAULT_ADMIN_PWD); + auditAppsProxy.getAuditAppEntries("randomId", null, HttpServletResponse.SC_NOT_FOUND); // 501 setRequestContext(networkOne.getId(), networkAdmin, DEFAULT_ADMIN_PWD); AuthenticationUtil.setFullyAuthenticatedUser(networkAdmin); @@ -366,23 +383,294 @@ public class AuditAppTest extends AbstractSingleNetworkSiteTest enableSystemAudit(); } + private void testAuditEntriesSorting(AuditApps auditAppsProxy, AuditApp auditApp) throws Exception + { + // paging + Paging paging = getPaging(0, 10); + Map otherParams = new HashMap<>(); + + // Default order. + addOrderBy(otherParams, org.alfresco.rest.api.Audit.CREATED_AT, null); + ListResponse auditEntries = auditAppsProxy.getAuditAppEntries(auditApp.getId(), + createParams(paging, otherParams), HttpServletResponse.SC_OK); + assertNotNull(auditEntries); + assertTrue("audit entry size more that 2", auditEntries.getList().size() > 1); + assertTrue("auditEntries order not valid", + auditEntries.getList().get(0).getCreatedAt().before(auditEntries.getList().get(1).getCreatedAt())); + + } + + private void testAuditEntriesWhereDate(AuditApps auditAppsProxy, AuditApp auditApp) throws Exception + { + // paging + Paging paging = getPaging(0, 10); + + Date dateBefore = new Date(); + + String dateBeforeWhere = ISO8601DateFormat.format(dateBefore); + + createUser("usern-" + RUNID, "userNPassword", networkOne); + + login("usern-" + RUNID, "userNPassword"); + + Date dateAfter = new Date(); + + String dateAfterWhere = ISO8601DateFormat.format(dateAfter); + + Map otherParams = new HashMap<>(); + otherParams.put("where", "(" + org.alfresco.rest.api.Audit.CREATED_AT + " between (" + "\'" + dateBeforeWhere + "\'" + ", " + "\'" + + dateAfterWhere + "\'" + "))"); + + ListResponse auditEntries = auditAppsProxy.getAuditAppEntries(auditApp.getId(), createParams(paging, otherParams), + HttpServletResponse.SC_OK); + assertNotNull(auditEntries); + assertTrue(auditEntries.getList().size() > 0); + + for (AuditEntry ae : auditEntries.getList()) + { + validateAuditEntryFields(ae, auditApp); + } + + // + // note: sanity test parsing of a few ISO8601 formats (non-exhaustive) - eg. +01:00, +0000, Z + // + + otherParams.put("where", "(" + org.alfresco.rest.api.Audit.CREATED_AT + " between (" + + "\'2016-06-02T12:13:51.593+01:00\'" + ", " + "\'2017-06-04T10:05:16.536+01:00\'" + "))"); + auditAppsProxy.getAuditAppEntries(auditApp.getId(), createParams(paging, otherParams), HttpServletResponse.SC_OK); + + otherParams.put("where", "(" + org.alfresco.rest.api.Audit.CREATED_AT + " between (" + + "\'2016-06-02T11:13:51.593+0000\'" + ", " + "\'2017-06-04T09:05:16.536+0000\'" + "))"); + auditAppsProxy.getAuditAppEntries(auditApp.getId(), createParams(paging, otherParams), HttpServletResponse.SC_OK); + + otherParams.put("where", "(" + org.alfresco.rest.api.Audit.CREATED_AT + " between (" + + "\'2016-06-02T11:13:51.593Z\'" + ", " + "\'2017-06-04T09:05:16.536Z\'" + "))"); + auditAppsProxy.getAuditAppEntries(auditApp.getId(), createParams(paging, otherParams), HttpServletResponse.SC_OK); + + // Negative tests + otherParams = new HashMap<>(); + otherParams.put("where", "(" + org.alfresco.rest.api.Audit.CREATED_AT + " between (" + + "\'2017-06-04T10:05:16.536+01:00\'" + ", " + "\'2016-06-02T12:13:51.593+01:00\'" + "))"); + auditAppsProxy.getAuditAppEntries(auditApp.getId(), createParams(paging, otherParams), HttpServletResponse.SC_BAD_REQUEST); + } + + private void testAuditEntriesWhereId(AuditApps auditAppsProxy, AuditApp auditApp) throws Exception + { + // paging + Paging paging = getPaging(0, 10); + + // where params + Map otherParams = new HashMap<>(); + otherParams.put("where", "(" + org.alfresco.rest.api.Audit.ID + " between (" + "\'1\' , \'10\'" + "))"); + + ListResponse auditEntries = auditAppsProxy.getAuditAppEntries(auditApp.getId(), + createParams(paging, otherParams), HttpServletResponse.SC_OK); + assertNotNull(auditEntries); + + // Negative tests + otherParams = new HashMap<>(); + otherParams.put("where", "(" + org.alfresco.rest.api.Audit.CREATED_AT + " between between (" + "\'10\' , \'1\'" + "))"); + auditAppsProxy.getAuditAppEntries(auditApp.getId(), createParams(paging, otherParams), HttpServletResponse.SC_BAD_REQUEST); + } + + private void testAuditEntriesWithInclude(AuditApps auditAppsProxy, AuditApp auditApp) throws Exception + { + Paging paging = getPaging(0, 10); + Map otherParams = new HashMap<>(); + ListResponse auditEntriesWithoutValues = auditAppsProxy.getAuditAppEntries(auditApp.getId(), createParams(paging, otherParams), + HttpServletResponse.SC_OK); + assertNotNull(auditEntriesWithoutValues); + + for (AuditEntry ae : auditEntriesWithoutValues.getList()) + { + validateAuditEntryFields(ae, auditApp); + assertNull(ae.getValues()); + } + + otherParams.put("include", org.alfresco.rest.api.Audit.PARAM_INCLUDE_VALUES); + // list auditEntries with values + ListResponse auditEntriesWithValues = auditAppsProxy.getAuditAppEntries(auditApp.getId(), createParams(paging, otherParams), + HttpServletResponse.SC_OK); + assertNotNull(auditEntriesWithValues); + + for (AuditEntry ae : auditEntriesWithValues.getList()) + { + validateAuditEntryFields(ae, auditApp); + assertNotNull(ae.getValues()); + assertTrue("audit values not empty", ae.getValues().keySet().size() > 0); + } + + } + + private void testAuditEntriesSkipCount(AuditApps auditAppsProxy, AuditApp auditApp) throws Exception + { + int skipCount = 0; + int maxItems = 4; + Paging paging = getPaging(skipCount, maxItems); + + Map otherParams = new HashMap<>(); + ListResponse resp = auditAppsProxy.getAuditAppEntries(auditApp.getId(), + createParams(paging, otherParams), HttpServletResponse.SC_OK); + + // Paging and list groups with skip count. + skipCount = 2; + maxItems = 2; + paging = getPaging(skipCount, maxItems); + + ListResponse sublistResponse = auditAppsProxy.getAuditAppEntries(auditApp.getId(), + createParams(paging, otherParams), HttpServletResponse.SC_OK); + List expectedSublist = sublist(resp.getList(), skipCount, maxItems); + checkList(expectedSublist, sublistResponse.getPaging(), sublistResponse); + } + + private void testRetrieveAuditEntry(AuditApps auditAppsProxy, AuditApp auditApp) throws Exception + { + int skipCount = 0; + int maxItems = 4; + Paging paging = getPaging(skipCount, maxItems); + + Map otherParams = new HashMap<>(); + ListResponse resp = auditAppsProxy.getAuditAppEntries(auditApp.getId(), + createParams(paging, otherParams), HttpServletResponse.SC_OK); + String id = resp.getList().get(0).getId().toString(); + + //Positive tests + //200 - without parameters + AuditEntry entryResp = auditAppsProxy.getAuditEntry(auditApp.getId(), id, null, HttpServletResponse.SC_OK); + validateAuditEntryFields(entryResp, auditApp); + assertNull(entryResp.getValues()); + + //200 - with parameters + otherParams.put("include", "values"); + entryResp = auditAppsProxy.getAuditEntry(auditApp.getId(), id, otherParams, HttpServletResponse.SC_OK); + validateAuditEntryFields(entryResp, auditApp); + assertNotNull(entryResp.getValues()); + + // Negative tests + // 400 + auditAppsProxy.getAuditEntry(auditApp.getId(), id+"invalidIdText", null, HttpServletResponse.SC_BAD_REQUEST); + // 401 + setRequestContext(networkOne.getId(), networkAdmin, "wrongPassword"); + auditAppsProxy.getAuditEntry(auditApp.getId(), id, null, HttpServletResponse.SC_UNAUTHORIZED); + // 403 + setRequestContext(networkOne.getId(), user1, null); + auditAppsProxy.getAuditEntry(auditApp.getId(), id, null, HttpServletResponse.SC_FORBIDDEN); + // 404 + setRequestContext(networkOne.getId(), networkAdmin, DEFAULT_ADMIN_PWD); + auditAppsProxy.getAuditEntry(auditApp.getId(), "" + Math.abs(new Random().nextLong()), null, HttpServletResponse.SC_NOT_FOUND); + // 501 + setRequestContext(networkOne.getId(), networkAdmin, DEFAULT_ADMIN_PWD); + AuthenticationUtil.setFullyAuthenticatedUser(networkAdmin); + disableSystemAudit(); + auditAppsProxy.getAuditEntry(auditApp.getId(), id, null, HttpServletResponse.SC_NOT_IMPLEMENTED); + enableSystemAudit(); + } + + private void testDeleteAuditEntry(AuditApps auditAppsProxy, AuditApp auditApp) throws Exception + { + int skipCount = 0; + int maxItems = 4; + Paging paging = getPaging(skipCount, maxItems); + + Map otherParams = new HashMap<>(); + ListResponse resp = auditAppsProxy.getAuditAppEntries(auditApp.getId(), + createParams(paging, otherParams), HttpServletResponse.SC_OK); + String id = resp.getList().get(0).getId().toString(); + + // Negative tests + // 400 + auditAppsProxy.getAuditEntry(auditApp.getId(), id+"invalidIdText", null, HttpServletResponse.SC_BAD_REQUEST); + // 401 + setRequestContext(networkOne.getId(), networkAdmin, "wrongPassword"); + auditAppsProxy.deleteAuditEntry(auditApp.getId(), id, null, HttpServletResponse.SC_UNAUTHORIZED); + // 403 + setRequestContext(networkOne.getId(), user1, null); + auditAppsProxy.deleteAuditEntry(auditApp.getId(), id, null, HttpServletResponse.SC_FORBIDDEN); + // 404 + setRequestContext(networkOne.getId(), networkAdmin, DEFAULT_ADMIN_PWD); + auditAppsProxy.deleteAuditEntry(auditApp.getId(), "" + Math.abs(new Random().nextLong()), null, HttpServletResponse.SC_NOT_FOUND); + // 501 + setRequestContext(networkOne.getId(), networkAdmin, DEFAULT_ADMIN_PWD); + AuthenticationUtil.setFullyAuthenticatedUser(networkAdmin); + disableSystemAudit(); + auditAppsProxy.deleteAuditEntry(auditApp.getId(), id, null, HttpServletResponse.SC_NOT_IMPLEMENTED); + enableSystemAudit(); + + //Positive tests + //204 + auditAppsProxy.deleteAuditEntry(auditApp.getId(), id, null, HttpServletResponse.SC_NO_CONTENT); + } + + private void testDeleteAuditEntries(AuditApps auditAppsProxy, AuditApp auditApp) throws Exception + { + int skipCount = 0; + int maxItems = 4; + Paging paging = getPaging(skipCount, maxItems); + + Map otherParams = new HashMap<>(); + ListResponse resp = auditAppsProxy.getAuditAppEntries(auditApp.getId(), createParams(paging, otherParams), + HttpServletResponse.SC_OK); + String dateBefore = ISO8601DateFormat.format(resp.getList().get(0).getCreatedAt()); + String dateAfter = ISO8601DateFormat.format(resp.getList().get(2).getCreatedAt()); + Long secondDeleteEntryId = resp.getList().get(1).getId(); + Long lastDeleteEntryId = resp.getList().get(2).getId(); + + // Negative tests + // 400 - switched dates and consecutive switched IDs + otherParams.put("where", "(" + org.alfresco.rest.api.Audit.CREATED_AT + " between (" + "\'" + dateAfter + "\'" + ", " + "\'" + + dateBefore + "\'" + "))"); + auditAppsProxy.deleteAuditEntries(auditApp.getId(), otherParams, HttpServletResponse.SC_BAD_REQUEST); + + otherParams.put("where", "(" + org.alfresco.rest.api.Audit.ID + " between (" + "\'" + lastDeleteEntryId + "\'" + ", " + "\'" + + secondDeleteEntryId + "\'" + "))"); + auditAppsProxy.deleteAuditEntries(auditApp.getId(), otherParams, HttpServletResponse.SC_BAD_REQUEST); + // 401 + // put correct dates back + otherParams.put("where", "(" + org.alfresco.rest.api.Audit.CREATED_AT + " between (" + "\'" + dateBefore + "\'" + ", " + "\'" + + dateAfter + "\'" + "))"); + setRequestContext(networkOne.getId(), networkAdmin, "wrongPassword"); + auditAppsProxy.deleteAuditEntries(auditApp.getId(), otherParams, HttpServletResponse.SC_UNAUTHORIZED); + // 403 + setRequestContext(networkOne.getId(), user1, null); + auditAppsProxy.deleteAuditEntries(auditApp.getId(), otherParams, HttpServletResponse.SC_FORBIDDEN); + // 404 + setRequestContext(networkOne.getId(), networkAdmin, DEFAULT_ADMIN_PWD); + auditAppsProxy.deleteAuditEntries("invalidAppId", otherParams, HttpServletResponse.SC_NOT_FOUND); + // 501 + setRequestContext(networkOne.getId(), networkAdmin, DEFAULT_ADMIN_PWD); + AuthenticationUtil.setFullyAuthenticatedUser(networkAdmin); + disableSystemAudit(); + auditAppsProxy.deleteAuditEntries(auditApp.getId(), otherParams, HttpServletResponse.SC_NOT_IMPLEMENTED);; + enableSystemAudit(); + + // Positive tests + // 200 + auditAppsProxy.deleteAuditEntries(auditApp.getId(), otherParams, HttpServletResponse.SC_NO_CONTENT); + + // check that the entries were deleted. + // firstEntry should have id > than lastDeleteEntryId + resp = auditAppsProxy.getAuditAppEntries(auditApp.getId(), createParams(paging, new HashMap<>()), + HttpServletResponse.SC_OK); + assertTrue("Entries were not deleted", resp.getList().get(0).getId() > lastDeleteEntryId); + } + /** * Perform a login attempt (to be used to create audit entries) */ - private void login(final String username, final String password) throws Exception + private void login(final String username, final String password) throws Exception { // Force a failed login - RunAsWork failureWork = new RunAsWork() + RunAsWork failureWork = new RunAsWork() { @Override - public Void doWork() throws Exception + public Void doWork() throws Exception { - try + try { authenticationService.authenticate(username, password.toCharArray()); fail("Failed to force authentication failure"); - } - catch (AuthenticationException e) + } + catch (AuthenticationException e) { // Expected } @@ -391,4 +679,212 @@ public class AuditAppTest extends AbstractSingleNetworkSiteTest }; AuthenticationUtil.runAs(failureWork, AuthenticationUtil.getSystemUserName()); } + + protected Map createParams(Paging paging, Map otherParams) + { + Map params = new HashMap(2); + if (paging != null) + { + if (paging.getSkipCount() != null) + { + params.put("skipCount", String.valueOf(paging.getSkipCount())); + } + if (paging.getMaxItems() != null) + { + params.put("maxItems", String.valueOf(paging.getMaxItems())); + } + } + if (otherParams != null) + { + params.putAll(otherParams); + } + return params; + } + + private void addOrderBy(Map otherParams, String sortColumn, Boolean asc) + { + otherParams.put("orderBy", + sortColumn + (asc != null ? " " + (asc ? SortColumn.ASCENDING : SortColumn.DESCENDING) : "")); + } + + private NodeRef createFolderNode() + { + NodeRef nodeRef = TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public NodeRef doWork() throws Exception + { + TestSite site = networkOne.createSite(SiteVisibility.PRIVATE); + NodeRef nodeRef = repoService.createDocument(site.getContainerNodeRef("documentLibrary"), "Test Doc", "Test Content"); + return nodeRef; + } + }, user1, networkOne.getId()); + return nodeRef; + } + + @Test + public void testAuditEntriesByNodeRefId() throws Exception + { + setRequestContext(networkOne.getId(), networkAdmin, DEFAULT_ADMIN_PWD); + final AuditApps auditAppsProxy = publicApiClient.auditApps(); + NodeRef nodeRef = createFolderNode(); + + testGetAuditEntriesByNodeRefId(auditAppsProxy, nodeRef); + testAuditEntriesSortingByNodeRefId(auditAppsProxy, nodeRef); + testAuditEntriesWhereDateByNodeRefId(auditAppsProxy, nodeRef); + testAuditEntriesWithIncludeByNodeRefId(auditAppsProxy, nodeRef); + testAuditEntriesSkipCountByNodeRefId(auditAppsProxy, nodeRef); + } + + private void testAuditEntriesSkipCountByNodeRefId(AuditApps auditAppsProxy, NodeRef nodeRef) throws Exception + { + int skipCount = 0; + int maxItems = 4; + final Paging paging = getPaging(skipCount, maxItems); + Map params; + + Map otherParams = new HashMap<>(); + params = createParams(paging, otherParams); + ListResponse resp = getNodeRefAuditEntries(auditAppsProxy, user1, networkOne.getId(), nodeRef.getId(), params, HttpServletResponse.SC_OK); + + // Paging and list groups with skip count. + skipCount = 2; + maxItems = 2; + final Paging pagingSkip = getPaging(skipCount, maxItems); + params = createParams(pagingSkip, otherParams); + ListResponse sublistResponse = getNodeRefAuditEntries(auditAppsProxy, user1, networkOne.getId(), nodeRef.getId(), params, + HttpServletResponse.SC_OK); + + List expectedSublist = sublist(resp.getList(), skipCount, maxItems); + checkList(expectedSublist, sublistResponse.getPaging(), sublistResponse); + + } + + private void testAuditEntriesWithIncludeByNodeRefId(AuditApps auditAppsProxy, NodeRef nodeRef) throws Exception + { + Paging paging = getPaging(0, 10); + Map otherParams = new HashMap<>(); + Map params = createParams(paging, otherParams); + + ListResponse auditEntriesWithoutValues = getNodeRefAuditEntries(auditAppsProxy, user1, networkOne.getId(), nodeRef.getId(), params, + HttpServletResponse.SC_OK); + assertNotNull(auditEntriesWithoutValues); + + AuditApp auditApp = auditAppsProxy.getAuditApp("alfresco-access"); + for (AuditEntry ae : auditEntriesWithoutValues.getList()) + { + validateAuditEntryFields(ae, auditApp); + assertNull(ae.getValues()); + } + + otherParams.put("include", org.alfresco.rest.api.Audit.PARAM_INCLUDE_VALUES); + params = createParams(paging, otherParams); + // list auditEntries with values + ListResponse auditEntriesWithValues = getNodeRefAuditEntries(auditAppsProxy, user1, networkOne.getId(), nodeRef.getId(), params, + HttpServletResponse.SC_OK); + assertNotNull(auditEntriesWithValues); + + for (AuditEntry ae : auditEntriesWithValues.getList()) + { + validateAuditEntryFields(ae, auditApp); + assertNotNull(ae.getValues()); + assertTrue("audit values not empty", ae.getValues().keySet().size() > 0); + } + } + + private void testAuditEntriesWhereDateByNodeRefId(AuditApps auditAppsProxy, NodeRef nodeRef) throws Exception + { + // paging + Paging paging = getPaging(0, 10); + final Map otherParams = new HashMap<>(); + Map params; + + // + // note: sanity test parsing of a few ISO8601 formats (non-exhaustive) - + // eg. +01:00, +0000, Z + // + + otherParams.put("where", "(" + org.alfresco.rest.api.Audit.CREATED_AT + " between (" + "\'2016-06-02T12:13:51.593+01:00\'" + ", " + + "\'2017-06-04T10:05:16.536+01:00\'" + "))"); + params = createParams(paging, otherParams); + getNodeRefAuditEntries(auditAppsProxy, user1, networkOne.getId(), nodeRef.getId(), params, HttpServletResponse.SC_OK); + + otherParams.put("where", "(" + org.alfresco.rest.api.Audit.CREATED_AT + " between (" + "\'2016-06-02T11:13:51.593+0000\'" + ", " + + "\'2017-06-04T09:05:16.536+0000\'" + "))"); + params = createParams(paging, otherParams); + getNodeRefAuditEntries(auditAppsProxy, user1, networkOne.getId(), nodeRef.getId(), params, HttpServletResponse.SC_OK); + + otherParams.put("where", "(" + org.alfresco.rest.api.Audit.CREATED_AT + " between (" + "\'2016-06-02T11:13:51.593Z\'" + ", " + + "\'2017-06-04T09:05:16.536Z\'" + "))"); + params = createParams(paging, otherParams); + getNodeRefAuditEntries(auditAppsProxy, user1, networkOne.getId(), nodeRef.getId(), params, HttpServletResponse.SC_OK); + + otherParams.put("where", "(" + org.alfresco.rest.api.Audit.CREATED_AT + " between (" + "\'2017-06-04T10:05:16.536+01:00\'" + ", " + + "\'2016-06-02T12:13:51.593+01:00\'" + "))"); + params = createParams(paging, otherParams); + getNodeRefAuditEntries(auditAppsProxy, user1, networkOne.getId(), nodeRef.getId(), params, HttpServletResponse.SC_BAD_REQUEST); + } + + private void testGetAuditEntriesByNodeRefId(AuditApps auditAppsProxy, NodeRef nodeRef) throws Exception + { + + ListResponse auditEntries = getNodeRefAuditEntries(auditAppsProxy, user1, networkOne.getId(), nodeRef.getId(), null, + HttpServletResponse.SC_OK); + + AuditApp auditApp = auditAppsProxy.getAuditApp("alfresco-access"); + for (AuditEntry ae : auditEntries.getList()) + { + validateAuditEntryFields(ae,auditApp); + } + + // Negative tests + // 401 + setRequestContext(networkOne.getId(), networkAdmin, "wrongPassword"); + auditAppsProxy.getAuditAppEntries(nodeRef.getId(), null, HttpServletResponse.SC_UNAUTHORIZED); + // 403 + setRequestContext(networkOne.getId(), user1, null); + auditAppsProxy.getAuditAppEntries(nodeRef.getId(), null, HttpServletResponse.SC_FORBIDDEN); + // 404 + setRequestContext(networkOne.getId(), networkAdmin, DEFAULT_ADMIN_PWD); + auditAppsProxy.getAuditAppEntries("randomId", null, HttpServletResponse.SC_NOT_FOUND); + // 501 + setRequestContext(networkOne.getId(), networkAdmin, DEFAULT_ADMIN_PWD); + AuthenticationUtil.setFullyAuthenticatedUser(networkAdmin); + disableSystemAudit(); + auditAppsProxy.getAuditAppEntries("randomId", null, HttpServletResponse.SC_NOT_IMPLEMENTED); + enableSystemAudit(); + } + + private void testAuditEntriesSortingByNodeRefId(AuditApps auditAppsProxy, NodeRef nodeRef) throws Exception + { + // paging + Paging paging = getPaging(0, 10); + Map otherParams = new HashMap<>(); + // Default order. + addOrderBy(otherParams, org.alfresco.rest.api.Audit.CREATED_AT, null); + Map params = createParams(paging, otherParams); + + ListResponse auditEntries = getNodeRefAuditEntries(auditAppsProxy, user1, networkOne.getId(), nodeRef.getId(), params, + HttpServletResponse.SC_OK); + + assertNotNull(auditEntries); + assertTrue("audit entry size more that 2", auditEntries.getList().size() > 1); + assertTrue("auditEntries order not valid", auditEntries.getList().get(0).getCreatedAt().before(auditEntries.getList().get(1).getCreatedAt())); + + } + + private ListResponse getNodeRefAuditEntries(AuditApps auditAppsProxy, final String uid, final String tenantDomain, String nodeId, + Map params, int expectedStatus) + { + return TenantUtil.runAsUserTenant(new TenantRunAsWork>() + { + @Override + public ListResponse doWork() throws Exception + { + ListResponse auditEntry = auditAppsProxy.getAuditAppEntriesByNodeRefId(nodeId, params, expectedStatus); + return auditEntry; + } + }, uid, tenantDomain); + } + }