Compare commits

..

33 Commits
20.2 ... 20.9

Author SHA1 Message Date
Travis CI User
4f561166b7 [maven-release-plugin][skip ci] prepare release 20.9 2022-11-09 12:08:59 +00:00
Antonio Felix
295a8f7ba2 MNT-23276 - The null facet name should be considered (#1540) 2022-11-09 11:31:51 +00:00
Piyush Joshi
fd73ebe45a Merge pull request #1532 from Alfresco/MNT-22353_Cutoff_Handling_of_Records_in_Hold
[MNT-22353]- Removed Hold cases to be processed in DispositionLifecycleJob
2022-11-09 15:21:41 +05:30
pjoshi31
3bbaabd755 [MNT-22353]- Formatting Changes. 2022-11-09 12:48:16 +05:30
Travis CI User
ed50b9bb9b [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-08 14:23:32 +00:00
Travis CI User
361a674a19 [maven-release-plugin][skip ci] prepare release 20.8 2022-11-08 14:23:29 +00:00
Kacper Magdziarz
9f839b5372 Feature/acs-3644 Allow multiple docker-copose files (#1533)
* ACS-3644 enable usage of multiple docker-compose files in start-compose.sh
2022-11-08 12:05:15 +01:00
Piyush Joshi
c76d3b99c4 Update DispositionLifecycleJobExecuter.java 2022-11-07 21:25:03 +05:30
Piyush Joshi
4998f19da9 Update DispositionLifecycleJobExecuter.java 2022-11-07 21:24:10 +05:30
Travis CI User
b1340d12ef [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-07 15:10:48 +00:00
Travis CI User
2b79a4489d [maven-release-plugin][skip ci] prepare release 20.7 2022-11-07 15:10:46 +00:00
Maciej Pichura
e41fc6af02 ACS-3855: Add validation for rule condition comparator. (#1538) 2022-11-07 15:31:19 +01:00
pjoshi31
162264a8d7 [MNT-22353]- Added UnitTest Changes. 2022-11-07 18:32:17 +05:30
pjoshi31
a5977fedb2 [MNT-22353]- Removed length condition. 2022-11-07 12:19:27 +05:30
Travis CI User
024e4e072b [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-06 00:10:56 +00:00
Travis CI User
5c33911e5f [maven-release-plugin][skip ci] prepare release 20.6 2022-11-06 00:10:53 +00:00
Alfresco CI User
2a6eb91ebd [force] Force release for 2022-11-06. 2022-11-06 00:03:33 +00:00
Travis CI User
c588b915d5 [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-04 17:05:47 +00:00
Travis CI User
4e2384fd9a [maven-release-plugin][skip ci] prepare release 20.5 2022-11-04 17:05:44 +00:00
Antonio Felix
6071188405 MNT-23276 - Protect from null facet names (#1534) 2022-11-04 16:17:12 +00:00
pjoshi31
4c2d9ef64d [MNT-22353]- Added comment. 2022-11-03 11:45:49 +05:30
pjoshi31
f71f243b9b [MNT-22353]- Changed variable. 2022-11-03 11:21:07 +05:30
pjoshi31
3f10227c0f [MNT-22353]- Added Streams for filtering frozen nodes. 2022-11-02 18:05:11 +05:30
pjoshi31
a361596512 [MNT-22353]- Added Parallel Streams for filtering frozen nodes. 2022-11-02 16:07:59 +05:30
pjoshi31
4ad2bda8b9 [MNT-22353]- Added debug logs. 2022-11-02 15:37:08 +05:30
pjoshi31
1339dd59a9 [MNT-22353]- Removed Hold cases to be processed. 2022-11-02 14:52:35 +05:30
Travis CI User
9dad28ee4d [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-01 09:44:03 +00:00
Travis CI User
308dd9825a [maven-release-plugin][skip ci] prepare release 20.4 2022-11-01 09:44:00 +00:00
MohinishSah
609aa750d6 updated Gdrive version to verify PRODSEC issue 2022-11-01 14:28:39 +05:30
Travis CI User
def0201274 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-31 10:55:52 +00:00
Travis CI User
a7d885c630 [maven-release-plugin][skip ci] prepare release 20.3 2022-10-31 10:55:49 +00:00
kavitshah-gl
3fcbb076a2 feature/APPS-1672 (#1470)
* Adding test for the stage AGS Smoke UI Tests for actions in RM site

* pushed the createCategoriesTest in APPS-1550 brach

* pushed the createCategoriesTest in APPS-1550 branch

* pushed the CreateFoldersTests in APPS-1550 branch

* [ags]

* ~ /\[ags\]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* Revert "~ /\[ags\]"

This reverts commit ed9443e5

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* Adding FoldersDispositionScheduleTests

* Added foldersDispositionScheduleWithGhosting

* Added foldersDispositionScheduleWithoutGhosting

* Added RecordsDispositionScheduleTests and other fixes

* Added RecordsDispositionScheduleWithGhostingTests

* [ags api]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* Revert "[ags api]"

This reverts commit 2153eafc0f.

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* DispositionScheduleLinkedRecordsTest class added

* [ags]

* [ags]

* [ags]

* [ags]

* ags

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* Added Audit Holds Test

* Added NonElectronicRecordAuditLogTest file

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* Verifying the test cases execution. [ags]

* Revert "Verifying the test cases execution. [ags]"

This reverts commit 4f6b86fac6.

* Cleanup AuditHoldsTest. [ags]

* Fixed Review Comments. [ags]

* [ags]

* Revert "[ags]"

This reverts commit e2b650b82c.

Co-authored-by: sbisht <shishuraj.bisht@globallogic.com>
Co-authored-by: ashiva <aditya.shiva@globallogic.com>
Co-authored-by: omkar.yadav <omkar.yadav@globallogic.com>
2022-10-31 15:34:55 +05:30
Travis CI User
9ab4d29ff6 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-30 00:11:17 +00:00
39 changed files with 1113 additions and 48 deletions

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-amps</artifactId>
<version>20.2</version>
<version>20.9</version>
</parent>
<modules>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-parent</artifactId>
<version>20.2</version>
<version>20.9</version>
</parent>
<modules>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-automation-community-repo</artifactId>
<version>20.2</version>
<version>20.9</version>
</parent>
<build>

View File

@@ -26,6 +26,7 @@
*/
package org.alfresco.rest.v0;
import static org.apache.http.HttpStatus.SC_OK;
import static org.testng.Assert.assertTrue;
import java.io.UnsupportedEncodingException;
@@ -36,6 +37,7 @@ import java.util.List;
import org.alfresco.rest.core.v0.BaseAPI;
import org.alfresco.rest.rm.community.model.audit.AuditEntry;
import org.alfresco.rest.rm.community.util.PojoUtility;
import org.apache.http.HttpResponse;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
@@ -58,6 +60,8 @@ public class RMAuditAPI extends BaseAPI
private static final String RM_AUDIT_API = "{0}rma/admin/rmauditlog";
private static final String RM_AUDIT_LOG_API = RM_AUDIT_API + "?{1}";
private static final String RM_AUDIT_LOG_AS_RECORD = "{0}node/{1}/rmauditlog";
/**
* Returns a list of rm audit entries .
*
@@ -84,6 +88,21 @@ public class RMAuditAPI extends BaseAPI
return PojoUtility.jsonToObject(auditEntries, AuditEntry.class);
}
/**
* Returns a list of rm audit entries .
*
* @param user The username of the user to use.
* @param password The password of the user.
* @param size Maximum number of log entries to return
* @return return All return log entries
*/
public List<AuditEntry> getRMAuditLogAll(String user, String password, final int size) {
String parameters = "size=" + size;
JSONArray auditEntries = doGetRequest(user, password,
MessageFormat.format(RM_AUDIT_LOG_API,"{0}", parameters)).getJSONObject("data").getJSONArray("entries");
return PojoUtility.jsonToObject(auditEntries, AuditEntry.class);
}
/**
* Clear the list of audit entries.
*
@@ -100,5 +119,19 @@ public class RMAuditAPI extends BaseAPI
&& getRMAuditLog(username, password, 100, null).size() == 2);
}
/**
* Logs the Audit Log as Record.
*
* @param username The username of the user to use.
* @param password The password of the user.
* @param recNodeRef The Record Node reference for which Audit log should be created as record
* @param destinationNodeRef The Folder id Node reference where the html file should be placed
* @throws AssertionError If the API call didn't create the Audit Log as Record.
*/
public HttpResponse logsAuditLogAsRecord(String username, String password, String recNodeRef, String destinationNodeRef) {
JSONObject requestParams = new JSONObject();
requestParams.put("destination", destinationNodeRef);
return doPostJsonRequest(username, password, SC_OK, requestParams, RM_AUDIT_LOG_AS_RECORD,recNodeRef);
}
}

View File

@@ -97,4 +97,16 @@ public class RecordFoldersAPI extends BaseAPI
return null;
}
public HttpResponse reOpenRecordFolder(String user, String password, String recordFolder)
{
String recNodeRef = getNodeRefSpacesStore() + contentService.getNodeRef(user, password, RM_SITE_ID, recordFolder);
JSONObject requestParams = new JSONObject();
requestParams.put("name", "openRecordFolder");
requestParams.put("nodeRef", recNodeRef);
return doPostJsonRequest(user, password, SC_OK, requestParams, RM_ACTIONS_API);
}
}

View File

@@ -360,4 +360,25 @@ public class RecordsAPI extends BaseAPI
{
return getNodeRefSpacesStore() + getItemNodeRef(username, password, recordPath + "/" + recordName);
}
/**
* Reopens the record given as parameter
*
* @param user the user declaring the document as record
* @param password the user's password
* @param recordName the record name
* @return The HTTP Response.
*/
public HttpResponse reOpenRecord(String user, String password, String recordName)
{
String recNodeRef = getNodeRefSpacesStore() + contentService.getNodeRef(user, password, RM_SITE_ID, recordName);
JSONObject requestParams = new JSONObject();
requestParams.put("name", "undeclareRecord");
requestParams.put("nodeRef", recNodeRef);
return doPostJsonRequest(user, password, SC_OK, requestParams, RM_ACTIONS_API);
}
}

View File

@@ -0,0 +1,146 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.rm.community.audit;
import static java.util.Arrays.asList;
import static org.alfresco.rest.rm.community.base.TestData.*;
import static org.alfresco.rest.rm.community.model.audit.AuditEvents.ADD_TO_HOLD;
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.data.RandomData.getRandomName;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.core.IsNot.not;
import static org.springframework.http.HttpStatus.CREATED;
import static org.testng.AssertJUnit.*;
import java.util.Collections;
import java.util.List;
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.audit.AuditEvents;
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.recordfolder.RecordFolder;
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.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;
public class AuditHoldsTest extends BaseRMRestTest {
private final String PREFIX = generateTestPrefix(AuditAddToHoldTests.class);
private final String HOLD1 = PREFIX + "hold1";
private SiteModel publicSite;
private FileModel testFile;
@Autowired
private RMAuditService rmAuditService;
@Autowired
private HoldsAPI holdsAPI;
@Autowired
private RoleService roleService;
private UserModel rmAdmin;
private RecordCategory recordCategory;
private RecordCategoryChild recordFolder1,recordFolder2;
private List<AuditEntry> auditEntries;
private String hold1NodeRef;
public static final String RECORD_FOLDER_THREE = "record-folder-three";
@BeforeClass(alwaysRun = true)
public void preconditionForAuditAddToHoldTests()
{
createRMSiteIfNotExists();
rmAdmin = roleService.createUserWithRMRole(UserRoles.ROLE_RM_ADMIN.roleId);
STEP("Create a hold");
hold1NodeRef = holdsAPI.createHoldAndGetNodeRef(rmAdmin.getUsername(), rmAdmin.getPassword(), HOLD1, HOLD_REASON,
HOLD_DESCRIPTION);
STEP("Create a collaboration site with a test file.");
publicSite = dataSite.usingAdmin().createPublicRandomSite();
testFile = dataContent.usingAdmin().usingSite(publicSite).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
STEP("Create a record category with 2 folders and 1 record");
recordCategory = createRootCategory(getRandomName("recordCategory"));
recordFolder1 = createRecordFolder(recordCategory.getId(), PREFIX + "recFolder1");
recordFolder2 = createRecordFolder(recordCategory.getId(), PREFIX + "recFolder2");
Record recordToBeAdded = createElectronicRecord(recordFolder1.getId(), PREFIX + "record");
assertStatusCode(CREATED);
STEP("Add some items to the hold, then remove them from the hold");
final List<String> itemsList = asList(testFile.getNodeRefWithoutVersion(), recordToBeAdded.getId(), recordFolder2.getId());
final List<String> holdsList = Collections.singletonList(HOLD1);
holdsAPI.addItemToHold(rmAdmin.getUsername(), rmAdmin.getPassword(), recordToBeAdded.getId(), HOLD1);
holdsAPI.removeItemsFromHolds(rmAdmin.getUsername(), rmAdmin.getPassword(), itemsList, holdsList);
STEP("Delete the record folder that was held");
getRestAPIFactory().getRecordFolderAPI().deleteRecordFolder(recordFolder2.getId());
STEP("Rename the parent of the record that was held");
RecordFolder recordFolder = RecordFolder.builder().name(RECORD_FOLDER_THREE).build();
getRestAPIFactory().getRecordFolderAPI().updateRecordFolder(recordFolder, recordFolder1.getId());
}
/**
* Data provider with hold events that have links to held items
*
* @return the hold events
*/
@DataProvider (name = "holdsEvents")
public Object[][] getHoldEvents()
{
return new AuditEvents[][]
{
{ ADD_TO_HOLD },
{ REMOVE_FROM_HOLD }
};
}
@Test (dataProvider = "holdsEvents")
public void checkItemPathLink(AuditEvents event) {
auditEntries = rmAuditService.getAuditEntriesFilteredByEvent(getAdminUser(), event);
assertFalse("Audit results should not be empty",auditEntries.size()==0);
final String auditedEvent = event + " - " + testFile.getName();
assertTrue("Audit results should contain one " + auditedEvent + " event",auditEntries.stream().anyMatch(e -> e.getEvent().startsWith(event.eventDisplayName)));
STEP("Check the audit log contains only an entry for add to hold.");
assertThat(auditEntries, is(not(empty())));
}
@AfterClass(alwaysRun = true)
private void cleanup() {
dataSite.usingAdmin().deleteSite(publicSite);
deleteRecordFolder(recordFolder1.getId());
deleteRecordFolder(recordFolder2.getId());
deleteRecordCategory(recordCategory.getId());
rmAuditService.clearAuditLog();
}
}

View File

@@ -0,0 +1,244 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.rm.community.audit;
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.v0.RMAuditAPI;
import org.alfresco.rest.v0.RMRolesAndActionsAPI;
import org.alfresco.rest.v0.RecordsAPI;
import org.alfresco.test.AlfrescoTest;
import org.alfresco.utility.Utility;
import org.alfresco.utility.model.UserModel;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.AssertJUnit;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAspects.ASPECTS_COMPLETED_RECORD;
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.createRecordModel;
import static org.springframework.http.HttpStatus.OK;
import static org.springframework.test.util.AssertionErrors.assertTrue;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.fail;
public class ElectronicRecordAuditLogTest extends BaseRMRestTest {
private Optional<UserModel> rmAdmin;
@Autowired
private RMRolesAndActionsAPI rmRolesAndActionsAPI;
@Autowired
private RMAuditAPI auditLog;
@Autowired
private RecordsAPI recordApi;
/* electronic record details */
private static final String AUDIT_ELECTRONIC_RECORD = generateTestPrefix(ElectronicRecordAuditLogTest.class) + "electronic record";
private static final String AUDIT_COMPLETE_REOPEN_ELECTRONIC_RECORD = "Complete Reopen Electronic Record";
public static final String TITLE = "Title";
public static final String DESCRIPTION = "Description";
private RecordCategory category1;
private RecordCategoryChild recordFolder1;
private Record electronicRecord, electronicRecord2;
@BeforeClass(alwaysRun = true)
public void electronicRecordsAuditLogSetup()
{
createRMSiteIfNotExists();
rmAdmin = Optional.ofNullable(getDataUser().createRandomTestUser());
rmRolesAndActionsAPI.assignRoleToUser(
getDataUser().usingAdmin().getAdminUser().getUsername(),
getDataUser().usingAdmin().getAdminUser().getPassword(),
rmAdmin.get().getUsername(),
"Administrator");
auditLog.clearAuditLog(rmAdmin.get().getUsername(),rmAdmin.get().getPassword());
category1 = createRootCategory(TITLE, DESCRIPTION);
recordFolder1 = createFolder(category1.getId(),TITLE);
electronicRecord = createElectronicRecord(recordFolder1.getId(),AUDIT_ELECTRONIC_RECORD,rmAdmin.get());
}
@Test(description = "Audit log for newly filed electronic record")
@AlfrescoTest(jira="RM-4303")
public void newElectronicRecordAudit() {
List<AuditEntry> auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
// newly created record contains 2 events: "file to" and metadata update
// the order in which object creation and metadata update are listed isn't always identical due to
// both happening in the same transaction
assertTrue("File To Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("File to")));
assertTrue("Updated metadata Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Updated Metadata")));
}
@Test
(
dependsOnMethods = "newElectronicRecordAudit",
description = "Viewing electronic record audit log is itself an auditable event"
)
@AlfrescoTest(jira="RM-4303")
public void electronicRecordAuditIsEvent()
{
List<AuditEntry> auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
assertTrue("Audit View Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Audit View")));
}
@Test
(
dependsOnMethods = "electronicRecordAuditIsEvent",
description = "Rename electronic record is an edit metadata event"
)
@AlfrescoTest(jira="RM-4303")
public void renameElectronicRecord() {
auditLog.clearAuditLog(rmAdmin.get().getUsername(),rmAdmin.get().getPassword());
Record renameElectronicRecord = createRecordModel("edited " + electronicRecord.getName(), "", "");
// rename record
getRestAPIFactory().getRecordsAPI().updateRecord(renameElectronicRecord, electronicRecord.getId());
assertStatusCode(OK);
// we expect 1 new event: "metadata update"
List<AuditEntry> auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
assertTrue("Updated metadata Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Updated Metadata")));
}
@Test (
dependsOnMethods = "newElectronicRecordAudit",
description = "Complete and reopen electronic record")
@AlfrescoTest(jira="RM-4303")
public void completeAndReopenElectronicRecord() {
electronicRecord2 = createElectronicRecord(recordFolder1.getId(),AUDIT_COMPLETE_REOPEN_ELECTRONIC_RECORD);
// complete record
recordApi.completeRecord(rmAdmin.get().getUsername(),rmAdmin.get().getPassword(),
electronicRecord2.getName());
try
{
Utility.sleep(1000, 30000, () ->
{
org.alfresco.rest.rm.community.requests.gscore.api.RecordsAPI recordsAPI = getRestAPIFactory().getRecordsAPI();
List<String> aspects = recordsAPI.getRecord(electronicRecord2.getId()).getAspectNames();
// a record must be completed
assertTrue("Record is not completed.",aspects.contains(ASPECTS_COMPLETED_RECORD));
});
}
catch (InterruptedException e)
{
fail("InterruptedException received while waiting for results.");
}
List<AuditEntry> auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
assertTrue("Complete Record Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Complete Record")));
// Reopen record
recordApi.reOpenRecord(rmAdmin.get().getUsername(),rmAdmin.get().getPassword(),
electronicRecord2.getName());
try
{
Utility.sleep(1000, 30000, () ->
{
org.alfresco.rest.rm.community.requests.gscore.api.RecordsAPI recordsAPI = getRestAPIFactory().getRecordsAPI();
List<String> aspects = recordsAPI.getRecord(electronicRecord2.getId()).getAspectNames();
// a record mustn't be completed
assertFalse(aspects.contains(ASPECTS_COMPLETED_RECORD));
});
}
catch (InterruptedException e)
{
fail("InterruptedException received while waiting for results.");
}
auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
assertTrue("Reopen Record Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Reopen Record")));
}
@Test
(
dependsOnMethods = "completeAndReopenElectronicRecord",
description = "File electronic record's audit log as record"
)
@AlfrescoTest(jira="RM-4303")
public void fileElectronicRecordAuditLogAsRecord()
{
// audit log is stored in the same folder, refresh it so that it appears in the list
HttpResponse auditRecordHttpResponse = auditLog.logsAuditLogAsRecord(rmAdmin.get().getUsername(),rmAdmin.get().getPassword(),
getRecordNodeRef(electronicRecord2.getId()),getFolderNodeRef(recordFolder1.getId()));
JSONObject auditRecordProperties = getAuditPropertyValues(auditRecordHttpResponse);
Record auditRecord = getRestAPIFactory().getRecordsAPI().getRecord(auditRecordProperties.get("record").toString()
.replace("workspace://SpacesStore/",""));
// check audit log
AssertJUnit.assertTrue(auditRecordProperties.get("recordName").toString().endsWith(".html"));
AssertJUnit.assertTrue(auditRecord.getAspectNames().stream().noneMatch(x -> x.startsWith(ASPECTS_COMPLETED_RECORD)));
}
private String getFolderNodeRef(String folderId) {
return "workspace://SpacesStore/" + folderId;
}
private String getRecordNodeRef(String recordId) {
return "workspace/SpacesStore/" + recordId;
}
private JSONObject getAuditPropertyValues(HttpResponse httpResponse) {
HttpEntity entity = httpResponse.getEntity();
String responseString = null;
try {
responseString = EntityUtils.toString(entity, "UTF-8");
} catch (IOException e) {
throw new RuntimeException(e);
}
JSONObject result = new JSONObject(responseString);
return result;
}
@AfterMethod
private void closeAuditLog() {
auditLog.clearAuditLog(rmAdmin.get().getUsername(),rmAdmin.get().getPassword());
}
@AfterClass(alwaysRun = true)
private void electronicRecordAuditLogCleanup() {
deleteRecord(electronicRecord.getId());
deleteRecordFolder(recordFolder1.getId());
deleteRecordCategory(category1.getId());
dataUser.usingAdmin().deleteUser(new UserModel(rmAdmin.get().getUsername(), rmAdmin.get().getPassword()));
}
}

View File

@@ -0,0 +1,246 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.rm.community.audit;
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.v0.RMAuditAPI;
import org.alfresco.rest.v0.RMRolesAndActionsAPI;
import org.alfresco.rest.v0.RecordsAPI;
import org.alfresco.test.AlfrescoTest;
import org.alfresco.utility.Utility;
import org.alfresco.utility.model.UserModel;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.AssertJUnit;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAspects.ASPECTS_COMPLETED_RECORD;
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.createRecordModel;
import static org.springframework.http.HttpStatus.OK;
import static org.springframework.test.util.AssertionErrors.assertTrue;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.fail;
public class NonElectronicRecordAuditLogTest extends BaseRMRestTest {
private Optional<UserModel> rmAdmin;
@Autowired
private RMRolesAndActionsAPI rmRolesAndActionsAPI;
@Autowired
private RMAuditAPI auditLog;
@Autowired
private RecordsAPI recordApi;
private RecordCategory category1;
private RecordCategoryChild recordFolder1;
private Record nonElectronicRecord , nonElectronicRecord2;
private static final String AUDIT_NON_ELECTRONIC_RECORD = generateTestPrefix(NonElectronicRecordAuditLogTest.class) + "non electronic record";
private static final String AUDIT_COMPLETE_REOPEN_NON_ELECTRONIC_RECORD = "Complete Reopen Non-Electronic Record";
public static final String TITLE = "Title";
public static final String DESCRIPTION = "Description";
@BeforeClass(alwaysRun = true)
public void nonElectronicRecordAuditLogSetup()
{
createRMSiteIfNotExists();
rmAdmin = Optional.ofNullable(getDataUser().createRandomTestUser());
rmRolesAndActionsAPI.assignRoleToUser(
getDataUser().usingAdmin().getAdminUser().getUsername(),
getDataUser().usingAdmin().getAdminUser().getPassword(),
rmAdmin.get().getUsername(),
"Administrator");
auditLog.clearAuditLog(rmAdmin.get().getUsername(),rmAdmin.get().getPassword());
category1 = createRootCategory(TITLE, DESCRIPTION);
recordFolder1 = createFolder(category1.getId(),TITLE);
nonElectronicRecord = createNonElectronicRecord(recordFolder1.getId(),AUDIT_NON_ELECTRONIC_RECORD,rmAdmin.get());
}
@Test(description = "Audit log for newly filed non-electronic record")
@AlfrescoTest(jira="RM-4303")
public void newNonElectronicRecordAudit()
{
List<AuditEntry> auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
// newly created record contains 3 events: "created object", "file to" and metadata update
assertTrue("File To Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("File to")));
assertTrue("Updated metadata Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Updated Metadata")));
assertTrue("Created Object Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Created Object")));
}
@Test
(
dependsOnMethods = "newNonElectronicRecordAudit",
description = "Viewing Non electronic record audit log is itself an auditable event"
)
@AlfrescoTest(jira="RM-4303")
public void nonElectronicRecordAuditIsEvent()
{
List<AuditEntry> auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
assertTrue("Audit View Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Audit View")));
}
@Test
(
dependsOnMethods = "nonElectronicRecordAuditIsEvent",
description = "Rename electronic record is an edit metadata event"
)
@AlfrescoTest(jira="RM-4303")
public void renameNonElectronicRecord()
{
auditLog.clearAuditLog(rmAdmin.get().getUsername(),rmAdmin.get().getPassword());
Record renameNonElectronicRecord = createRecordModel("edited " + nonElectronicRecord.getName(), "", "");
// rename record
getRestAPIFactory().getRecordsAPI().updateRecord(renameNonElectronicRecord, nonElectronicRecord.getId());
assertStatusCode(OK);
// we expect 1 new event: "metadata update"
List<AuditEntry> auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
assertTrue("Updated metadata Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Updated Metadata")));
}
@Test (dependsOnMethods = "newNonElectronicRecordAudit",description = "Complete and reopen electronic record")
@AlfrescoTest(jira="RM-4303")
public void completeAndReopenNonElectronicRecord()
{
nonElectronicRecord2 = createNonElectronicRecord(recordFolder1.getId(),AUDIT_COMPLETE_REOPEN_NON_ELECTRONIC_RECORD);
// complete record
recordApi.completeRecord(rmAdmin.get().getUsername(),rmAdmin.get().getPassword(),
nonElectronicRecord2.getName());
try
{
Utility.sleep(1000, 30000, () ->
{
org.alfresco.rest.rm.community.requests.gscore.api.RecordsAPI recordsAPI = getRestAPIFactory().getRecordsAPI();
List<String> aspects = recordsAPI.getRecord(nonElectronicRecord2.getId()).getAspectNames();
// a record must be completed
assertTrue("Record is not completed.",aspects.contains(ASPECTS_COMPLETED_RECORD));
});
}
catch (InterruptedException e)
{
fail("InterruptedException received while waiting for results.");
}
List<AuditEntry> auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
assertTrue("Complete Record Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Complete Record")));
// Reopen record
recordApi.reOpenRecord(rmAdmin.get().getUsername(),rmAdmin.get().getPassword(),
nonElectronicRecord2.getName());
try
{
Utility.sleep(1000, 30000, () ->
{
org.alfresco.rest.rm.community.requests.gscore.api.RecordsAPI recordsAPI = getRestAPIFactory().getRecordsAPI();
List<String> aspects = recordsAPI.getRecord(nonElectronicRecord2.getId()).getAspectNames();
// a record mustn't be completed
assertFalse(aspects.contains(ASPECTS_COMPLETED_RECORD));
});
}
catch (InterruptedException e)
{
fail("InterruptedException received while waiting for results.");
}
auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
assertTrue("Reopen Record Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Reopen Record")));
}
@Test
(
dependsOnMethods = "completeAndReopenNonElectronicRecord",
description = "File electronic record's audit log as record"
)
@AlfrescoTest(jira="RM-4303")
public void fileNonElectronicRecordAuditLogAsRecord()
{
// audit log is stored in the same folder, refresh it so that it appears in the list
HttpResponse auditRecordHttpResponse = auditLog.logsAuditLogAsRecord(rmAdmin.get().getUsername(),rmAdmin.get().getPassword(),
getRecordNodeRef(nonElectronicRecord2.getId()),getFolderNodeRef(recordFolder1.getId()));
JSONObject auditRecordProperties = getAuditPropertyValues(auditRecordHttpResponse);
Record auditRecord = getRestAPIFactory().getRecordsAPI().getRecord(auditRecordProperties.get("record").toString()
.replace("workspace://SpacesStore/",""));
// check audit log
AssertJUnit.assertTrue(auditRecordProperties.get("recordName").toString().endsWith(".html"));
AssertJUnit.assertTrue(auditRecord.getAspectNames().stream().noneMatch(x -> x.startsWith(ASPECTS_COMPLETED_RECORD)));
}
private String getFolderNodeRef(String folderId) {
return "workspace://SpacesStore/" + folderId;
}
private String getRecordNodeRef(String recordId) {
return "workspace/SpacesStore/" + recordId;
}
private JSONObject getAuditPropertyValues(HttpResponse httpResponse) {
HttpEntity entity = httpResponse.getEntity();
String responseString = null;
try {
responseString = EntityUtils.toString(entity, "UTF-8");
} catch (IOException e) {
throw new RuntimeException(e);
}
JSONObject result = new JSONObject(responseString);
return result;
}
@AfterMethod
private void closeAuditLog() {
auditLog.clearAuditLog(rmAdmin.get().getUsername(),rmAdmin.get().getPassword());
}
@AfterClass(alwaysRun = true)
private void nonElectronicRecordAuditLogCleanup() {
deleteRecord(nonElectronicRecord.getId());
deleteRecord(nonElectronicRecord2.getId());
deleteRecordFolder(recordFolder1.getId());
deleteRecordCategory(category1.getId());
dataUser.usingAdmin().deleteUser(new UserModel(rmAdmin.get().getUsername(), rmAdmin.get().getPassword()));
}
}

View File

@@ -0,0 +1,120 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.rm.community.audit;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.audit.AuditEntry;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
import org.alfresco.rest.v0.RMAuditAPI;
import org.alfresco.rest.v0.RMRolesAndActionsAPI;
import org.alfresco.test.AlfrescoTest;
import org.alfresco.utility.model.UserModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.util.List;
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
import static org.alfresco.utility.data.RandomData.getRandomAlphanumeric;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.springframework.http.HttpStatus.OK;
import static org.springframework.test.util.AssertionErrors.assertTrue;
public class RecordCategoryAuditLogTest extends BaseRMRestTest {
@Autowired
private RMRolesAndActionsAPI rmRolesAndActionsAPI;
@Autowired
private RMAuditAPI auditLog;
private final String TEST_PREFIX = generateTestPrefix(RecordCategoryAuditLogTest.class);
private final String RM_ADMIN = TEST_PREFIX + "rm_admin";
private static final String AUDIT_CATEGORY = generateTestPrefix(RecordCategoryAuditLogTest.class) + "category";
private RecordCategory recordCategoryAudit;
@BeforeClass(alwaysRun = true)
public void recordCategoryAuditLogSetup() {
STEP("Create RM Site");
createRMSiteIfNotExists();
STEP("Create RM Admin user");
rmRolesAndActionsAPI.createUserAndAssignToRole(getAdminUser().getUsername(), getAdminUser().getPassword(), RM_ADMIN,
getAdminUser().getPassword(),
"Administrator");
}
@Test
@AlfrescoTest(jira = "RM-2768")
public void recordCategoryAudit() throws Exception {
STEP("Create root level category");
recordCategoryAudit = createRootCategory(AUDIT_CATEGORY);
List<AuditEntry> auditEntries = auditLog.getRMAuditLogAll(getAdminUser().getUsername(), getAdminUser().getPassword(), 100);
// newly created record category contains 3 events: object creation, inherited permissions set to false and metadata update
// the order in which object creation and metadata update are listed isn't always identical due to
// both happening in the same transaction
assertTrue("Created Object Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Created Object")));
assertTrue("Updated metadata Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Updated Metadata")));
}
@Test
(
dependsOnMethods = "recordCategoryAudit",
description = "Viewing audit log is itself an auditable event"
)
@AlfrescoTest(jira="RM-4303")
public void recordCategoryAuditIsEvent() {
List<AuditEntry> auditEntries = auditLog.getRMAuditLogAll(getAdminUser().getUsername(), getAdminUser().getPassword(), 100);
assertTrue("Audit View Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Audit View")));
}
@Test
(
dependsOnMethods = "recordCategoryAuditIsEvent",
description = "Record category rename is an edit metadata event"
)
@AlfrescoTest(jira="RM-4303")
public void renameRecordCategory() {
String categoryName = "Category name " + getRandomAlphanumeric();
RecordCategory rootRecordCategory = createRootCategory(categoryName);
String newCategoryName = "Rename " + categoryName;
RecordCategory recordCategoryUpdated = RecordCategory.builder().name(newCategoryName).build();
RecordCategory renamedRecordCategory = getRestAPIFactory().getRecordCategoryAPI().updateRecordCategory(recordCategoryUpdated, rootRecordCategory.getId());
assertStatusCode(OK);
// we expect 1 new event: "metadata update"
List<AuditEntry> auditEntries = auditLog.getRMAuditLogAll(getAdminUser().getUsername(), getAdminUser().getPassword(), 100);
assertTrue("Updated metadata Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Updated Metadata")));
}
@AfterClass(alwaysRun = true)
private void electronicRecordAuditLogCleanup() {
deleteRecordCategory(recordCategoryAudit.getId());
dataUser.deleteUser(new UserModel(RM_ADMIN,
getAdminUser().getPassword()));
auditLog.clearAuditLog(getAdminUser().getUsername(), getAdminUser().getPassword());
}
}

View File

@@ -0,0 +1,175 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.rm.community.audit;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.audit.AuditEntry;
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.recordfolder.RecordFolder;
import org.alfresco.rest.v0.RMAuditAPI;
import org.alfresco.rest.v0.RMRolesAndActionsAPI;
import org.alfresco.rest.v0.RecordFoldersAPI;
import org.alfresco.test.AlfrescoTest;
import org.alfresco.utility.Utility;
import org.alfresco.utility.model.UserModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.util.List;
import java.util.Optional;
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAspects.ASPECTS_COMPLETED_RECORD;
import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.createRecordFolderModel;
import static org.springframework.http.HttpStatus.OK;
import static org.springframework.test.util.AssertionErrors.assertTrue;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.fail;
public class RecordFolderAuditLogTest extends BaseRMRestTest {
private Optional<UserModel> rmAdmin;
@Autowired
private RMRolesAndActionsAPI rmRolesAndActionsAPI;
@Autowired
private RMAuditAPI auditLog;
@Autowired
private RecordFoldersAPI recordFoldersAPI;
private RecordCategory category1;
private RecordCategoryChild recordFolder1;
public static final String TITLE = "Title";
public static final String DESCRIPTION = "Description";
@BeforeClass(alwaysRun = true)
public void recordFolderAuditLogSetup() {
createRMSiteIfNotExists();
rmAdmin = Optional.ofNullable(getDataUser().createRandomTestUser());
rmRolesAndActionsAPI.assignRoleToUser(
getDataUser().usingAdmin().getAdminUser().getUsername(),
getDataUser().usingAdmin().getAdminUser().getPassword(),
rmAdmin.get().getUsername(),
"Administrator");
}
@Test(description = "Audit log for empty record folder")
@AlfrescoTest(jira = "RM-4303")
public void recordFolderAudit() {
category1 = createRootCategory(TITLE, DESCRIPTION);
recordFolder1 = createFolder(category1.getId(), TITLE);
List<AuditEntry> auditEntries = auditLog.getRMAuditLogAll(getAdminUser().getUsername(), getAdminUser().getPassword(), 100);
assertTrue("Created Object Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Created Object")));
assertTrue("Updated metadata Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Updated Metadata")));
}
@Test
(
dependsOnMethods = "recordFolderAudit",
description = "Viewing record folder audit log is itself an auditable event"
)
@AlfrescoTest(jira = "RM-4303")
public void recordFolderAuditIsEvent() {
List<AuditEntry> auditEntries = auditLog.getRMAuditLogAll(getAdminUser().getUsername(), getAdminUser().getPassword(), 100);
assertTrue("Audit View Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Audit View")));
}
@Test
(
dependsOnMethods = "recordFolderAuditIsEvent",
description = "Record folder rename is an edit metadata event"
)
@AlfrescoTest(jira = "RM-4303")
public void renameRecordFolder() {
auditLog.clearAuditLog(rmAdmin.get().getUsername(), rmAdmin.get().getPassword());
RecordFolder renameRecordFolder = createRecordFolderModel(category1.getId(), "edited");
getRestAPIFactory().getRecordFolderAPI().updateRecordFolder(renameRecordFolder, recordFolder1.getId());
assertStatusCode(OK);
// we expect 1 new event: "metadata update"
List<AuditEntry> auditEntries = auditLog.getRMAuditLogAll(getAdminUser().getUsername(), getAdminUser().getPassword(), 100);
// assertTrue("Move To Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Move to")));
assertTrue("Updated metadata Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Updated Metadata")));
}
@Test(dependsOnMethods = "recordFolderAudit",
description = "Close and reopen folder")
@AlfrescoTest(jira = "RM-4303")
public void closeReopenFolder() {
//close folder
recordFoldersAPI.closeRecordFolder(rmAdmin.get().getUsername(), rmAdmin.get().getPassword(),
recordFolder1.getName());
try
{
Utility.sleep(1000, 30000, () ->
{
List<AuditEntry> auditEntries = auditLog.getRMAuditLogAll(getAdminUser().getUsername(), getAdminUser().getPassword(), 100);
assertTrue("Folder Close Record Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Close Record Folder")));
});
}
catch (InterruptedException e)
{
fail("InterruptedException received while waiting for results.");
}
//reopen folder
recordFoldersAPI.reOpenRecordFolder(rmAdmin.get().getUsername(), rmAdmin.get().getPassword(),
recordFolder1.getName());
try
{
Utility.sleep(1000, 30000, () ->
{
List<AuditEntry> auditEntries = auditLog.getRMAuditLogAll(getAdminUser().getUsername(), getAdminUser().getPassword(), 100);
assertTrue("Reopen Record Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Open Record Folder")));
});
}
catch (InterruptedException e)
{
fail("InterruptedException received while waiting for results.");
}
}
@AfterMethod
private void closeAuditLog()
{
auditLog.clearAuditLog(rmAdmin.get().getUsername(),rmAdmin.get().getPassword());
}
@AfterClass (alwaysRun = true)
public void recordFolderAuditLogCleanup()
{
deleteRecordFolder(recordFolder1.getId());
deleteRecordCategory(category1.getId());
dataUser.usingAdmin().deleteUser(new UserModel(rmAdmin.get().getUsername(), rmAdmin.get().getPassword()));
}
}

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-parent</artifactId>
<version>20.2</version>
<version>20.9</version>
</parent>
<modules>

View File

@@ -8,7 +8,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
<version>20.2</version>
<version>20.9</version>
</parent>
<properties>

View File

@@ -30,8 +30,10 @@ package org.alfresco.module.org_alfresco_module_rm.job;
import static org.alfresco.module.org_alfresco_module_rm.action.RMDispositionActionExecuterAbstractBase.PARAM_NO_ERROR_CHECK;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.alfresco.error.AlfrescoRuntimeException;
@@ -47,7 +49,6 @@ import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.PersonService;
import org.springframework.extensions.surf.util.I18NUtil;
/**
@@ -64,7 +65,6 @@ public class DispositionLifecycleJobExecuter extends RecordsManagementJobExecute
/** batching properties */
private int batchSize;
public static final int DEFAULT_BATCH_SIZE = 500;
private static final String MSG_NODE_FROZEN = "rm.action.node.frozen.error-message";
/** list of disposition actions to automatically execute */
private List<String> dispositionActions;
@@ -194,6 +194,7 @@ public class DispositionLifecycleJobExecuter extends RecordsManagementJobExecute
boolean hasMore = true;
int skipCount = 0;
List<NodeRef> resultNodes = new ArrayList<>();
if (batchSize < 1)
{
@@ -214,7 +215,14 @@ public class DispositionLifecycleJobExecuter extends RecordsManagementJobExecute
// execute search
ResultSet results = searchService.query(params);
List<NodeRef> resultNodes = results.getNodeRefs();
if(results != null)
{
// filtering out the hold/freezed cases from the result set
resultNodes =
results.getNodeRefs().stream().filter(node -> nodeService.getPrimaryParent(node) == null ?
!freezeService.isFrozenOrHasFrozenChildren(node) :
!freezeService.isFrozenOrHasFrozenChildren(nodeService.getPrimaryParent(node).getParentRef())).collect(Collectors.toList());
}
hasMore = results.hasMore();
skipCount += resultNodes.size(); // increase by page size
results.close();
@@ -265,12 +273,6 @@ public class DispositionLifecycleJobExecuter extends RecordsManagementJobExecute
}
Map<String, Serializable> props = Map.of(PARAM_NO_ERROR_CHECK, false);
if (freezeService.isFrozenOrHasFrozenChildren(parent.getParentRef()))
{
log.debug(I18NUtil.getMessage(MSG_NODE_FROZEN, dispAction));
continue;
}
try
{
// execute disposition action

View File

@@ -170,7 +170,7 @@ public class DispositionLifecycleJobExecuterUnitTest extends BaseUnitTest
executer.executeImpl();
// then
verify(mockedNodeService, times(2)).getPrimaryParent(any(NodeRef.class));
// ensure the query is executed and closed
verifyQueryTimes(2);
@@ -206,7 +206,7 @@ public class DispositionLifecycleJobExecuterUnitTest extends BaseUnitTest
executer.executeImpl();
// then
verify(mockedNodeService, times(1)).getPrimaryParent(any(NodeRef.class));
// ensure the query is executed and closed
verifyQueryTimes(1);
@@ -262,11 +262,11 @@ public class DispositionLifecycleJobExecuterUnitTest extends BaseUnitTest
// ensure each node is process correctly
// node1
verify(mockedNodeService, times(1)).getProperty(node1, RecordsManagementModel.PROP_DISPOSITION_ACTION);
verify(mockedNodeService, times(1)).getPrimaryParent(node1);
verify(mockedNodeService, times(3)).getPrimaryParent(node1);
verify(mockedRecordsManagementActionService, times(1)).executeRecordsManagementAction(eq(parent), eq(CUTOFF), anyMap());
// node2
verify(mockedNodeService, times(1)).getProperty(node2, RecordsManagementModel.PROP_DISPOSITION_ACTION);
verify(mockedNodeService, times(1)).getPrimaryParent(node2);
verify(mockedNodeService, times(3)).getPrimaryParent(node2);
verify(mockedRecordsManagementActionService, times(1)).executeRecordsManagementAction(eq(parent), eq(RETAIN), anyMap());
// ensure no more interactions
@@ -329,7 +329,7 @@ public class DispositionLifecycleJobExecuterUnitTest extends BaseUnitTest
// call the service
executer.executeImpl();
// check the loop iterated trough all the elements
// check the loop iterated through all the elements
verify(mockedNodeService).exists(node1);
verify(mockedNodeService).exists(node2);
verify(mockedNodeService).exists(node3);

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
<version>20.2</version>
<version>20.9</version>
</parent>
<build>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>20.2</version>
<version>20.9</version>
</parent>
<modules>

View File

@@ -8,7 +8,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-amps</artifactId>
<version>20.2</version>
<version>20.9</version>
</parent>
<properties>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>20.2</version>
<version>20.9</version>
</parent>
<dependencies>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>20.2</version>
<version>20.9</version>
</parent>
<properties>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>20.2</version>
<version>20.9</version>
</parent>
<dependencies>

View File

@@ -9,6 +9,6 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId>
<version>20.2</version>
<version>20.9</version>
</parent>
</project>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId>
<version>20.2</version>
<version>20.9</version>
</parent>
<properties>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>20.2</version>
<version>20.9</version>
</parent>
<modules>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId>
<version>20.2</version>
<version>20.9</version>
</parent>
<modules>

View File

@@ -1,9 +1,21 @@
#!/usr/bin/env bash
set -x
export DOCKER_COMPOSE_PATH=$1
export CLEAN_UP="$2"
export DOCKER_COMPOSES=""
export CLEAN_UP=""
if [ -z "$DOCKER_COMPOSE_PATH" ]
for var in "$@"
do
if [ "$var" == "no-clean-up" ]
then
export CLEAN_UP="$var"
else
export DOCKER_COMPOSES+="--file $var "
fi
done
if [ -z "$DOCKER_COMPOSES" ]
then
echo "Please provide path to docker-compose.yml: \"${0##*/} /path/to/docker-compose.yml\""
exit 1
@@ -15,8 +27,8 @@ fi
# The second parameter can be used to avoid doing a clean up if we are doing a restart test.
if [ "$CLEAN_UP" != "no-clean-up" ]
then
docker-compose --file "${DOCKER_COMPOSE_PATH}" kill
docker-compose --file "${DOCKER_COMPOSE_PATH}" rm -f
docker-compose ${DOCKER_COMPOSES} --project-directory $(dirname "${DOCKER_COMPOSE_PATH}") kill
docker-compose ${DOCKER_COMPOSES} --project-directory $(dirname "${DOCKER_COMPOSE_PATH}") rm -f
export GENERATED_IMAGES=$(docker images | grep '^environment_' | awk '{ print $3 }')
if [ -n "$GENERATED_IMAGES" ]
@@ -31,7 +43,7 @@ export TRANSFORMERS_TAG=$(mvn help:evaluate -Dexpression=dependency.alfresco-tra
export TRANSFORM_ROUTER_TAG=$(mvn help:evaluate -Dexpression=dependency.alfresco-transform-service.version -q -DforceStdout)
# .env files are picked up from project directory correctly on docker-compose 1.23.0+
docker-compose --file "${DOCKER_COMPOSE_PATH}" --project-directory $(dirname "${DOCKER_COMPOSE_PATH}") up -d
docker-compose ${DOCKER_COMPOSES} --project-directory $(dirname "${DOCKER_COMPOSE_PATH}") up -d
if [ $? -eq 0 ]
then

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>20.2</version>
<version>20.9</version>
</parent>
<organization>

View File

@@ -9,7 +9,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>20.2</version>
<version>20.9</version>
</parent>
<developers>

View File

@@ -9,7 +9,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>20.2</version>
<version>20.9</version>
</parent>
<developers>

View File

@@ -9,7 +9,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>20.2</version>
<version>20.9</version>
</parent>
<developers>

View File

@@ -951,6 +951,28 @@ public class CreateRulesTests extends RestTest
restClient.assertLastError().containsSummary("Category in condition is invalid");
}
/**
* Check we get 400 error when condition comparator is invalid
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void createRuleWithConditions_invalidComparator()
{
STEP("Try to create a rule with invalid comparator in conditions.");
final String comparator = "greaterthan";
RestCompositeConditionDefinitionModel conditions = rulesUtils.createCompositeCondition(List.of(
rulesUtils.createCompositeCondition(!INVERTED, List.of(
rulesUtils.createSimpleCondition("size", comparator, "500")
))
));
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
ruleModel.setConditions(conditions);
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
restClient.assertStatusCodeIs(BAD_REQUEST);
restClient.assertLastError().containsSummary("Comparator value for condition is invalid: " + comparator);
}
private String getAddPermissionsBody(String username, String role)
{
JsonObject userPermission = Json.createObjectBuilder().add("permissions",

View File

@@ -9,7 +9,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>20.2</version>
<version>20.9</version>
</parent>
<developers>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId>
<version>20.2</version>
<version>20.9</version>
</parent>
<properties>

View File

@@ -2,7 +2,7 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>alfresco-community-repo</artifactId>
<version>20.2</version>
<version>20.9</version>
<packaging>pom</packaging>
<name>Alfresco Community Repo Parent</name>
@@ -109,7 +109,7 @@
<dependency.jakarta-json-path.version>2.7.0</dependency.jakarta-json-path.version>
<dependency.jakarta-rpc-api.version>1.1.4</dependency.jakarta-rpc-api.version>
<alfresco.googledrive.version>3.3.0</alfresco.googledrive.version>
<alfresco.googledrive.version>3.3.1-A1</alfresco.googledrive.version>
<alfresco.aos-module.version>1.5.0</alfresco.aos-module.version>
<alfresco.api-explorer.version>7.3.0</alfresco.api-explorer.version> <!-- Also in alfresco-enterprise-share -->
@@ -149,7 +149,7 @@
<connection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</connection>
<developerConnection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</developerConnection>
<url>https://github.com/Alfresco/alfresco-community-repo</url>
<tag>20.2</tag>
<tag>20.9</tag>
</scm>
<distributionManagement>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>20.2</version>
<version>20.9</version>
</parent>
<dependencies>

View File

@@ -64,6 +64,7 @@ public class RestRuleSimpleConditionModelMapper implements RestModelMapper<Simpl
static final String FIELD_NOT_NULL = "Field in condition must not be blank";
static final String PARAMETER_NOT_NULL = "Parameter in condition must not be blank";
static final String COMPARATOR_NOT_NULL = "Comparator in condition must not be blank";
static final String INVALID_COMPARATOR_VALUE = "Comparator value for condition is invalid: %s";
private final NamespaceService namespaceService;
private final Nodes nodes;
@@ -157,13 +158,23 @@ public class RestRuleSimpleConditionModelMapper implements RestModelMapper<Simpl
parameterValues.put(ComparePropertyValueEvaluator.PARAM_PROPERTY, QName.createQName(field, namespaceService));
}
checkStringNotBlank(restModel.getComparator(), COMPARATOR_NOT_NULL);
parameterValues.put(ComparePropertyValueEvaluator.PARAM_OPERATION, restModel.getComparator().toUpperCase());
parameterValues.put(ComparePropertyValueEvaluator.PARAM_OPERATION, getComparatorValue(restModel.getComparator()));
parameterValues.put(ComparePropertyValueEvaluator.PARAM_VALUE, parameter);
break;
}
return new ActionConditionImpl(UUID.randomUUID().toString(), conditionDefinitionId, parameterValues);
}
private String getComparatorValue(String comparator)
{
try
{
return ComparePropertyValueOperation.valueOf(comparator.toUpperCase()).toString();
} catch (IllegalArgumentException e) {
throw new InvalidArgumentException(String.format(INVALID_COMPARATOR_VALUE, comparator));
}
}
private void checkStringNotBlank(final String string, final String message) {
if (Strings.isBlank(string))
{

View File

@@ -28,6 +28,7 @@ package org.alfresco.rest.api.impl.mapper.rules;
import static org.alfresco.rest.api.impl.mapper.rules.RestRuleSimpleConditionModelMapper.COMPARATOR_NOT_NULL;
import static org.alfresco.rest.api.impl.mapper.rules.RestRuleSimpleConditionModelMapper.FIELD_NOT_NULL;
import static org.alfresco.rest.api.impl.mapper.rules.RestRuleSimpleConditionModelMapper.INVALID_COMPARATOR_VALUE;
import static org.alfresco.rest.api.impl.mapper.rules.RestRuleSimpleConditionModelMapper.PARAMETER_NOT_NULL;
import static org.alfresco.rest.api.impl.mapper.rules.RestRuleSimpleConditionModelMapper.PARAM_CATEGORY;
import static org.alfresco.rest.api.impl.mapper.rules.RestRuleSimpleConditionModelMapper.PARAM_MIMETYPE;
@@ -366,6 +367,22 @@ public class RestRuleSimpleConditionModelMapperTest
.hasMessageContaining(COMPARATOR_NOT_NULL);
}
@Test
public void testToServiceModel_invalidComparator()
{
final String comparator = "greaterthan";
final SimpleCondition simpleConditionNullComparator = SimpleCondition.builder()
.field("size")
.comparator(comparator)
.parameter("65000")
.create();
// when
assertThatThrownBy(() -> objectUnderTest.toServiceModel(simpleConditionNullComparator))
.isInstanceOf(InvalidArgumentException.class)
.hasMessageContaining(String.format(INVALID_COMPARATOR_VALUE, comparator));
}
private static ActionCondition createActionCondition(final String actionDefinitionName)
{
return new ActionConditionImpl("fake-id", actionDefinitionName, createParameterValues());

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>20.2</version>
<version>20.9</version>
</parent>
<dependencies>

View File

@@ -267,8 +267,12 @@ public class SolrJSONResultSet implements SearchEngineResultSet {
ArrayList<Pair<String, Integer>> facetValues = new ArrayList<Pair<String, Integer>>(facetArraySize/2);
for(int i = 0; i < facetArraySize; i+=2)
{
String facetEntryName = facets.getString(i);
Integer facetEntryCount = Integer.valueOf(facets.getInt(i+1));
String facetEntryName = "Null";
if(!facets.isNull(i))
{
facetEntryName = facets.getString(i);
}
Integer facetEntryCount = Integer.valueOf(facets.getInt(i + 1));
Pair<String, Integer> pair = new Pair<String, Integer>(facetEntryName, facetEntryCount);
facetValues.add(pair);
}