mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-09-10 14:11:58 +00:00
Compare commits
58 Commits
hack/hacka
...
17.118
Author | SHA1 | Date | |
---|---|---|---|
|
3fde3cbadb | ||
|
ac1a77156e | ||
|
e66263a5a8 | ||
|
a410dbe538 | ||
|
48f53d204d | ||
|
b589d574ea | ||
|
a04f743318 | ||
|
d4aa429643 | ||
|
ebdc01300d | ||
|
977681ba9b | ||
|
e457a8b7c7 | ||
|
772109d629 | ||
|
ee8adb45fb | ||
|
7daf864168 | ||
|
9744b1da4d | ||
|
033a00075f | ||
|
2a48160442 | ||
|
64955658fc | ||
|
bec0ac0236 | ||
|
b22595058e | ||
|
742a4c89dd | ||
|
09db0fcad3 | ||
|
313823eb8c | ||
|
b7d2d3bae9 | ||
|
e265bb0a5d | ||
|
6da0d7cc7b | ||
|
430d15f32d | ||
|
3fc0100bb5 | ||
|
7ccd9640ee | ||
|
bea34483b5 | ||
|
e0867a099f | ||
|
172d6c2185 | ||
|
4692d471a3 | ||
|
3c55c1a9a0 | ||
|
400b33c7eb | ||
|
bc9c23503b | ||
|
7ed021fb77 | ||
|
0e73bc1572 | ||
|
7eb063e923 | ||
|
a5a34c05c1 | ||
|
9f4371eb9c | ||
|
5846a1fd11 | ||
|
ffef5f875a | ||
|
fa04a7264f | ||
|
6e5d37067d | ||
|
0bbc63fb20 | ||
|
2819e0590b | ||
|
2a84afe2f0 | ||
|
80ccf64df8 | ||
|
5cf7c1934a | ||
|
25d6b428aa | ||
|
829393b602 | ||
|
18d2dfc84d | ||
|
8cdff26342 | ||
|
8bc3b357cf | ||
|
d2a71d0c9f | ||
|
0eb5a4b806 | ||
|
b8ac41ac0d |
11
.github/workflows/hackathon.yml
vendored
11
.github/workflows/hackathon.yml
vendored
@@ -1,11 +0,0 @@
|
||||
name: Hackathon
|
||||
|
||||
on:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
sleep:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: sleep 240
|
11
.travis.yml
11
.travis.yml
@@ -53,7 +53,7 @@ jobs:
|
||||
|
||||
- name: "Source Clear Scan (SCA)"
|
||||
stage: test
|
||||
if: branch = master OR branch =~ /release\/.*/
|
||||
if: (branch = master OR branch =~ /release\/.*/) AND type != pull_request
|
||||
# Run Veracode
|
||||
install: skip
|
||||
script: travis_wait 30 bash scripts/travis/source_clear.sh
|
||||
@@ -264,6 +264,7 @@ jobs:
|
||||
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal+transforms.yml
|
||||
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
|
||||
script: travis_wait 60 mvn -B verify -f packaging/tests/tas-restapi/pom.xml -Pall-tas-tests,run-restapi-part1 -Denvironment=default -DrunBugs=false
|
||||
after_failure: ${TAS_SCRIPTS}/output_logs_for_failures.sh "packaging/tests/tas-restapi"
|
||||
|
||||
- name: "REST API TAS tests part2"
|
||||
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
|
||||
@@ -272,6 +273,7 @@ jobs:
|
||||
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal+transforms.yml
|
||||
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
|
||||
script: travis_wait 60 mvn -B verify -f packaging/tests/tas-restapi/pom.xml -Pall-tas-tests,run-restapi-part2 -Denvironment=default -DrunBugs=false
|
||||
after_failure: ${TAS_SCRIPTS}/output_logs_for_failures.sh "packaging/tests/tas-restapi"
|
||||
|
||||
- name: "REST API TAS tests part3"
|
||||
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
|
||||
@@ -280,6 +282,7 @@ jobs:
|
||||
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal+transforms.yml
|
||||
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
|
||||
script: travis_wait 60 mvn -B verify -f packaging/tests/tas-restapi/pom.xml -Pall-tas-tests,run-restapi-part3 -Denvironment=default -DrunBugs=false
|
||||
after_failure: ${TAS_SCRIPTS}/output_logs_for_failures.sh "packaging/tests/tas-restapi"
|
||||
|
||||
- name: "CMIS TAS tests - BROWSER binding"
|
||||
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
|
||||
@@ -288,6 +291,7 @@ jobs:
|
||||
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal+transforms.yml
|
||||
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
|
||||
script: travis_wait 40 mvn -B verify -f packaging/tests/tas-cmis/pom.xml -Pall-tas-tests,run-cmis-browser -Denvironment=default -DrunBugs=false
|
||||
after_failure: ${TAS_SCRIPTS}/output_logs_for_failures.sh "packaging/tests/tas-cmis"
|
||||
|
||||
- name: "CMIS TAS tests - ATOM binding"
|
||||
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
|
||||
@@ -296,6 +300,7 @@ jobs:
|
||||
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal+transforms.yml
|
||||
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
|
||||
script: travis_wait 40 mvn -B verify -f packaging/tests/tas-cmis/pom.xml -Pall-tas-tests,run-cmis-atom -Denvironment=default -DrunBugs=false
|
||||
after_failure: ${TAS_SCRIPTS}/output_logs_for_failures.sh "packaging/tests/tas-cmis"
|
||||
|
||||
- name: "CMIS TAS tests - WEBSERVICES binding"
|
||||
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
|
||||
@@ -304,6 +309,7 @@ jobs:
|
||||
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal+transforms.yml
|
||||
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
|
||||
script: travis_wait 40 mvn -B verify -f packaging/tests/tas-cmis/pom.xml -Pall-tas-tests,run-cmis-webservices -Denvironment=default -DrunBugs=false
|
||||
after_failure: ${TAS_SCRIPTS}/output_logs_for_failures.sh "packaging/tests/tas-cmis"
|
||||
|
||||
- name: "Email TAS tests"
|
||||
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
|
||||
@@ -312,6 +318,7 @@ jobs:
|
||||
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal.yml
|
||||
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
|
||||
script: travis_wait 30 mvn -B verify -f packaging/tests/tas-email/pom.xml -Pall-tas-tests -Denvironment=default -DrunBugs=false
|
||||
after_failure: ${TAS_SCRIPTS}/output_logs_for_failures.sh "packaging/tests/tas-email"
|
||||
|
||||
- name: "WebDAV TAS tests"
|
||||
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
|
||||
@@ -320,6 +327,7 @@ jobs:
|
||||
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal.yml
|
||||
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
|
||||
script: travis_wait 30 mvn -B verify -f packaging/tests/tas-webdav/pom.xml -Pall-tas-tests -Denvironment=default -DrunBugs=false
|
||||
after_failure: ${TAS_SCRIPTS}/output_logs_for_failures.sh "packaging/tests/tas-webdav"
|
||||
|
||||
- name: "Integration TAS tests"
|
||||
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
|
||||
@@ -328,6 +336,7 @@ jobs:
|
||||
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal.yml
|
||||
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
|
||||
script: travis_wait 30 mvn -B verify -f packaging/tests/tas-integration/pom.xml -Pall-tas-tests -Denvironment=default -DrunBugs=false
|
||||
after_failure: ${TAS_SCRIPTS}/output_logs_for_failures.sh "packaging/tests/tas-integration"
|
||||
|
||||
- name: "Share Services - ShareServicesTestSuite"
|
||||
if: commit_message !~ /\[skip repo\]/
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||
<version>17.102-SNAPSHOT</version>
|
||||
<version>17.118</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||
<version>17.102-SNAPSHOT</version>
|
||||
<version>17.118</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-automation-community-repo</artifactId>
|
||||
<version>17.102-SNAPSHOT</version>
|
||||
<version>17.118</version>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
|
@@ -0,0 +1,73 @@
|
||||
/*-
|
||||
* #%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.v0;
|
||||
|
||||
import org.alfresco.rest.core.v0.BaseAPI;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Methods to make API requests using v0 API for Linking Records
|
||||
*
|
||||
* @author Kavit Shah
|
||||
* @since 3.2
|
||||
*/
|
||||
@Component
|
||||
public class LinksAPI extends BaseAPI {
|
||||
|
||||
private static final String LINK_API = "{0}doclib/action/rm-link/site/rm/documentLibrary/{1}";
|
||||
|
||||
/**
|
||||
* Creates the Link
|
||||
*
|
||||
* @param user The username of the user to use.
|
||||
* @param password The password of the user.
|
||||
* @param expectedStatusCode The expected return status code.
|
||||
* @param sourcePath The Source of link the record. This should be in the format
|
||||
* "{site}/{container}/{path}", "{site}/{container}", "{store_type}/{store_id}/{id}/{path}",
|
||||
* "{store_type}/{store_id}/{id}" or "{store_type}/{store_id}".
|
||||
* @param nodeRefs The Node that needs to be linked.
|
||||
* @return The HTTP Response.
|
||||
* @throws AssertionError If the API didn't return the expected status code.
|
||||
*/
|
||||
public HttpResponse linkRecord(String user, String password, int expectedStatusCode, String sourcePath, List<String> nodeRefs) throws UnsupportedEncodingException {
|
||||
JSONObject requestParams = new JSONObject();
|
||||
requestParams.put("nodeRefs", new JSONArray(nodeRefs));
|
||||
|
||||
return doSlingshotPostJsonRequest(user, password, expectedStatusCode, requestParams,
|
||||
MessageFormat.format(LINK_API, "{0}", sourcePath));
|
||||
}
|
||||
|
||||
}
|
@@ -52,7 +52,7 @@ public class RecordCategoriesAPI extends BaseAPI
|
||||
private static final String RM_ACTIONS_API = "{0}rma/actions/ExecutionQueue";
|
||||
private static final String DISPOSITION_ACTIONS_API = "{0}node/{1}/dispositionschedule/dispositionactiondefinitions";
|
||||
private static final String DISPOSITION_SCHEDULE_API = "{0}node/{1}/dispositionschedule";
|
||||
|
||||
private static final String NEXT_DISPOSITION_ACTIONS_API = "{0}node/{1}/nextdispositionaction";
|
||||
|
||||
/**
|
||||
* Creates a retention schedule for the category given as parameter
|
||||
@@ -191,4 +191,19 @@ public class RecordCategoriesAPI extends BaseAPI
|
||||
retentionProperties.put(RETENTION_SCHEDULE.RETENTION_INSTRUCTIONS, instructions);
|
||||
return retentionProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Next Disposition Action
|
||||
*
|
||||
* @param user
|
||||
* @param password
|
||||
* @param recordId
|
||||
* @return the next disposition schedule action
|
||||
*/
|
||||
public JSONObject getNextDispositionAction(String user, String password, String recordId)
|
||||
{
|
||||
String nodeRef = NODE_PREFIX + recordId;
|
||||
JSONObject nextDispositionAction = doGetRequest(user, password, MessageFormat.format(NEXT_DISPOSITION_ACTIONS_API, "{0}", nodeRef));
|
||||
return nextDispositionAction;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
* #%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.records;
|
||||
|
||||
import org.alfresco.dataprep.CMISUtil;
|
||||
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
|
||||
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.rules.ActionsOnRule;
|
||||
import org.alfresco.rest.rm.community.model.rules.RuleDefinition;
|
||||
import org.alfresco.rest.rm.community.model.unfiledcontainer.UnfiledContainer;
|
||||
import org.alfresco.rest.rm.community.model.unfiledcontainer.UnfiledContainerChildCollection;
|
||||
import org.alfresco.rest.v0.RMRolesAndActionsAPI;
|
||||
import org.alfresco.rest.v0.RecordsAPI;
|
||||
import org.alfresco.rest.v0.RulesAPI;
|
||||
import org.alfresco.rest.v0.service.DispositionScheduleService;
|
||||
import org.alfresco.test.AlfrescoTest;
|
||||
import org.alfresco.utility.constants.UserRole;
|
||||
import org.alfresco.utility.model.FileModel;
|
||||
import org.alfresco.utility.model.FolderModel;
|
||||
import org.alfresco.utility.model.SiteModel;
|
||||
import org.alfresco.utility.model.UserModel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.alfresco.rest.core.v0.BaseAPI.NODE_PREFIX;
|
||||
import static org.alfresco.rest.core.v0.BaseAPI.RM_SITE_ID;
|
||||
import static org.alfresco.rest.rm.community.base.TestData.DEFAULT_PASSWORD;
|
||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.UNFILED_RECORDS_CONTAINER_ALIAS;
|
||||
import static org.alfresco.rest.rm.community.model.recordcategory.RetentionPeriodProperty.CREATED_DATE;
|
||||
import static org.alfresco.rest.rm.community.model.user.UserPermissions.PERMISSION_READ_RECORDS;
|
||||
import static org.alfresco.rest.rm.community.requests.gscore.api.FilesAPI.PARENT_ID_PARAM;
|
||||
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.http.HttpStatus.CREATED;
|
||||
|
||||
public class DeclareInPlaceRecordsTestLevel2 extends BaseRMRestTest {
|
||||
private final String TEST_PREFIX = generateTestPrefix(DeclareInPlaceRecordsTestLevel2.class);
|
||||
private final String RM_ADMIN = TEST_PREFIX + "rm_admin";
|
||||
private final String RECORDS_CATEGORY_ONE = TEST_PREFIX + "category";
|
||||
public static final String RECORD_FOLDER_ONE = "record-folder-one";
|
||||
public static final String RECORD_CATEGORY_TWO = "record-category-two" + System.currentTimeMillis();
|
||||
public static final String RECORD_FOLDER_TWO = "record-folder-two";
|
||||
private final String RULE_NAME = TEST_PREFIX + "rule unfiled";
|
||||
private String unfiledRecordsNodeRef;
|
||||
private RecordCategory RecordCategoryOne, RecordCategoryTwo;
|
||||
private RecordCategoryChild recordFolder;
|
||||
private UnfiledContainer unfiledContainer;
|
||||
private FolderModel testFolder;
|
||||
private SiteModel testSite;
|
||||
private SiteModel privateSite;
|
||||
private UserModel testUser;
|
||||
@Autowired
|
||||
private DispositionScheduleService dispositionScheduleService;
|
||||
@Autowired
|
||||
private RulesAPI rulesAPI;
|
||||
/**
|
||||
* data prep services
|
||||
*/
|
||||
@Autowired
|
||||
private RMRolesAndActionsAPI rmRolesAndActionsAPI;
|
||||
@Autowired
|
||||
private RecordsAPI recordsAPI;
|
||||
|
||||
@BeforeClass(alwaysRun = true)
|
||||
public void preConditions() {
|
||||
STEP("Create RM Site");
|
||||
createRMSiteIfNotExists();
|
||||
privateSite = dataSite.usingAdmin().createPrivateRandomSite();
|
||||
}
|
||||
|
||||
/**
|
||||
* Given that a user is the owner of a document
|
||||
* And that user has been deleted
|
||||
* When admin tries to declare the document as a record
|
||||
* Then the document becomes an inplace record
|
||||
*/
|
||||
@Test
|
||||
@AlfrescoTest(jira="RM-2584")
|
||||
public void DeclareRecordOwnerDeleted() throws Exception {
|
||||
|
||||
createTestPrecondition();
|
||||
|
||||
// Upload document in a folder in a collaboration site
|
||||
FileModel uploadedDoc = dataContent.usingSite(testSite)
|
||||
.usingUser(testUser)
|
||||
.usingResource(testFolder)
|
||||
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
|
||||
// delete the test user
|
||||
dataUser.deleteUser(testUser);
|
||||
|
||||
// declare uploadedDocument as record
|
||||
getRestAPIFactory().getFilesAPI(getDataUser().getAdminUser()).declareAsRecord(uploadedDoc.getNodeRefWithoutVersion());
|
||||
assertStatusCode(CREATED);
|
||||
|
||||
// assert that the document is now a record
|
||||
assertTrue(hasRecordAspect(uploadedDoc));
|
||||
}
|
||||
/**
|
||||
* Given that a user is the owner of a document
|
||||
* And that user declare the document as a record
|
||||
* When admin files the record to a category that has a disposition schedule applied on records and a cut off step
|
||||
* And admin completes the record so the pending record action is now Cut off
|
||||
* Then user is still able to see the in place record in original share site location
|
||||
*/
|
||||
@Test
|
||||
@AlfrescoTest(jira="MNT-18558")
|
||||
public void inPlaceRecordVisibilityAfterFilingToCategoryWithCutOffStep() throws Exception {
|
||||
|
||||
// create test precondition
|
||||
createTestPrecondition(RECORDS_CATEGORY_ONE);
|
||||
|
||||
//create a disposition schedule on Records level with a cut off step
|
||||
dispositionScheduleService.createCategoryRetentionSchedule(RECORDS_CATEGORY_ONE, true);
|
||||
dispositionScheduleService.addCutOffAfterPeriodStep(RECORDS_CATEGORY_ONE, "day|2", CREATED_DATE);
|
||||
|
||||
//create a folder in category
|
||||
recordFolder = createFolder(getAdminUser(),RecordCategoryOne.getId(),RECORD_FOLDER_ONE);
|
||||
|
||||
// create a File to record folder rule applied on Unfiled Records container
|
||||
fileToRuleAppliedOnUnfiledRecords();
|
||||
|
||||
//create a new test user
|
||||
UserModel testUser = createSiteManager();
|
||||
|
||||
// upload a new document as the user and declare the document as record
|
||||
FileModel uploadedDoc = dataContent.usingSite(privateSite)
|
||||
.usingUser(testUser)
|
||||
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
|
||||
Record uploadedRecord = getRestAPIFactory().getFilesAPI(getDataUser().getAdminUser()).declareAsRecord(uploadedDoc.getNodeRefWithoutVersion());
|
||||
assertStatusCode(CREATED);
|
||||
|
||||
//Complete the record as admin to be sure that pending action is now Cut off
|
||||
recordsAPI.completeRecord(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), uploadedRecord.getName());
|
||||
|
||||
// As test user navigate to collaboration site documents library and check that the record is still visible
|
||||
dataContent.usingAdmin().usingSite(privateSite).assertContentExist();
|
||||
}
|
||||
/**
|
||||
* Create a user called test
|
||||
* Create a collaboration site
|
||||
* Add the user to the collaboration site as consumer
|
||||
* Create an RM site
|
||||
* In RM, create a new categories under file plan with a cut off step set after an event happens
|
||||
* Under the previously created category create a folder
|
||||
* Set READ-ONLY permission for test user for the folder previously created (the user does not have Read
|
||||
* permissions to the category containing the folder)
|
||||
* In the collaboration site create two files
|
||||
* File as record the first file
|
||||
* Log in with test user and check if he can still see the two files in the collaboration site
|
||||
*/
|
||||
@Test
|
||||
@AlfrescoTest (jira = "MNT-22138")
|
||||
public void filesVisibilityAfterFilingToCategoryWithCutOffAfterEventStep() throws Exception {
|
||||
|
||||
//create a category
|
||||
RecordCategoryTwo = createRootCategory(RECORD_CATEGORY_TWO);
|
||||
|
||||
//create a disposition schedule on Records level with a cut off step
|
||||
dispositionScheduleService.createCategoryRetentionSchedule(RECORD_CATEGORY_TWO, true);
|
||||
dispositionScheduleService.addCutOffAfterPeriodStep(RECORD_CATEGORY_TWO, "day|2", CREATED_DATE);
|
||||
|
||||
//create a folder in category
|
||||
recordFolder = createFolder(getAdminUser(),RecordCategoryTwo.getId(),RECORD_FOLDER_TWO);
|
||||
|
||||
//create a new test user
|
||||
UserModel siteConsumer = getDataUser().createRandomTestUser();
|
||||
getDataUser().addUserToSite(siteConsumer,privateSite,UserRole.SiteConsumer);
|
||||
|
||||
// give read permissions to test user
|
||||
getRestAPIFactory().getRMUserAPI().addUserPermission(recordFolder.getId(), siteConsumer, PERMISSION_READ_RECORDS);
|
||||
|
||||
// create two documents
|
||||
FileModel testFile = dataContent.usingSite(new SiteModel(privateSite.getTitle()))
|
||||
.usingAdmin()
|
||||
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
|
||||
FileModel testFileNotFiled = dataContent.usingSite(new SiteModel(privateSite.getTitle()))
|
||||
.usingAdmin()
|
||||
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
|
||||
// file one of the documents as record
|
||||
getRestAPIFactory().getFilesAPI()
|
||||
.usingParams(String.format("%s=%s", PARENT_ID_PARAM, recordFolder.getId()))
|
||||
.declareAsRecord(testFile.getNodeRefWithoutVersion());
|
||||
getRestAPIFactory().getRmRestWrapper().assertStatusCodeIs(CREATED);
|
||||
|
||||
// As test user navigate to collaboration site documents library and check that both of the documents are
|
||||
// visible
|
||||
STEP("Verify the document in collaboration site is now a record");
|
||||
Assert.assertTrue(hasRecordAspect(testFile), "File should have record aspect");
|
||||
Assert.assertFalse(hasRecordAspect(testFileNotFiled), "File should not have record aspect");
|
||||
}
|
||||
|
||||
private void createTestPrecondition(String categoryName) {
|
||||
|
||||
// create "rm admin" user if it does not exist and assign it to RM Administrator role
|
||||
rmRolesAndActionsAPI.createUserAndAssignToRole(
|
||||
getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(),
|
||||
RM_ADMIN, DEFAULT_PASSWORD, "Administrator");
|
||||
|
||||
// create category
|
||||
STEP("Create category");
|
||||
RecordCategoryOne = createRootCategory(categoryName,"Title");
|
||||
|
||||
unfiledContainer = getRestAPIFactory().getUnfiledContainersAPI().getUnfiledContainer(UNFILED_RECORDS_CONTAINER_ALIAS);
|
||||
|
||||
unfiledRecordsNodeRef = NODE_PREFIX + unfiledContainer.getId();
|
||||
}
|
||||
private void createTestPrecondition() {
|
||||
STEP("Create collab_user user");
|
||||
testUser = getDataUser().createRandomTestUser();
|
||||
testSite = dataSite.usingAdmin().createPublicRandomSite();
|
||||
|
||||
// invite collab_user to Collaboration site with Contributor role
|
||||
getDataUser().addUserToSite(testUser, testSite, UserRole.SiteContributor);
|
||||
|
||||
testFolder = dataContent.usingSite(testSite).usingUser(testUser).createFolder();
|
||||
}
|
||||
private void fileToRuleAppliedOnUnfiledRecords() {
|
||||
unfiledRecordsRuleTeardown();
|
||||
|
||||
// create a rule
|
||||
RuleDefinition ruleDefinition = RuleDefinition.createNewRule().title(RULE_NAME)
|
||||
.description(RULE_NAME)
|
||||
.createRecordPath(false)
|
||||
.path("/" + RECORDS_CATEGORY_ONE + "/" + RECORD_FOLDER_ONE)
|
||||
.runInBackground(true)
|
||||
.actions(asList(ActionsOnRule.FILE_TO.getActionValue()));
|
||||
|
||||
// create a rule on unfiledRecords
|
||||
rulesAPI.createRule(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), unfiledRecordsNodeRef, ruleDefinition);
|
||||
}
|
||||
private void unfiledRecordsRuleTeardown() {
|
||||
rulesAPI.deleteAllRulesOnContainer(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), unfiledRecordsNodeRef);
|
||||
}
|
||||
public UserModel createSiteManager() {
|
||||
UserModel siteManager = getDataUser().createRandomTestUser();
|
||||
getDataUser().addUserToSite(siteManager, privateSite, UserRole.SiteManager);
|
||||
return siteManager;
|
||||
}
|
||||
@AfterClass
|
||||
public void cleanupCategory() {
|
||||
unfiledRecordsRuleTeardown();
|
||||
rmRolesAndActionsAPI.deleteAllItemsInContainer(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), RM_SITE_ID, RECORD_FOLDER_ONE);
|
||||
rmRolesAndActionsAPI.deleteAllItemsInContainer(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), RM_SITE_ID, RecordCategoryOne.getName());
|
||||
deleteRecordCategory(RecordCategoryOne.getId());
|
||||
|
||||
rmRolesAndActionsAPI.deleteAllItemsInContainer(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), RM_SITE_ID, RECORD_FOLDER_TWO);
|
||||
rmRolesAndActionsAPI.deleteAllItemsInContainer(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), RM_SITE_ID, RecordCategoryTwo.getName());
|
||||
deleteRecordCategory(RecordCategoryTwo.getId());
|
||||
|
||||
dataSite.usingAdmin().deleteSite(privateSite);
|
||||
dataSite.usingAdmin().deleteSite(testSite);
|
||||
|
||||
UnfiledContainerChildCollection unfiledContainerChildCollection = getRestAPIFactory()
|
||||
.getUnfiledContainersAPI().getUnfiledContainerChildren(unfiledContainer.getId());
|
||||
|
||||
unfiledContainerChildCollection.getEntries().forEach(unfiledChild ->
|
||||
{
|
||||
if (unfiledChild.getEntry().getIsRecord())
|
||||
{
|
||||
getRestAPIFactory().getRecordsAPI().deleteRecord(unfiledChild.getEntry().getId());
|
||||
}
|
||||
else
|
||||
{
|
||||
getRestAPIFactory().getUnfiledRecordFoldersAPI().deleteUnfiledRecordFolder(unfiledChild.getEntry().getId());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@@ -102,7 +102,7 @@ public class DeleteRecordTests extends BaseRMRestTest
|
||||
testSite = dataSite.usingAdmin().createPublicRandomSite();
|
||||
recordFolder = createCategoryFolderInFilePlan();
|
||||
unfiledRecordFolder = createUnfiledContainerChild(UNFILED_RECORDS_CONTAINER_ALIAS, getRandomName("Unfiled Folder "),
|
||||
UNFILED_RECORD_FOLDER_TYPE);
|
||||
UNFILED_RECORD_FOLDER_TYPE);
|
||||
}
|
||||
|
||||
/** Data provider with electronic and non-electronic records to be deleted */
|
||||
@@ -133,10 +133,10 @@ public class DeleteRecordTests extends BaseRMRestTest
|
||||
* </pre>
|
||||
*/
|
||||
@Test
|
||||
(
|
||||
dataProvider = "recordsToBeDeleted",
|
||||
description = "Admin user can delete records"
|
||||
)
|
||||
(
|
||||
dataProvider = "recordsToBeDeleted",
|
||||
description = "Admin user can delete records"
|
||||
)
|
||||
@AlfrescoTest(jira="RM-4363")
|
||||
public void adminCanDeleteRecords(String recordId)
|
||||
{
|
||||
@@ -154,17 +154,17 @@ public class DeleteRecordTests extends BaseRMRestTest
|
||||
* </pre>
|
||||
*/
|
||||
@Test
|
||||
(
|
||||
description = "User without write permissions can't delete a record"
|
||||
)
|
||||
(
|
||||
description = "User without write permissions can't delete a record"
|
||||
)
|
||||
@AlfrescoTest(jira="RM-4363")
|
||||
public void userWithoutWritePermissionsCantDeleteRecord()
|
||||
{
|
||||
// Create a non-electronic record in unfiled records
|
||||
UnfiledContainerChild nonElectronicRecord = UnfiledContainerChild.builder()
|
||||
.name("Record " + RandomData.getRandomAlphanumeric())
|
||||
.nodeType(NON_ELECTRONIC_RECORD_TYPE)
|
||||
.build();
|
||||
.name("Record " + RandomData.getRandomAlphanumeric())
|
||||
.nodeType(NON_ELECTRONIC_RECORD_TYPE)
|
||||
.build();
|
||||
UnfiledContainerChild newRecord = getRestAPIFactory().getUnfiledContainersAPI().createUnfiledContainerChild(nonElectronicRecord, UNFILED_RECORDS_CONTAINER_ALIAS);
|
||||
|
||||
assertStatusCode(CREATED);
|
||||
@@ -187,9 +187,9 @@ public class DeleteRecordTests extends BaseRMRestTest
|
||||
* </pre>
|
||||
*/
|
||||
@Test
|
||||
(
|
||||
description = "User without delete records capability can't delete a record"
|
||||
)
|
||||
(
|
||||
description = "User without delete records capability can't delete a record"
|
||||
)
|
||||
@AlfrescoTest(jira="RM-4363")
|
||||
public void userWithoutDeleteRecordsCapabilityCantDeleteRecord()
|
||||
{
|
||||
@@ -234,7 +234,7 @@ public class DeleteRecordTests extends BaseRMRestTest
|
||||
|
||||
STEP("Create a record in first folder and copy it into second folder.");
|
||||
String recordId = getRestAPIFactory().getRecordFolderAPI()
|
||||
.createRecord(createElectronicRecordModel(), recordFolder.getId(), getFile(IMAGE_FILE)).getId();
|
||||
.createRecord(createElectronicRecordModel(), recordFolder.getId(), getFile(IMAGE_FILE)).getId();
|
||||
String copyId = copyNode(recordId, recordFolderB.getId()).getId();
|
||||
assertStatusCode(CREATED);
|
||||
|
||||
@@ -323,9 +323,9 @@ public class DeleteRecordTests extends BaseRMRestTest
|
||||
|
||||
STEP("Execute the disposition schedule steps.");
|
||||
rmRolesAndActionsAPI.executeAction(getAdminUser().getUsername(), getAdminUser().getUsername(), recordFiled.getName(),
|
||||
RM_ACTIONS.CUT_OFF);
|
||||
RM_ACTIONS.CUT_OFF);
|
||||
rmRolesAndActionsAPI.executeAction(getAdminUser().getUsername(), getAdminUser().getUsername(), recordFiled.getName(),
|
||||
RM_ACTIONS.DESTROY);
|
||||
RM_ACTIONS.DESTROY);
|
||||
|
||||
STEP("Check that it's possible to load the copy content.");
|
||||
getNodeContent(copy.getId());
|
||||
@@ -348,14 +348,14 @@ public class DeleteRecordTests extends BaseRMRestTest
|
||||
|
||||
STEP("Declare file version as record.");
|
||||
recordsAPI.declareDocumentVersionAsRecord(getAdminUser().getUsername(), getAdminUser().getPassword(), testSite.getId(),
|
||||
testFile.getName());
|
||||
testFile.getName());
|
||||
UnfiledContainerChild unfiledContainerChild = getRestAPIFactory().getUnfiledContainersAPI()
|
||||
.getUnfiledContainerChildren(UNFILED_RECORDS_CONTAINER_ALIAS)
|
||||
.getEntries().stream()
|
||||
.filter(child -> child.getEntry().getName()
|
||||
.startsWith(testFile.getName().substring(0, testFile.getName().indexOf("."))))
|
||||
.findFirst()
|
||||
.get().getEntry();
|
||||
.getUnfiledContainerChildren(UNFILED_RECORDS_CONTAINER_ALIAS)
|
||||
.getEntries().stream()
|
||||
.filter(child -> child.getEntry().getName()
|
||||
.startsWith(testFile.getName().substring(0, testFile.getName().indexOf("."))))
|
||||
.findFirst()
|
||||
.get().getEntry();
|
||||
|
||||
STEP("Delete the record.");
|
||||
deleteAndVerify(unfiledContainerChild.getId());
|
||||
|
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* #%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.records;
|
||||
|
||||
import org.alfresco.dataprep.ContentService;
|
||||
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
|
||||
import org.alfresco.rest.v0.RMRolesAndActionsAPI;
|
||||
import org.alfresco.rest.v0.RecordsAPI;
|
||||
import org.alfresco.test.AlfrescoTest;
|
||||
import org.apache.commons.httpclient.HttpStatus;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.alfresco.rest.core.v0.BaseAPI.RM_SITE_ID;
|
||||
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
|
||||
import static org.testng.AssertJUnit.assertEquals;
|
||||
import static org.testng.AssertJUnit.assertFalse;
|
||||
|
||||
/**
|
||||
* Tests to cover share action for records
|
||||
* @author Kavit Shah
|
||||
*/
|
||||
public class ShareRecordsTest extends BaseRMRestTest {
|
||||
|
||||
/** data prep services*/
|
||||
@Autowired
|
||||
private RecordsAPI service;
|
||||
@Autowired
|
||||
private ContentService contentService;
|
||||
@Autowired
|
||||
private RMRolesAndActionsAPI rmRolesAndActionsAPI;
|
||||
/** Constants*/
|
||||
private final String TEST_PREFIX = generateTestPrefix(ShareRecordsTest.class);
|
||||
private final String CATEGORY = "CategoryWithSharedRecords" + TEST_PREFIX;
|
||||
private final String FOLDER = "FolderWithSharedRecords" + TEST_PREFIX;
|
||||
private final String ELECTRONIC_RECORD = "ELECTRONIC_RECORD" + TEST_PREFIX;
|
||||
private final String NONELECTRONIC_REC = "NON_ELECTRONIC_RECORD" + TEST_PREFIX;
|
||||
private RecordCategory category;
|
||||
private RecordCategoryChild recordCategoryChild;
|
||||
/**
|
||||
* Given a record
|
||||
* When admin tries to share it via API
|
||||
* Then the record can't be shared
|
||||
*/
|
||||
@Test
|
||||
@AlfrescoTest(jira = "RM-5308")
|
||||
public void shareRecordViaApi()
|
||||
{
|
||||
//create RM Site
|
||||
createRMSiteIfNotExists();
|
||||
|
||||
//create a category
|
||||
category = createRootCategory(CATEGORY);
|
||||
|
||||
//create folder
|
||||
recordCategoryChild = createFolder(category.getId(),FOLDER);
|
||||
|
||||
createNonElectronicRecord(recordCategoryChild.getId(),NONELECTRONIC_REC);
|
||||
|
||||
// create record to be shared
|
||||
createElectronicRecord(recordCategoryChild.getId(),ELECTRONIC_RECORD);
|
||||
|
||||
//get the node id for the ELECTRONIC_RECORD created
|
||||
String nodeRefRec1= contentService.getNodeRefByPath(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(),
|
||||
"/Sites/" + RM_SITE_ID + "/documentLibrary/" + CATEGORY + "/" + FOLDER + "/" + service.getRecordFullName(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), FOLDER, ELECTRONIC_RECORD));
|
||||
//check record can't be shared
|
||||
assertFalse("The record has been succesfully shared",
|
||||
service.shareDocument(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(),nodeRefRec1 ).getKey());
|
||||
//check the error code when trying to share a record
|
||||
assertEquals("The API response code is not " + HttpStatus.SC_INTERNAL_SERVER_ERROR, service.shareDocument(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), nodeRefRec1).getValue(),
|
||||
String.valueOf( HttpStatus.SC_INTERNAL_SERVER_ERROR));
|
||||
|
||||
//get the node id for NONELECTRONIC_REC created
|
||||
String nodeRefRec2 = contentService.getNodeRefByPath(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(),
|
||||
"/Sites/" + RM_SITE_ID + "/documentLibrary/" + CATEGORY + "/" + FOLDER + "/" + service.getRecordFullName(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), FOLDER, NONELECTRONIC_REC));
|
||||
//check record can't be shared
|
||||
assertFalse("The record has been succesfully shared",
|
||||
service.shareDocument(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), nodeRefRec2).getKey());
|
||||
//check the error code when trying to share a record
|
||||
assertEquals("The API response code is not " + HttpStatus.SC_INTERNAL_SERVER_ERROR, service.shareDocument(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), nodeRefRec2).getValue(),
|
||||
String.valueOf(HttpStatus.SC_INTERNAL_SERVER_ERROR));
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public void cleanupCategory() {
|
||||
rmRolesAndActionsAPI.deleteAllItemsInContainer(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), RM_SITE_ID, recordCategoryChild.getName());
|
||||
rmRolesAndActionsAPI.deleteAllItemsInContainer(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), RM_SITE_ID, category.getName());
|
||||
deleteRecordCategory(category.getId());
|
||||
}
|
||||
}
|
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* #%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.smoke;
|
||||
|
||||
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
|
||||
import org.alfresco.rest.v0.RMRolesAndActionsAPI;
|
||||
import org.alfresco.rest.v0.RecordFoldersAPI;
|
||||
import org.alfresco.rest.v0.service.DispositionScheduleService;
|
||||
import org.alfresco.test.AlfrescoTest;
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.testng.annotations.AfterMethod;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.alfresco.rest.rm.community.model.recordcategory.RetentionPeriodProperty.CREATED_DATE;
|
||||
import static org.alfresco.rest.rm.community.model.recordcategory.RetentionPeriodProperty.CUT_OFF_DATE;
|
||||
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
|
||||
import static org.alfresco.rest.rm.community.utils.CoreUtil.createBodyForMoveCopy;
|
||||
import static org.alfresco.rest.rm.community.utils.CoreUtil.toContentModel;
|
||||
import static org.alfresco.utility.data.RandomData.getRandomName;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.springframework.http.HttpStatus.OK;
|
||||
import static org.testng.AssertJUnit.assertNotNull;
|
||||
|
||||
|
||||
public class DestroyRecordFolderActionsTest extends BaseRMRestTest {
|
||||
|
||||
private RecordCategory Category1,CATEGORY_TO_MOVE;
|
||||
@Autowired
|
||||
private DispositionScheduleService dispositionScheduleService;
|
||||
@Autowired
|
||||
private RecordFoldersAPI recordFoldersAPI;
|
||||
private final String TEST_PREFIX = generateTestPrefix(DestroyRecordFolderActionsTest.class);
|
||||
private final String folderDisposition = TEST_PREFIX + "RM-2937 folder ghosting";
|
||||
|
||||
|
||||
@BeforeClass(alwaysRun = true)
|
||||
private void setUp(){
|
||||
|
||||
STEP("Create the RM site if doesn't exist");
|
||||
createRMSiteIfNotExists();
|
||||
|
||||
STEP("Create two record category");
|
||||
Category1 = createRootCategory(getRandomName("Category1"));
|
||||
CATEGORY_TO_MOVE = createRootCategory(getRandomName("CATEGORY_TO_MOVE"));
|
||||
|
||||
//create retention schedule
|
||||
dispositionScheduleService.createCategoryRetentionSchedule(Category1.getName(), false);
|
||||
|
||||
// add cut off step
|
||||
dispositionScheduleService.addCutOffAfterPeriodStep(Category1.getName(), "day|2", CREATED_DATE);
|
||||
|
||||
// add destroy step with ghosting
|
||||
dispositionScheduleService.addDestroyWithGhostingImmediatelyAfterCutOff(Category1.getName());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@AlfrescoTest (jira = "RM-1621")
|
||||
public void moveOnCutOffDestroyFolders() throws Exception {
|
||||
|
||||
//create folders
|
||||
RecordCategoryChild FOLDER_DESTROY = createFolder(getAdminUser(),Category1.getId(),folderDisposition);
|
||||
|
||||
// edit disposition date
|
||||
recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),editDispositionDateJson(),FOLDER_DESTROY.getName());
|
||||
|
||||
// cut off the FOLDER_DESTROY
|
||||
recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),FOLDER_DESTROY.getName());
|
||||
|
||||
|
||||
// Destroy the FOLDER_DESTROY
|
||||
recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),new JSONObject().put("name","destroy"),FOLDER_DESTROY.getName());
|
||||
|
||||
|
||||
//Move the FOLDER_DESTROY within the CATEGORY_TO_MOVE.");
|
||||
getRestAPIFactory().getNodeAPI(toContentModel(FOLDER_DESTROY.getId())).move(createBodyForMoveCopy(CATEGORY_TO_MOVE.getId()));
|
||||
assertStatusCode(OK);
|
||||
|
||||
}
|
||||
|
||||
@AfterMethod(alwaysRun = true)
|
||||
private void deletePreconditions() {
|
||||
|
||||
deleteRecordCategory(Category1.getId());
|
||||
deleteRecordCategory(CATEGORY_TO_MOVE.getId());
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,425 @@
|
||||
/*
|
||||
* #%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.smoke;
|
||||
|
||||
import org.alfresco.rest.core.v0.RMEvents;
|
||||
import org.alfresco.rest.model.RestNodeBodyMoveCopyModel;
|
||||
import org.alfresco.rest.model.RestNodeModel;
|
||||
import org.alfresco.rest.requests.Node;
|
||||
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
|
||||
import org.alfresco.rest.rm.community.model.fileplan.FilePlan;
|
||||
import org.alfresco.rest.rm.community.model.record.Record;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
|
||||
import org.alfresco.rest.rm.community.model.user.UserRoles;
|
||||
import org.alfresco.rest.v0.LinksAPI;
|
||||
import org.alfresco.rest.v0.RMRolesAndActionsAPI;
|
||||
import org.alfresco.rest.v0.RecordFoldersAPI;
|
||||
import org.alfresco.rest.v0.RecordsAPI;
|
||||
import org.alfresco.rest.v0.service.DispositionScheduleService;
|
||||
import org.alfresco.test.AlfrescoTest;
|
||||
import org.alfresco.utility.model.RepoTestModel;
|
||||
import org.alfresco.utility.model.UserModel;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
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.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.alfresco.rest.core.v0.BaseAPI.NODE_REF_WORKSPACE_SPACES_STORE;
|
||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.FILE_PLAN_ALIAS;
|
||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAspects.CUT_OFF_ASPECT;
|
||||
import static org.alfresco.rest.rm.community.model.recordcategory.RetentionPeriodProperty.*;
|
||||
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.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.http.HttpStatus.NO_CONTENT;
|
||||
|
||||
public class DispositionScheduleLinkedRecordsTest extends BaseRMRestTest {
|
||||
@Autowired
|
||||
private RMRolesAndActionsAPI rmRolesAndActionsAPI;
|
||||
@Autowired
|
||||
private DispositionScheduleService dispositionScheduleService;
|
||||
@Autowired
|
||||
private LinksAPI linksAPI;
|
||||
@Autowired
|
||||
private RecordsAPI recordsAPI;
|
||||
@Autowired
|
||||
private RecordFoldersAPI recordFoldersAPI;
|
||||
private final static String TEST_PREFIX = generateTestPrefix(DispositionScheduleLinkedRecordsTest.class);
|
||||
private RecordCategory Category1,catsameLevel1,catsameLevel2;
|
||||
private RecordCategoryChild CopyCatFolder,folder1,CatFolder,folder2;
|
||||
private static final String categoryRM3077 = TEST_PREFIX + "RM-3077_manager_sees_me";
|
||||
private static final String copyCategoryRM3077 = "Copy_of_" + categoryRM3077;
|
||||
private static final String folderRM3077 = "RM-3077_folder_"+ categoryRM3077;
|
||||
private static final String copyFolderRM3077 = "Copy_of_" + folderRM3077;
|
||||
private final String electronicRecord = "RM-2937 electronic 2 record";
|
||||
private final String folder = TEST_PREFIX + "RM-2937 folder ghosting";
|
||||
private static final String categoryRecordsRM2526 = TEST_PREFIX + "RM-2526_category_records_immediately";
|
||||
private static final String category2RecordsRM2526 = TEST_PREFIX + "RM-2526_category_2_records_1_day";
|
||||
private static final String firstCategoryRM3060 = TEST_PREFIX + "RM-3060_category_record";
|
||||
private static final String secondCategoryRM3060 = "Copy_of_" + firstCategoryRM3060;
|
||||
private static final String firstFolderRM3060 = TEST_PREFIX + "RM-3060_folder";
|
||||
private static final String secondFolderRM3060 = TEST_PREFIX + "RM-3060_disposition_on_Record_Level";
|
||||
private static final String electronicRecordRM3060 = TEST_PREFIX + "RM-3060_electronic_1_record";
|
||||
private static final String nonElectronicRecordRM3060 = TEST_PREFIX + "RM-3060_non-electronic_record";
|
||||
private static final String TRANSFER_LOCATION = TEST_PREFIX + "RM-3060_transferred_records";
|
||||
public static final String TRANSFER_TYPE = "rma:transferred";
|
||||
private FilePlan filePlanModel;
|
||||
private UserModel rmAdmin, rmManager;
|
||||
@BeforeClass(alwaysRun = true)
|
||||
public void setupDispositionScheduleLinkedRecordsTest() {
|
||||
createRMSiteIfNotExists();
|
||||
//get file plan
|
||||
filePlanModel = getRestAPIFactory().getFilePlansAPI().getFilePlan(FILE_PLAN_ALIAS);
|
||||
|
||||
// create "rm admin" user if it does not exist and assign it to RM Administrator role
|
||||
rmAdmin = getDataUser().createRandomTestUser();
|
||||
rmRolesAndActionsAPI.assignRoleToUser(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(),rmAdmin.getUsername(),
|
||||
UserRoles.ROLE_RM_ADMIN.roleId);
|
||||
|
||||
// create "rm Manager" user if it does not exist and assign it to RM Administrator role
|
||||
rmManager = getDataUser().createRandomTestUser();
|
||||
rmRolesAndActionsAPI.assignRoleToUser(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(),rmManager.getUsername(),
|
||||
UserRoles.ROLE_RM_MANAGER.roleId);
|
||||
}
|
||||
/**
|
||||
* Disposition Schedule on Record Folder with linked records test
|
||||
* <p>
|
||||
* Precondition:
|
||||
* <p>
|
||||
* Create rm_manager user that would have RM Managers role, rm_admin that would have RM Administrator role.
|
||||
* Log in with admin user, create a category "manager sees me", give rm_manager read&file permission over it.
|
||||
* Create a disposition schedule for it that would cut off folders after 1 day from created date. Copy the category.
|
||||
* <p>
|
||||
* <p/> TestRail Test C775<p/>
|
||||
**/
|
||||
@Test
|
||||
@AlfrescoTest(jira = "RM-1622")
|
||||
public void dispositionScheduleLinkedRecords() throws UnsupportedEncodingException {
|
||||
STEP("Create record category");
|
||||
Category1 = createRootCategory(categoryRM3077);
|
||||
|
||||
//create retention schedule
|
||||
dispositionScheduleService.createCategoryRetentionSchedule(Category1.getName(), false);
|
||||
|
||||
// add cut off step
|
||||
dispositionScheduleService.addCutOffAfterPeriodStep(Category1.getName(), "day|2", CREATED_DATE);
|
||||
|
||||
//create a copy of the category recordsCategory
|
||||
String CopyCategoryId = copyCategory(getAdminUser(),Category1.getId(), copyCategoryRM3077);
|
||||
|
||||
// create folders in both categories
|
||||
CatFolder = createRecordFolder(Category1.getId(), folderRM3077);
|
||||
CopyCatFolder = createRecordFolder(CopyCategoryId, copyFolderRM3077);
|
||||
|
||||
// create record files
|
||||
String electronicRecord = "RM-2801 electronic record";
|
||||
Record elRecord = createElectronicRecord(CatFolder.getId(), electronicRecord);
|
||||
String elRecordFullName = recordsAPI.getRecordFullName(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), CatFolder.getName(), electronicRecord);
|
||||
|
||||
String nonElectronicRecord = "RM-2801 non-electronic record";
|
||||
Record nonElRecord = createNonElectronicRecord(CatFolder.getId(), nonElectronicRecord);
|
||||
String nonElRecordFullName = recordsAPI.getRecordFullName(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), CatFolder.getName(), nonElectronicRecord);
|
||||
|
||||
// link the records to copy folder, then complete them
|
||||
List<String> recordLists = new ArrayList<>();
|
||||
recordLists.add(NODE_REF_WORKSPACE_SPACES_STORE + elRecord.getId());
|
||||
recordLists.add(NODE_REF_WORKSPACE_SPACES_STORE + nonElRecord.getId());
|
||||
|
||||
linksAPI.linkRecord(getDataUser().getAdminUser().getUsername(),
|
||||
getDataUser().getAdminUser().getPassword(), HttpStatus.SC_OK,copyCategoryRM3077 + "/" +
|
||||
copyFolderRM3077, recordLists);
|
||||
recordsAPI.completeRecord(rmAdmin.getUsername(), rmAdmin.getPassword(), elRecordFullName);
|
||||
recordsAPI.completeRecord(rmAdmin.getUsername(), rmAdmin.getPassword(), nonElRecordFullName);
|
||||
|
||||
// edit disposition date
|
||||
recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),editDispositionDateJson(),CatFolder.getName());
|
||||
|
||||
// cut off the Folder
|
||||
recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),CatFolder.getName());
|
||||
|
||||
// Verify the Content
|
||||
Node electronicNode = getNode(elRecord.getId());
|
||||
assertTrue("The content of " + electronicRecord + " is available",
|
||||
StringUtils.isEmpty(electronicNode.getNodeContent().getResponse().getBody().asString()));
|
||||
|
||||
// verify the Properties
|
||||
AssertJUnit.assertNull("The properties are present even after cutting off the record.", elRecord.getProperties().getTitle());
|
||||
|
||||
// delete precondition
|
||||
deleteRecordCategory(Category1.getId());
|
||||
deleteRecordCategory(CopyCategoryId);
|
||||
}
|
||||
/**
|
||||
* Test covering RM-3060
|
||||
* Check the disposition steps for a record can be executed
|
||||
* When the record is linked to a folder with the same disposition schedule
|
||||
* */
|
||||
@Test
|
||||
@AlfrescoTest (jira = "RM-3060")
|
||||
public void sameDispositionScheduleLinkedRecords() throws UnsupportedEncodingException {
|
||||
|
||||
// create a category with retention applied on records level
|
||||
RecordCategory recordCategory = getRestAPIFactory().getFilePlansAPI(rmAdmin)
|
||||
.createRootRecordCategory(RecordCategory.builder().name(firstCategoryRM3060).build(),
|
||||
RecordCategory.DEFAULT_FILE_PLAN_ALIAS);
|
||||
dispositionScheduleService.createCategoryRetentionSchedule(firstCategoryRM3060, true);
|
||||
dispositionScheduleService.addCutOffAfterPeriodStep(firstCategoryRM3060, "week|1", DATE_FILED);
|
||||
dispositionScheduleService.addTransferAfterEventStep(firstCategoryRM3060, TRANSFER_LOCATION, RMEvents.CASE_CLOSED.getEventName());
|
||||
dispositionScheduleService.addDestroyWithoutGhostingAfterPeriodStep(firstCategoryRM3060, "week|1", CUT_OFF_DATE);
|
||||
|
||||
// make a copy of the category created
|
||||
String categorySecondId = copyCategory(getAdminUser(), recordCategory.getId(), secondCategoryRM3060);
|
||||
|
||||
// create a folder on the category firstCategoryRM3060 with a complete electronic record
|
||||
RecordCategoryChild firstFolderRecordCategoryChild = createRecordFolder(recordCategory.getId(),firstFolderRM3060);
|
||||
Record firstElectronicRecord = createElectronicRecord(firstFolderRecordCategoryChild.getId(),electronicRecordRM3060);
|
||||
|
||||
String elRecordFullName = recordsAPI.getRecordFullName(getDataUser().getAdminUser().getUsername(),
|
||||
getDataUser().getAdminUser().getPassword(),firstFolderRM3060, electronicRecordRM3060);
|
||||
String elRecordNameNodeRef = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordFullName, "/" + firstCategoryRM3060 + "/" + firstFolderRM3060);
|
||||
|
||||
recordsAPI.completeRecord(getDataUser().getAdminUser().getUsername(),
|
||||
getDataUser().getAdminUser().getPassword(), elRecordFullName);
|
||||
|
||||
// create a folder on the category secondCategoryRM3060 with a non electronic record
|
||||
RecordCategoryChild secondFolderRecordCategoryChild = createRecordFolder(categorySecondId,secondFolderRM3060);
|
||||
Record secondNonElectronicRecord = createNonElectronicRecord(secondFolderRecordCategoryChild.getId(),nonElectronicRecordRM3060);
|
||||
|
||||
// link the nonElectronicRecordRM3060 to firstFolderRM3060
|
||||
List<String> recordLists = new ArrayList<>();
|
||||
recordLists.add(NODE_REF_WORKSPACE_SPACES_STORE + secondNonElectronicRecord.getId());
|
||||
|
||||
linksAPI.linkRecord(getDataUser().getAdminUser().getUsername(),
|
||||
getDataUser().getAdminUser().getPassword(), HttpStatus.SC_OK,secondCategoryRM3060 + "/" +
|
||||
secondFolderRM3060, recordLists);
|
||||
String nonElRecordFullName = recordsAPI.getRecordFullName(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), secondFolderRM3060, secondNonElectronicRecord.getName());
|
||||
String nonElRecordNameNodeRef = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), nonElRecordFullName, "/" + secondCategoryRM3060 + "/" + secondFolderRM3060);
|
||||
|
||||
// complete records and cut them off
|
||||
recordsAPI.completeRecord(getDataUser().getAdminUser().getUsername(),
|
||||
getDataUser().getAdminUser().getPassword(), nonElRecordFullName);
|
||||
|
||||
// edit the disposition date
|
||||
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),editDispositionDateJson(),nonElRecordNameNodeRef);
|
||||
|
||||
// cut off the record
|
||||
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),nonElRecordNameNodeRef);
|
||||
|
||||
//check the record is cut off
|
||||
AssertJUnit.assertTrue("The file " + nonElectronicRecordRM3060 + " has not been successfully cut off.", getRestAPIFactory().getRecordsAPI().getRecord(secondNonElectronicRecord.getId()).getAspectNames().contains(CUT_OFF_ASPECT));
|
||||
|
||||
// link the electronic record to secondFolderRM3060
|
||||
recordLists.clear();
|
||||
recordLists.add(NODE_REF_WORKSPACE_SPACES_STORE + secondNonElectronicRecord.getId());
|
||||
linksAPI.linkRecord(getDataUser().getAdminUser().getUsername(),
|
||||
getDataUser().getAdminUser().getPassword(), HttpStatus.SC_OK,secondCategoryRM3060 + "/" +
|
||||
secondFolderRM3060, recordLists);
|
||||
|
||||
// edit the disposition date and cut off the record
|
||||
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),editDispositionDateJson(),elRecordNameNodeRef);
|
||||
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),elRecordNameNodeRef);
|
||||
|
||||
AssertJUnit.assertTrue("The file " + electronicRecordRM3060 + " has not been successfully cut off.", getRestAPIFactory().getRecordsAPI().getRecord(firstElectronicRecord.getId()).getAspectNames().contains(CUT_OFF_ASPECT));
|
||||
|
||||
// open the record and complete the disposition schedule event
|
||||
rmRolesAndActionsAPI.completeEvent(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(), elRecordFullName, RMEvents.CASE_CLOSED, Instant.now());
|
||||
rmRolesAndActionsAPI.completeEvent(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(), nonElRecordFullName, RMEvents.CASE_CLOSED, Instant.now());
|
||||
|
||||
// transfer the files & complete transfers
|
||||
HttpResponse nonElRecordNameHttpResponse = recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),new JSONObject().put("name","transfer"),recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), nonElRecordFullName, "/" + secondCategoryRM3060 + "/" + secondFolderRM3060));
|
||||
|
||||
String nonElRecordNameTransferId = getTransferId(nonElRecordNameHttpResponse,nonElRecordNameNodeRef);
|
||||
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),new JSONObject().put("name","transferComplete"),nonElRecordNameTransferId);
|
||||
|
||||
HttpResponse elRecordNameHttpResponse = recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),new JSONObject().put("name","transfer"),recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordFullName, "/" + firstCategoryRM3060 + "/" + firstFolderRM3060));
|
||||
|
||||
String elRecordNameTransferId = getTransferId(elRecordNameHttpResponse,elRecordNameNodeRef);
|
||||
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),new JSONObject().put("name","transferComplete"),elRecordNameTransferId);
|
||||
|
||||
AssertJUnit.assertTrue("The file " + electronicRecordRM3060 + " has not been successfully transferred", getRestAPIFactory().getRecordsAPI().getRecord(firstElectronicRecord.getId()).getAspectNames().contains(TRANSFER_TYPE));
|
||||
AssertJUnit.assertTrue("The file " + nonElectronicRecordRM3060 + " has not been successfully transferred.", getRestAPIFactory().getRecordsAPI().getRecord(secondNonElectronicRecord.getId()).getAspectNames().contains(TRANSFER_TYPE));
|
||||
|
||||
// edit the disposition date for nonElectronicRecordRM3060 & electronicRecordRM3060
|
||||
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),editDispositionDateJson(),nonElRecordNameNodeRef);
|
||||
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),editDispositionDateJson(),elRecordNameNodeRef);
|
||||
|
||||
// destroy nonElectronicRecordRM3060 & electronicRecordRM3060 records
|
||||
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),new JSONObject().put("name","destroy"),nonElRecordNameNodeRef);
|
||||
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),new JSONObject().put("name","destroy"),elRecordNameNodeRef);
|
||||
|
||||
// check the file is not displayed
|
||||
assertNull("The file " + nonElectronicRecordRM3060 + " has not been successfully destroyed.", secondNonElectronicRecord.getContent());
|
||||
assertNull("The file " + electronicRecordRM3060 + " has not been successfully destroyed.", firstElectronicRecord.getContent());
|
||||
|
||||
// delete precondition
|
||||
deleteRecordCategory(recordCategory.getId());
|
||||
deleteRecordCategory(categorySecondId);
|
||||
}
|
||||
private String copyCategory(UserModel user, String categoryId, String copyName) {
|
||||
RepoTestModel repoTestModel = new RepoTestModel() {};
|
||||
repoTestModel.setNodeRef(categoryId);
|
||||
RestNodeModel restNodeModel;
|
||||
|
||||
RestNodeBodyMoveCopyModel copyDestinationInfo = new RestNodeBodyMoveCopyModel();
|
||||
copyDestinationInfo.setTargetParentId(filePlanModel.getId());
|
||||
copyDestinationInfo.setName(copyName);
|
||||
|
||||
try
|
||||
{
|
||||
restNodeModel = getRestAPIFactory().getNodeAPI(user, repoTestModel).copy(copyDestinationInfo);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException("Problem copying category.", e);
|
||||
}
|
||||
return restNodeModel.getId();
|
||||
}
|
||||
|
||||
private Node getNode(String recordId)
|
||||
{
|
||||
RepoTestModel repoTestModel = new RepoTestModel() {};
|
||||
repoTestModel.setNodeRef(recordId);
|
||||
return getRestAPIFactory().getNodeAPI(repoTestModel);
|
||||
}
|
||||
|
||||
private String getTransferId(HttpResponse httpResponse,String nodeRef) {
|
||||
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
|
||||
.getJSONObject("results")
|
||||
.get(nodeRef)
|
||||
.toString();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@AlfrescoTest(jira = "RM-1622")
|
||||
public void sameLevelDispositionScheduleStepsPeriodsCalculation() throws Exception {
|
||||
|
||||
// create a category with retention applied on records level
|
||||
RecordCategory catsameLevel1 = getRestAPIFactory().getFilePlansAPI(rmAdmin)
|
||||
.createRootRecordCategory(RecordCategory.builder().name(firstCategoryRM3060).build(),
|
||||
RecordCategory.DEFAULT_FILE_PLAN_ALIAS);
|
||||
RecordCategory catsameLevel2 = getRestAPIFactory().getFilePlansAPI(rmAdmin)
|
||||
.createRootRecordCategory(RecordCategory.builder().name(secondCategoryRM3060).build(),
|
||||
RecordCategory.DEFAULT_FILE_PLAN_ALIAS);
|
||||
|
||||
// create retention schedule applied on records for category 1
|
||||
dispositionScheduleService.createCategoryRetentionSchedule(firstCategoryRM3060, true);
|
||||
|
||||
// with retain immediately after record creation date and cut 1 day after record creation date
|
||||
dispositionScheduleService.addCutOffAfterPeriodStep(firstCategoryRM3060, "day|1", DATE_FILED);
|
||||
|
||||
|
||||
// create a folder on the category firstCategoryRM3060 with a complete electronic record
|
||||
RecordCategoryChild firstFolderRecordCategoryChild = createRecordFolder(catsameLevel1.getId(),firstFolderRM3060);
|
||||
Record firstElectronicRecord = createElectronicRecord(firstFolderRecordCategoryChild.getId(),electronicRecordRM3060);
|
||||
|
||||
String elRecordFullName = recordsAPI.getRecordFullName(getDataUser().getAdminUser().getUsername(),
|
||||
getDataUser().getAdminUser().getPassword(),firstFolderRM3060, electronicRecordRM3060);
|
||||
String elRecordNameNodeRef = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordFullName, "/" + firstCategoryRM3060 + "/" + firstFolderRM3060);
|
||||
|
||||
recordsAPI.completeRecord(getDataUser().getAdminUser().getUsername(),
|
||||
getDataUser().getAdminUser().getPassword(), elRecordFullName);
|
||||
|
||||
// create a folder on the category secondCategoryRM3060 with a non electronic record
|
||||
RecordCategoryChild secondFolderRecordCategoryChild = createRecordFolder(catsameLevel2.getId(),secondFolderRM3060);
|
||||
String elRecordNameNodeRefs = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordFullName, "/" + firstCategoryRM3060 + "/" + firstFolderRM3060);
|
||||
|
||||
|
||||
// link it to the folder in second category through the details page
|
||||
List<String> recordLists = new ArrayList<>();
|
||||
recordLists.add(NODE_REF_WORKSPACE_SPACES_STORE + firstElectronicRecord.getId());
|
||||
|
||||
linksAPI.linkRecord(getDataUser().getAdminUser().getUsername(),
|
||||
getDataUser().getAdminUser().getPassword(), HttpStatus.SC_OK,secondCategoryRM3060 + "/" +
|
||||
secondFolderRM3060, recordLists);
|
||||
|
||||
// edit disposition date
|
||||
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),editDispositionDateJson(),elRecordNameNodeRefs);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test (dependsOnMethods = {"sameLevelDispositionScheduleStepsPeriodsCalculation" })
|
||||
public void deleteLongestPeriodTestPrecondition() {
|
||||
// Delete the RM site
|
||||
getRestAPIFactory().getRMSiteAPI().deleteRMSite();
|
||||
|
||||
// Verify the status code
|
||||
assertStatusCode(NO_CONTENT);
|
||||
}
|
||||
}
|
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* #%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.smoke;
|
||||
|
||||
import org.alfresco.dataprep.CMISUtil;
|
||||
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
|
||||
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.RecordFolderCollection;
|
||||
import org.alfresco.rest.rm.community.model.user.UserRoles;
|
||||
import org.alfresco.rest.rm.community.records.FileUnfiledRecordsTests;
|
||||
import org.alfresco.rest.v0.RMRolesAndActionsAPI;
|
||||
import org.alfresco.rest.v0.RecordCategoriesAPI;
|
||||
import org.alfresco.rest.v0.RecordsAPI;
|
||||
import org.alfresco.rest.v0.service.RoleService;
|
||||
import org.alfresco.test.AlfrescoTest;
|
||||
import org.alfresco.utility.Utility;
|
||||
import org.alfresco.utility.data.DataContent;
|
||||
import org.alfresco.utility.data.DataSite;
|
||||
import org.alfresco.utility.model.FileModel;
|
||||
import org.alfresco.utility.model.FileType;
|
||||
import org.alfresco.utility.model.SiteModel;
|
||||
import org.alfresco.utility.model.UserModel;
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static org.alfresco.rest.rm.community.model.user.UserPermissions.PERMISSION_FILING;
|
||||
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.springframework.test.util.AssertionErrors.assertTrue;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
public class FileVersionAsRecordTests extends BaseRMRestTest {
|
||||
|
||||
private UserModel nonRMuser,rmManager;
|
||||
private SiteModel testSite;
|
||||
private FileModel document, documentDeclared;
|
||||
private RecordCategory category_manager, category_admin;
|
||||
private RecordCategoryChild folder_admin, folder_manager ;
|
||||
private static final String CATEGORY_MANAGER = "catManager" + generateTestPrefix(FileAsRecordTests.class);
|
||||
private static final String CATEGORY_ADMIN = "catAdmin" + generateTestPrefix(FileAsRecordTests.class);
|
||||
private static final String FOLDER_MANAGER = "recordFolder" + generateTestPrefix(FileAsRecordTests.class);
|
||||
private static final String FOLDER_ADMIN = "recordFolder" + generateTestPrefix(FileAsRecordTests.class);
|
||||
|
||||
@Autowired
|
||||
private DataSite dataSite;
|
||||
@Autowired
|
||||
private DataContent dataContent;
|
||||
@Autowired
|
||||
private RoleService roleService;
|
||||
|
||||
@BeforeClass(alwaysRun = true)
|
||||
public void preconditionForFileVersionAsRecordTests()
|
||||
{
|
||||
STEP("Create the RM site if doesn't exist");
|
||||
createRMSiteIfNotExists();
|
||||
|
||||
STEP("Create a user");
|
||||
nonRMuser = dataUser.createRandomTestUser("testUser");
|
||||
|
||||
STEP("Create a collaboration site");
|
||||
testSite = dataSite.usingUser(nonRMuser).createPublicRandomSite();
|
||||
|
||||
STEP("Create a document with the user without RM role");
|
||||
document = dataContent.usingSite(testSite)
|
||||
.usingUser(nonRMuser)
|
||||
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
|
||||
STEP("Create two categories with two folders");
|
||||
category_manager = createRootCategory(CATEGORY_MANAGER);
|
||||
category_admin = createRootCategory(CATEGORY_ADMIN);
|
||||
folder_admin = createFolder(category_admin.getId(),FOLDER_ADMIN);
|
||||
folder_manager = createFolder(category_manager.getId(),FOLDER_MANAGER);
|
||||
|
||||
STEP("Create an rm user and give filling permission over CATEGORY_MANAGER record category");
|
||||
RecordCategory recordCategory = new RecordCategory().builder()
|
||||
.id(category_manager.getId())
|
||||
.build();
|
||||
rmManager = roleService.createCollaboratorWithRMRoleAndPermission(testSite, recordCategory,
|
||||
UserRoles.ROLE_RM_MANAGER, PERMISSION_FILING);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@AlfrescoTest (jira = "APPS-1625")
|
||||
public void fileVersionAsRecordToUnfiledRecordContainer() throws Exception
|
||||
{
|
||||
|
||||
AtomicReference<RecordFolderCollection> apiChildren = new AtomicReference<>();
|
||||
|
||||
STEP("Create a document with the user without RM role");
|
||||
FileModel inplaceRecord = dataContent.usingSite(testSite).usingUser(rmManager)
|
||||
.createContent(new FileModel("declareAndFileToIntoUnfiledRecordFolder",
|
||||
FileType.TEXT_PLAIN));
|
||||
|
||||
STEP("Click on Declare and file without selecting a record folder");
|
||||
getRestAPIFactory().getActionsAPI(rmManager).declareAndFile(inplaceRecord,"");
|
||||
|
||||
STEP("Check the file is declared in unfiled record folder");
|
||||
Assert.assertTrue(isMatchingRecordInUnfiledRecords(inplaceRecord), "Record should be filed to Unfiled Records folder");
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* #%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.smoke;
|
||||
|
||||
import org.alfresco.rest.core.v0.BaseAPI;
|
||||
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
|
||||
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.RMRolesAndActionsAPI;
|
||||
import org.alfresco.rest.v0.RecordCategoriesAPI;
|
||||
import org.alfresco.rest.v0.RecordFoldersAPI;
|
||||
import org.alfresco.rest.v0.RecordsAPI;
|
||||
import org.alfresco.rest.v0.service.DispositionScheduleService;
|
||||
import org.alfresco.test.AlfrescoTest;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.Test;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import static org.alfresco.rest.rm.community.base.TestData.DEFAULT_PASSWORD;
|
||||
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
public class RecordRetentionAsOfDateTest extends BaseRMRestTest {
|
||||
|
||||
/** data prep 6services */
|
||||
@Autowired
|
||||
private RMRolesAndActionsAPI rmRolesAndActionsAPI;
|
||||
@Autowired
|
||||
private RecordsAPI recordsAPI;
|
||||
@Autowired
|
||||
private RecordFoldersAPI recordFoldersAPI;
|
||||
@Autowired
|
||||
private RecordCategoriesAPI recordCategoriesAPI;
|
||||
@Autowired
|
||||
private DispositionScheduleService dispositionScheduleService;
|
||||
private RecordCategory Category1;
|
||||
private final String TEST_PREFIX = generateTestPrefix(RecordRetentionAsOfDateTest.class);
|
||||
private final String RM_ADMIN = TEST_PREFIX + "rm_admin";
|
||||
private final String recordsCategory = TEST_PREFIX + "RM-5733 category";
|
||||
private final String folderDisposition = TEST_PREFIX + "RM-5733 folder";
|
||||
|
||||
private static final String YEAR_MONTH_DAY = "yyyy-MM-dd";
|
||||
|
||||
@Test
|
||||
@AlfrescoTest (jira = "RM-5733,RM-5799")
|
||||
public void checkRetentionAsOfDateForTransferStepWithRetentionAction() {
|
||||
|
||||
// create test precondition
|
||||
createTestPrecondition(recordsCategory);
|
||||
|
||||
// create disposition schedule
|
||||
dispositionScheduleService.createCategoryRetentionSchedule(Category1.getName(), true);
|
||||
|
||||
// add cut off step
|
||||
dispositionScheduleService.addCutOffImmediatelyStep(Category1.getName());
|
||||
|
||||
// add transfer step
|
||||
HashMap<BaseAPI.RETENTION_SCHEDULE, String> transferStep = new HashMap<>();
|
||||
transferStep.put(BaseAPI.RETENTION_SCHEDULE.RETENTION_PERIOD, "day|1");
|
||||
transferStep.put(BaseAPI.RETENTION_SCHEDULE.NAME, "transfer");
|
||||
transferStep.put(BaseAPI.RETENTION_SCHEDULE.RETENTION_PERIOD_PROPERTY, "rma:cutOffDate");
|
||||
transferStep.put(BaseAPI.RETENTION_SCHEDULE.COMBINE_DISPOSITION_STEP_CONDITIONS, "false");
|
||||
transferStep.put(BaseAPI.RETENTION_SCHEDULE.RETENTION_ELIGIBLE_FIRST_EVENT, "true");
|
||||
transferStep.put(BaseAPI.RETENTION_SCHEDULE.RETENTION_GHOST, "on");
|
||||
transferStep.put(BaseAPI.RETENTION_SCHEDULE.DESCRIPTION, "Transfer after 1 day");
|
||||
recordCategoriesAPI.addDispositionScheduleSteps(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(), Category1.getName(), transferStep);
|
||||
|
||||
// create a folder and an electronic and a non-electronic record in it
|
||||
RecordCategoryChild FOLDER = createFolder(getAdminUser(),Category1.getId(),folderDisposition);
|
||||
|
||||
String nonElectronicRecord = TEST_PREFIX + "RM-5733 non-electronic record";
|
||||
Record nonElRecord = createNonElectronicRecord(FOLDER.getId(), nonElectronicRecord);
|
||||
|
||||
// complete records and cut them off
|
||||
String nonElRecordName = recordsAPI.getRecordFullName(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(), folderDisposition, nonElectronicRecord);
|
||||
|
||||
// complete records and cut them off
|
||||
completeRecord(nonElRecord.getId());
|
||||
|
||||
String nonElRecordNameNodeRef = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), nonElRecordName, "/" + Category1.getName() + "/" + folderDisposition);
|
||||
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),nonElRecordNameNodeRef);
|
||||
|
||||
JSONObject nextDispositionActionJson = recordCategoriesAPI.getNextDispositionAction(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(),nonElRecord.getId());
|
||||
|
||||
assertTrue(getAsOfDate(nextDispositionActionJson).startsWith(getTomorrow()),
|
||||
"The retention as of date is not set to tomorrow.");
|
||||
}
|
||||
|
||||
@AfterClass(alwaysRun = true)
|
||||
public void cleanUp() {
|
||||
// delete category
|
||||
deleteRecordCategory(Category1.getId());
|
||||
}
|
||||
|
||||
private void createTestPrecondition(String categoryName) {
|
||||
createRMSiteIfNotExists();
|
||||
|
||||
// create "rm admin" user if it does not exist and assign it to RM Administrator role
|
||||
rmRolesAndActionsAPI.createUserAndAssignToRole(
|
||||
getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(),
|
||||
RM_ADMIN, DEFAULT_PASSWORD, "Administrator");
|
||||
|
||||
// create category
|
||||
STEP("Create category");
|
||||
Category1 = createRootCategory(categoryName,"Title");
|
||||
}
|
||||
|
||||
private String getAsOfDate(JSONObject nextDispositionActionJson) {
|
||||
return nextDispositionActionJson.getJSONObject("data").get("asOf").toString();
|
||||
}
|
||||
|
||||
private static String getTomorrow() {
|
||||
Date today = new Date();
|
||||
Date tomorrow = DateUtils.addDays(today, 1);
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat(YEAR_MONTH_DAY);
|
||||
return dateFormat.format(tomorrow);
|
||||
}
|
||||
|
||||
}
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||
<version>17.102-SNAPSHOT</version>
|
||||
<version>17.118</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||
<version>17.102-SNAPSHOT</version>
|
||||
<version>17.118</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||
<version>17.102-SNAPSHOT</version>
|
||||
<version>17.118</version>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>17.102-SNAPSHOT</version>
|
||||
<version>17.118</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||
<version>17.102-SNAPSHOT</version>
|
||||
<version>17.118</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -11,7 +11,7 @@ function main()
|
||||
var params =
|
||||
{
|
||||
type: "people",
|
||||
term: args.t,
|
||||
term: args.t + " [hint:useCQ]",
|
||||
maxResults: (args.maxResults !== null) ? parseInt(args.maxResults, 10) : DEFAULT_MAX_RESULTS,
|
||||
startIndex: (args.startIndex !== null) ? parseInt(args.startIndex, 10) : 0
|
||||
};
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>17.102-SNAPSHOT</version>
|
||||
<version>17.118</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -25,6 +25,9 @@ package org.alfresco.error;
|
||||
*/
|
||||
public class ExceptionStackUtil
|
||||
{
|
||||
private static final String JAVASCRIPT_EXCEPTION = "org.mozilla.javascript.JavaScriptException";
|
||||
private static final String EXCEPTION_DELIMITER = ":";
|
||||
|
||||
/**
|
||||
* Searches through the exception stack of the given throwable to find any instance
|
||||
* of the possible cause. The top-level throwable will also be tested.
|
||||
@@ -38,10 +41,17 @@ public class ExceptionStackUtil
|
||||
{
|
||||
while (throwable != null)
|
||||
{
|
||||
Class<?> throwableClass = throwable.getClass();
|
||||
|
||||
boolean isJavaScriptException = throwableClass.getName().contains(JAVASCRIPT_EXCEPTION);
|
||||
String throwableMsg = throwable.getMessage() != null ? throwable.getMessage() : "";
|
||||
|
||||
for (Class<?> possibleCauseClass : possibleCauses)
|
||||
{
|
||||
Class<?> throwableClass = throwable.getClass();
|
||||
if (possibleCauseClass.isAssignableFrom(throwableClass))
|
||||
String possibleCauseClassName = possibleCauseClass.getName();
|
||||
|
||||
if (possibleCauseClass.isAssignableFrom(throwableClass)
|
||||
|| (isJavaScriptException && throwableMsg.contains(possibleCauseClassName + EXCEPTION_DELIMITER)))
|
||||
{
|
||||
// We have a match
|
||||
return throwable;
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>17.102-SNAPSHOT</version>
|
||||
<version>17.118</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>17.102-SNAPSHOT</version>
|
||||
<version>17.118</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -9,6 +9,6 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>17.102-SNAPSHOT</version>
|
||||
<version>17.118</version>
|
||||
</parent>
|
||||
</project>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>17.102-SNAPSHOT</version>
|
||||
<version>17.118</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>17.102-SNAPSHOT</version>
|
||||
<version>17.118</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>17.102-SNAPSHOT</version>
|
||||
<version>17.118</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
12
packaging/tests/scripts/output_logs_for_failures.sh
Executable file
12
packaging/tests/scripts/output_logs_for_failures.sh
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
TAS_DIRECTORY=$1
|
||||
|
||||
cd ${TAS_DIRECTORY}
|
||||
|
||||
failures=$(grep 'status="FAIL"' target/surefire-reports/testng-results.xml | sed 's|^.*[ ]name="\([^"]*\)".*$|\1|g')
|
||||
|
||||
for failure in ${failures}
|
||||
do
|
||||
cat target/reports/alfresco-tas.log | sed '/STARTING Test: \['${failure}'\]/,/ENDING Test: \['${failure}'\]/!d;/ENDING Test: \['${failure}'\]/q'
|
||||
done
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>17.102-SNAPSHOT</version>
|
||||
<version>17.118</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>17.102-SNAPSHOT</version>
|
||||
<version>17.118</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>17.102-SNAPSHOT</version>
|
||||
<version>17.118</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>17.102-SNAPSHOT</version>
|
||||
<version>17.118</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -49,6 +49,7 @@ import java.util.stream.IntStream;
|
||||
|
||||
import org.alfresco.rest.RestTest;
|
||||
import org.alfresco.rest.model.RestActionBodyExecTemplateModel;
|
||||
import org.alfresco.rest.model.RestCompositeConditionDefinitionModel;
|
||||
import org.alfresco.rest.model.RestRuleModel;
|
||||
import org.alfresco.rest.model.RestRuleModelsCollection;
|
||||
import org.alfresco.utility.constants.UserRole;
|
||||
@@ -66,8 +67,6 @@ import org.testng.annotations.Test;
|
||||
@Test(groups = {TestGroup.RULES})
|
||||
public class CreateRulesTests extends RestTest
|
||||
{
|
||||
private static final String IGNORE_ID = "id";
|
||||
private static final String IGNORE_IS_SHARED = "isShared";
|
||||
private UserModel user;
|
||||
private SiteModel site;
|
||||
private FolderModel ruleFolder;
|
||||
@@ -94,12 +93,11 @@ public class CreateRulesTests extends RestTest
|
||||
.createSingleRule(ruleModel);
|
||||
|
||||
RestRuleModel expectedRuleModel = createRuleModelWithModifiedValues();
|
||||
expectedRuleModel.setActions(addActionContextParams(expectedRuleModel.getActions()));
|
||||
expectedRuleModel.setConditions(createEmptyConditionModel());
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
rule.assertThat().isEqualTo(expectedRuleModel, IGNORE_ID, IGNORE_IS_SHARED)
|
||||
.assertThat().field("id").isNotNull()
|
||||
.assertThat().field("isShared").isNull();
|
||||
rule.assertThat().isEqualTo(expectedRuleModel, ID, IS_SHARED)
|
||||
.assertThat().field(ID).isNotNull()
|
||||
.assertThat().field(IS_SHARED).isNull();
|
||||
}
|
||||
|
||||
/** Check creating a rule in a non-existent folder returns an error. */
|
||||
@@ -384,12 +382,108 @@ public class CreateRulesTests extends RestTest
|
||||
.createSingleRule(ruleModel);
|
||||
|
||||
final RestRuleModel expectedRuleModel = createRuleModelWithDefaultValues();
|
||||
expectedRuleModel.setActions(addActionContextParams(Arrays.asList(copyAction, checkOutAction, scriptAction)));
|
||||
expectedRuleModel.setActions(Arrays.asList(copyAction, checkOutAction, scriptAction));
|
||||
expectedRuleModel.setConditions(createEmptyConditionModel());
|
||||
expectedRuleModel.setTriggers(List.of("inbound"));
|
||||
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
rule.assertThat().isEqualTo(expectedRuleModel, IGNORE_ID, IGNORE_IS_SHARED)
|
||||
.assertThat().field("isShared").isNull();
|
||||
rule.assertThat().isEqualTo(expectedRuleModel, ID, IS_SHARED)
|
||||
.assertThat().field(IS_SHARED).isNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check we get error when attempt to create a rule without any actions.
|
||||
*/
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleWithoutActionsShouldFail()
|
||||
{
|
||||
final RestRuleModel ruleModel = createRuleModelWithDefaultValues();
|
||||
ruleModel.setActions(null);
|
||||
|
||||
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.createSingleRule(ruleModel);
|
||||
|
||||
restClient.assertStatusCodeIs(BAD_REQUEST);
|
||||
restClient.assertLastError().containsSummary("A rule must have at least one action");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check we get error when attempt to create a rule with invalid action.
|
||||
*/
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleWithInvalidActionsShouldFail()
|
||||
{
|
||||
final RestRuleModel ruleModel = createRuleModelWithDefaultValues();
|
||||
final RestActionBodyExecTemplateModel invalidAction = new RestActionBodyExecTemplateModel();
|
||||
final String actionDefinitionId = "invalid-definition-value";
|
||||
invalidAction.setActionDefinitionId(actionDefinitionId);
|
||||
invalidAction.setParams(Map.of("dummy-key", "dummy-value"));
|
||||
ruleModel.setActions(List.of(invalidAction));
|
||||
|
||||
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.createSingleRule(ruleModel);
|
||||
|
||||
restClient.assertStatusCodeIs(NOT_FOUND);
|
||||
restClient.assertLastError().containsSummary(actionDefinitionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check we can create a rule with multiple conditions
|
||||
*/
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleWithConditions()
|
||||
{
|
||||
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
|
||||
ruleModel.setConditions(createVariousConditions());
|
||||
|
||||
RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.createSingleRule(ruleModel);
|
||||
|
||||
RestRuleModel expectedRuleModel = createRuleModelWithDefaultValues();
|
||||
expectedRuleModel.setConditions(createVariousConditions());
|
||||
expectedRuleModel.setTriggers(List.of("inbound"));
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
rule.assertThat().isEqualTo(expectedRuleModel, ID, IS_SHARED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check we can create a rule with empty list as conditions
|
||||
*/
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleWithConditions_emptyConditionList()
|
||||
{
|
||||
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
|
||||
ruleModel.setConditions(createCompositeCondition(null));
|
||||
|
||||
RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.createSingleRule(ruleModel);
|
||||
|
||||
RestRuleModel expectedRuleModel = createRuleModelWithDefaultValues();
|
||||
expectedRuleModel.setConditions(createCompositeCondition(null));
|
||||
expectedRuleModel.setTriggers(List.of("inbound"));
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
rule.assertThat().isEqualTo(expectedRuleModel, ID, IS_SHARED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check we can NOT create a rule when category ID in condition is invalid, HTTP status code 400 is expected
|
||||
*/
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleWithConditions_invalidCategory()
|
||||
{
|
||||
STEP("Try to create a rule with non existing category in conditions.");
|
||||
String fakeCategoryId = "bdba5f9f-fake-id22-803b-349bcfd06fd1";
|
||||
RestCompositeConditionDefinitionModel conditions = createCompositeCondition(List.of(
|
||||
createCompositeCondition(!INVERTED, List.of(
|
||||
createSimpleCondition("category", "equals", fakeCategoryId)
|
||||
))
|
||||
));
|
||||
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
|
||||
ruleModel.setConditions(conditions);
|
||||
|
||||
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
|
||||
|
||||
restClient.assertStatusCodeIs(BAD_REQUEST);
|
||||
restClient.assertLastError().containsSummary("Category in condition is invalid");
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 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.rules;
|
||||
|
||||
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModelWithModifiedValues;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.alfresco.rest.RestTest;
|
||||
import org.alfresco.rest.model.RestRuleModel;
|
||||
import org.alfresco.rest.model.RestRuleModelsCollection;
|
||||
import org.alfresco.rest.model.RestRuleSetLinkModel;
|
||||
import org.alfresco.rest.model.RestRuleSetModel;
|
||||
import org.alfresco.rest.model.RestRuleSetModelsCollection;
|
||||
import org.alfresco.utility.model.FolderModel;
|
||||
import org.alfresco.utility.model.SiteModel;
|
||||
import org.alfresco.utility.model.TestGroup;
|
||||
import org.alfresco.utility.model.UserModel;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* Tests for GET /nodes/{nodeId}/rule-sets/{ruleSetId}/rules with rule inheritance.
|
||||
*/
|
||||
@Test(groups = {TestGroup.RULES})
|
||||
public class GetInheritedRulesTests extends RestTest
|
||||
{
|
||||
private UserModel user;
|
||||
private SiteModel site;
|
||||
|
||||
@BeforeClass(alwaysRun = true)
|
||||
public void dataPreparation()
|
||||
{
|
||||
STEP("Create a user and site");
|
||||
user = dataUser.createRandomTestUser();
|
||||
site = dataSite.usingUser(user).createPublicRandomSite();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check we can get all the rules for the folder by providing the different rule set ids.
|
||||
*/
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
|
||||
public void getInheritedRules()
|
||||
{
|
||||
STEP("Create a parent and child folder, each with inheriting rules");
|
||||
FolderModel parent = dataContent.usingUser(user).usingSite(site).createFolder();
|
||||
FolderModel child = dataContent.usingUser(user).usingResource(parent).createFolder();
|
||||
RestRuleModel parentRule = createRuleModelWithModifiedValues();
|
||||
parentRule = restClient.authenticateUser(user).withCoreAPI().usingNode(parent).usingDefaultRuleSet().createSingleRule(parentRule);
|
||||
RestRuleModel childRule = createRuleModelWithModifiedValues();
|
||||
childRule = restClient.authenticateUser(user).withCoreAPI().usingNode(child).usingDefaultRuleSet().createSingleRule(childRule);
|
||||
|
||||
STEP("Get the rules in the default rule set for the child folder");
|
||||
RestRuleModelsCollection rules = restClient.authenticateUser(user).withCoreAPI().usingNode(child).usingDefaultRuleSet().getListOfRules();
|
||||
rules.assertThat().entriesListContains("id", childRule.getId())
|
||||
.and().entriesListCountIs(1);
|
||||
|
||||
STEP("Get the rules in the inherited rule set for the child folder");
|
||||
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI().usingNode(child).include("inclusionType").getListOfRuleSets();
|
||||
String inheritedRuleSetId = ruleSets.getEntries().stream()
|
||||
.filter(ruleSet -> ruleSet.onModel().getInclusionType().equals("inherited"))
|
||||
.findFirst().get().onModel().getId();
|
||||
RestRuleModelsCollection inheritedRules = restClient.authenticateUser(user).withCoreAPI().usingNode(child).usingRuleSet(inheritedRuleSetId).getListOfRules();
|
||||
inheritedRules.assertThat().entriesListContains("id", parentRule.getId())
|
||||
.and().entriesListCountIs(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that we only get each rule once with linking and inheritance, and the order is correct.
|
||||
* <p>
|
||||
* The folder structure for this test is as follows:
|
||||
* <pre>
|
||||
* A --[links]-> DRuleSet
|
||||
* +-B --[owns]-> BRuleSet
|
||||
* +-C --[owns]-> CRuleSet
|
||||
* +-D --[owns]--> DRuleSet
|
||||
* </pre>
|
||||
*/
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
|
||||
public void rulesReturnedAreUnique()
|
||||
{
|
||||
STEP("Create four folders with rules");
|
||||
FolderModel folderA = dataContent.usingUser(user).usingSite(site).createFolder();
|
||||
FolderModel folderB = dataContent.usingUser(user).usingResource(folderA).createFolder();
|
||||
FolderModel folderC = dataContent.usingUser(user).usingResource(folderB).createFolder();
|
||||
FolderModel folderD = dataContent.usingUser(user).usingResource(folderC).createFolder();
|
||||
RestRuleModel ruleB = restClient.authenticateUser(user).withCoreAPI().usingNode(folderB).usingDefaultRuleSet().createSingleRule(createRuleModelWithModifiedValues());
|
||||
RestRuleModel ruleC = restClient.authenticateUser(user).withCoreAPI().usingNode(folderC).usingDefaultRuleSet().createSingleRule(createRuleModelWithModifiedValues());
|
||||
RestRuleModel ruleD = restClient.authenticateUser(user).withCoreAPI().usingNode(folderD).usingDefaultRuleSet().createSingleRule(createRuleModelWithModifiedValues());
|
||||
STEP("Link folderA to ruleSetD");
|
||||
RestRuleSetLinkModel linkModel = new RestRuleSetLinkModel();
|
||||
linkModel.setId(folderD.getNodeRef());
|
||||
restClient.authenticateUser(user).withCoreAPI().usingNode(folderA).createRuleLink(linkModel);
|
||||
|
||||
STEP("Get the rule sets for the folderD");
|
||||
List<RestRuleSetModel> ruleSets = restClient.authenticateUser(user).withCoreAPI().usingNode(folderD).getListOfRuleSets().getEntries();
|
||||
|
||||
STEP("Check the rules for each rule set are as expected");
|
||||
List<RestRuleModel> expectedRuleIds = List.of(ruleD, ruleB, ruleC);
|
||||
IntStream.range(0, 2).forEach(index -> {
|
||||
String ruleSetId = ruleSets.get(index).onModel().getId();
|
||||
List<RestRuleModel> rules = restClient.authenticateUser(user)
|
||||
.withCoreAPI()
|
||||
.usingNode(folderD)
|
||||
.usingRuleSet(ruleSetId)
|
||||
.getListOfRules()
|
||||
.getEntries()
|
||||
.stream()
|
||||
.map(RestRuleModel::onModel)
|
||||
.collect(Collectors.toList());
|
||||
assertEquals(rules, List.of(expectedRuleIds.get(index)), "Unexpected rules found for rule set " + ruleSetId);
|
||||
});
|
||||
assertEquals(ruleSets.size(), 3, "Expected three unique rule sets to be returned but got " + ruleSets);
|
||||
}
|
||||
}
|
@@ -25,16 +25,26 @@
|
||||
*/
|
||||
package org.alfresco.rest.rules;
|
||||
|
||||
import static org.alfresco.rest.requests.RuleSettings.IS_INHERITANCE_ENABLED;
|
||||
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModel;
|
||||
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModelWithModifiedValues;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.http.HttpStatus.NOT_FOUND;
|
||||
import static org.springframework.http.HttpStatus.OK;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import org.alfresco.rest.RestTest;
|
||||
import org.alfresco.rest.model.RestRuleModel;
|
||||
import org.alfresco.rest.model.RestRuleSetLinkModel;
|
||||
import org.alfresco.rest.model.RestRuleSetModel;
|
||||
import org.alfresco.rest.model.RestRuleSetModelsCollection;
|
||||
import org.alfresco.rest.model.RestRuleSettingsModel;
|
||||
import org.alfresco.rest.requests.coreAPI.RestCoreAPI;
|
||||
import org.alfresco.utility.constants.UserRole;
|
||||
import org.alfresco.utility.model.FolderModel;
|
||||
import org.alfresco.utility.model.SiteModel;
|
||||
import org.alfresco.utility.model.TestGroup;
|
||||
@@ -51,6 +61,8 @@ public class GetRuleSetsTests extends RestTest
|
||||
private UserModel user;
|
||||
private SiteModel site;
|
||||
private FolderModel ruleFolder;
|
||||
private FolderModel inheritingChildFolder;
|
||||
private FolderModel notInheritingChildFolder;
|
||||
private RestRuleModel rule;
|
||||
private String ruleSetId;
|
||||
|
||||
@@ -62,6 +74,14 @@ public class GetRuleSetsTests extends RestTest
|
||||
site = dataSite.usingUser(user).createPublicRandomSite();
|
||||
ruleFolder = dataContent.usingUser(user).usingSite(site).createFolder();
|
||||
|
||||
STEP("Create two children of the folder - one that inherits rules and one that doesn't");
|
||||
inheritingChildFolder = dataContent.usingUser(user).usingResource(ruleFolder).createFolder();
|
||||
notInheritingChildFolder = dataContent.usingUser(user).usingResource(ruleFolder).createFolder();
|
||||
RestRuleSettingsModel doesntInherit = new RestRuleSettingsModel();
|
||||
doesntInherit.setValue(false);
|
||||
restClient.authenticateUser(user).withCoreAPI().usingNode(notInheritingChildFolder)
|
||||
.usingIsInheritanceEnabledRuleSetting().updateSetting(doesntInherit);
|
||||
|
||||
STEP("Create a rule in the folder.");
|
||||
RestRuleModel ruleModel = createRuleModel("ruleName");
|
||||
rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
@@ -133,7 +153,7 @@ public class GetRuleSetsTests extends RestTest
|
||||
|
||||
/** Check we can get the reason that a rule set is included in the list. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
public void getRuleSetsAndInclusionType()
|
||||
public void getRuleSetsAndOwnedInclusionType()
|
||||
{
|
||||
STEP("Get the rule sets and inclusion type");
|
||||
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI()
|
||||
@@ -148,6 +168,36 @@ public class GetRuleSetsTests extends RestTest
|
||||
ruleSets.assertThat().entriesListCountIs(1);
|
||||
}
|
||||
|
||||
/** Check we can tell that a rule set has been inherited. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
public void getRuleSetsAndInheritedInclusionType()
|
||||
{
|
||||
STEP("Get the rule sets and inclusion type");
|
||||
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI()
|
||||
.usingNode(inheritingChildFolder)
|
||||
.include("inclusionType")
|
||||
.getListOfRuleSets();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
ruleSets.getEntries().get(0).onModel()
|
||||
.assertThat().field("inclusionType").is("inherited")
|
||||
.assertThat().field("id").is(ruleSetId);
|
||||
ruleSets.assertThat().entriesListCountIs(1);
|
||||
}
|
||||
|
||||
/** Check that a rule set is not inherited if inheriting is disabled. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
public void getRuleSetsWithoutInheriting()
|
||||
{
|
||||
STEP("Get the rule sets and inclusion type");
|
||||
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI()
|
||||
.usingNode(notInheritingChildFolder)
|
||||
.getListOfRuleSets();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
ruleSets.assertThat().entriesListCountIs(0);
|
||||
}
|
||||
|
||||
/** Check we can get a rule set by its id. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
|
||||
public void getRuleSetById()
|
||||
@@ -207,4 +257,78 @@ public class GetRuleSetsTests extends RestTest
|
||||
ruleSet.assertThat().field("owningFolder").is(ruleFolder.getNodeRef())
|
||||
.assertThat().field("id").is(ruleSetId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check we can find out the id of any folders that inherit a rule set.
|
||||
* <p>
|
||||
* The test checks several different situations:
|
||||
* <pre>
|
||||
* folder --[owns]-> rule set
|
||||
* +- publicFolder --[inherits]-> rule set (user has access)
|
||||
* +- privateFolder --[inherits]-> rule set (user does not have access)
|
||||
* +- publicGrandchild --[inherits]-> rule set (user has access again)
|
||||
* +- nonInheritingFolder (inheritance should be prevented)
|
||||
* +- linkingFolder --[links]-> rule set (not inherited)
|
||||
* +- descendantFolder --[inherits]-> rule set (inherited via link)
|
||||
* </pre>
|
||||
*/
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
public void getRuleSetAndInheritedBy()
|
||||
{
|
||||
STEP("Create a site owned by admin and add user as a contributor");
|
||||
SiteModel siteModel = dataSite.usingAdmin().createPrivateRandomSite();
|
||||
dataUser.addUserToSite(user, siteModel, UserRole.SiteContributor);
|
||||
|
||||
STEP("Create the folder structure");
|
||||
FolderModel folder = dataContent.usingUser(user).usingSite(siteModel).createFolder();
|
||||
FolderModel publicFolder = dataContent.usingUser(user).usingResource(folder).createFolder();
|
||||
FolderModel privateFolder = dataContent.usingAdmin().usingResource(folder).createFolder();
|
||||
dataContent.usingAdmin().usingResource(privateFolder).setInheritPermissions(false);
|
||||
// Create the grandchild with user and use admin to move it under the private folder.
|
||||
FolderModel publicGrandchild = dataContent.usingUser(user).usingSite(siteModel).createFolder();
|
||||
coreAPIForAdmin().usingActions().executeAction("move", publicGrandchild, ImmutableMap.of("destination-folder", "workspace://SpacesStore/" + privateFolder.getNodeRef()));
|
||||
// Create the non-inheriting folder.
|
||||
FolderModel nonInheritingFolder = dataContent.usingUser(user).usingResource(folder).createFolder();
|
||||
RestRuleSettingsModel nonInheriting = new RestRuleSettingsModel();
|
||||
nonInheriting.setKey(IS_INHERITANCE_ENABLED);
|
||||
nonInheriting.setValue(false);
|
||||
coreAPIForUser().usingNode(nonInheritingFolder).usingIsInheritanceEnabledRuleSetting().updateSetting(nonInheriting);
|
||||
// Create a child that will link to the rule and a child of that to inherit via the link.
|
||||
FolderModel linkingFolder = dataContent.usingUser(user).usingResource(nonInheritingFolder).createFolder();
|
||||
FolderModel descendantFolder = dataContent.usingUser(user).usingResource(linkingFolder).createFolder();
|
||||
|
||||
STEP("Create an inheritable rule in the folder and get the rule set id.");
|
||||
RestRuleModel ruleModel = createRuleModelWithModifiedValues();
|
||||
coreAPIForUser().usingNode(folder).usingDefaultRuleSet().createSingleRule(ruleModel);
|
||||
RestRuleSetModelsCollection ruleSets = coreAPIForUser().usingNode(folder).getListOfRuleSets();
|
||||
String ruleSetId = ruleSets.getEntries().get(0).onModel().getId();
|
||||
|
||||
STEP("Create the link to the rule from the linking folder");
|
||||
RestRuleSetLinkModel ruleSetLink = new RestRuleSetLinkModel();
|
||||
ruleSetLink.setId(folder.getNodeRef());
|
||||
coreAPIForUser().usingNode(linkingFolder).createRuleLink(ruleSetLink);
|
||||
|
||||
STEP("Remove the user from the site");
|
||||
dataUser.removeUserFromSite(user, siteModel);
|
||||
|
||||
STEP("Get the rule set and inheriting folders");
|
||||
RestRuleSetModel ruleSet = coreAPIForUser().usingNode(folder)
|
||||
.include("inheritedBy")
|
||||
.getRuleSet(ruleSetId);
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
List<String> expectedInheritors = List.of(publicFolder.getNodeRef(), descendantFolder.getNodeRef(), publicGrandchild.getNodeRef());
|
||||
ruleSet.assertThat().field("inheritedBy").is(expectedInheritors)
|
||||
.assertThat().field("id").is(ruleSetId);
|
||||
}
|
||||
|
||||
private RestCoreAPI coreAPIForUser()
|
||||
{
|
||||
return restClient.authenticateUser(user).withCoreAPI();
|
||||
}
|
||||
|
||||
private RestCoreAPI coreAPIForAdmin()
|
||||
{
|
||||
return restClient.authenticateUser(dataUser.getAdminUser()).withCoreAPI();
|
||||
}
|
||||
}
|
||||
|
@@ -189,7 +189,6 @@ public class GetRulesTests extends RestTest
|
||||
.createSingleRule(ruleModel);
|
||||
|
||||
RestRuleModel expectedRuleModel = createRuleModelWithModifiedValues();
|
||||
expectedRuleModel.setActions(addActionContextParams(expectedRuleModel.getActions()));
|
||||
expectedRuleModel.setTriggers(List.of("update"));
|
||||
expectedRuleModel.setConditions(createEmptyConditionModel());
|
||||
|
||||
@@ -212,7 +211,6 @@ public class GetRulesTests extends RestTest
|
||||
.createSingleRule(ruleModel);
|
||||
|
||||
RestRuleModel expectedRuleModel = createRuleModelWithDefaultValues();
|
||||
expectedRuleModel.setActions(addActionContextParams(expectedRuleModel.getActions()));
|
||||
expectedRuleModel.setTriggers(List.of("inbound"));
|
||||
expectedRuleModel.setConditions(createEmptyConditionModel());
|
||||
|
||||
|
@@ -234,7 +234,7 @@ public class RuleSetLinksTests extends RestTest
|
||||
STEP("Assert link result is 400");
|
||||
restClient.assertStatusCodeIs(BAD_REQUEST)
|
||||
.assertLastError().containsSummary(
|
||||
"Unable to link to a ruleset because the folder has pre-existing rules or is already linked to a ruleset.");
|
||||
"Unable to link to a rule set because the folder has pre-existing rules or is already linked to a rule set.");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -26,13 +26,13 @@
|
||||
package org.alfresco.rest.rules;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.rest.model.RestActionBodyExecTemplateModel;
|
||||
import org.alfresco.rest.model.RestCompositeConditionDefinitionModel;
|
||||
import org.alfresco.rest.model.RestRuleModel;
|
||||
import org.alfresco.rest.model.RestSimpleConditionDefinitionModel;
|
||||
|
||||
public class RulesTestsUtils
|
||||
{
|
||||
@@ -43,7 +43,14 @@ public class RulesTestsUtils
|
||||
static final boolean RULE_ASYNC_DEFAULT = true;
|
||||
static final boolean RULE_SHARED_DEFAULT = false;
|
||||
static final String RULE_ERROR_SCRIPT_DEFAULT = "error-script";
|
||||
static final List<String> ruleTriggersDefault = List.of("inbound", "update", "outbound");
|
||||
static final String INBOUND = "inbound";
|
||||
static final String UPDATE = "update";
|
||||
static final String OUTBOUND = "outbound";
|
||||
static final List<String> RULE_TRIGGERS_DEFAULT = List.of(INBOUND, UPDATE, OUTBOUND);
|
||||
static final boolean INVERTED = true;
|
||||
static final String AND = "and";
|
||||
static final String ID = "id";
|
||||
static final String IS_SHARED = "isShared";
|
||||
|
||||
/**
|
||||
* Create a rule model filled with default values.
|
||||
@@ -58,7 +65,7 @@ public class RulesTestsUtils
|
||||
ruleModel.setCascade(RULE_CASCADE_DEFAULT);
|
||||
ruleModel.setAsynchronous(RULE_ASYNC_DEFAULT);
|
||||
ruleModel.setIsShared(RULE_SHARED_DEFAULT);
|
||||
ruleModel.setTriggers(ruleTriggersDefault);
|
||||
ruleModel.setTriggers(RULE_TRIGGERS_DEFAULT);
|
||||
ruleModel.setErrorScript(RULE_ERROR_SCRIPT_DEFAULT);
|
||||
|
||||
return ruleModel;
|
||||
@@ -102,16 +109,6 @@ public class RulesTestsUtils
|
||||
return restActionModel;
|
||||
}
|
||||
|
||||
public static List<RestActionBodyExecTemplateModel> addActionContextParams(List<RestActionBodyExecTemplateModel> inputActions)
|
||||
{
|
||||
inputActions.forEach(inputAction -> {
|
||||
final Map<String, Serializable> params = new HashMap<>((Map<String, Serializable>) inputAction.getParams());
|
||||
params.put("actionContext", "rule");
|
||||
inputAction.setParams(params);
|
||||
});
|
||||
return inputActions;
|
||||
}
|
||||
|
||||
public static RestActionBodyExecTemplateModel createCustomActionModel(String actionDefinitionId, Map<String, Serializable> params)
|
||||
{
|
||||
RestActionBodyExecTemplateModel restActionModel = new RestActionBodyExecTemplateModel();
|
||||
@@ -123,8 +120,59 @@ public class RulesTestsUtils
|
||||
public static RestCompositeConditionDefinitionModel createEmptyConditionModel()
|
||||
{
|
||||
RestCompositeConditionDefinitionModel conditions = new RestCompositeConditionDefinitionModel();
|
||||
conditions.setInverted(false);
|
||||
conditions.setBooleanMode("and");
|
||||
conditions.setInverted(!INVERTED);
|
||||
conditions.setBooleanMode(AND);
|
||||
return conditions;
|
||||
}
|
||||
|
||||
public static RestCompositeConditionDefinitionModel createVariousConditions()
|
||||
{
|
||||
return createCompositeCondition(List.of(
|
||||
createCompositeCondition(!INVERTED, List.of(
|
||||
createSimpleCondition("cm:created", "less_than", "2022-09-01T12:59:00.000+02:00"),
|
||||
createSimpleCondition("cm:creator", "ends", "ski"),
|
||||
createSimpleCondition("size", "greater_than", "90000000"),
|
||||
createSimpleCondition("mimetype", "equals", "video/3gpp"),
|
||||
createSimpleCondition("encoding", "equals", "utf-8"),
|
||||
createSimpleCondition("type", "equals", "cm:folder"),
|
||||
createSimpleCondition("tag", "equals", "uat")
|
||||
)),
|
||||
createCompositeCondition(INVERTED, List.of(
|
||||
createSimpleCondition("aspect", "equals", "audio:audio"),
|
||||
createSimpleCondition("cm:modelVersion", "begins", "1.")
|
||||
))
|
||||
));
|
||||
}
|
||||
|
||||
public static RestSimpleConditionDefinitionModel createSimpleCondition(String field, String comparator, String parameter)
|
||||
{
|
||||
RestSimpleConditionDefinitionModel simpleCondition = new RestSimpleConditionDefinitionModel();
|
||||
simpleCondition.setField(field);
|
||||
simpleCondition.setComparator(comparator);
|
||||
simpleCondition.setParameter(parameter);
|
||||
return simpleCondition;
|
||||
}
|
||||
|
||||
public static RestCompositeConditionDefinitionModel createCompositeCondition(List<RestCompositeConditionDefinitionModel> compositeConditions)
|
||||
{
|
||||
return createCompositeCondition(AND, !INVERTED, compositeConditions, null);
|
||||
}
|
||||
|
||||
public static RestCompositeConditionDefinitionModel createCompositeCondition(boolean inverted,
|
||||
List<RestSimpleConditionDefinitionModel> simpleConditions)
|
||||
{
|
||||
return createCompositeCondition(AND, inverted, null, simpleConditions);
|
||||
}
|
||||
|
||||
private static RestCompositeConditionDefinitionModel createCompositeCondition(String booleanMode, boolean inverted,
|
||||
List<RestCompositeConditionDefinitionModel> compositeConditions, List<RestSimpleConditionDefinitionModel> simpleConditions)
|
||||
{
|
||||
RestCompositeConditionDefinitionModel compositeCondition = new RestCompositeConditionDefinitionModel();
|
||||
compositeCondition.setBooleanMode(booleanMode);
|
||||
compositeCondition.setInverted(inverted);
|
||||
compositeCondition.setCompositeConditions(compositeConditions);
|
||||
compositeCondition.setSimpleConditions(simpleConditions);
|
||||
|
||||
return compositeCondition;
|
||||
}
|
||||
}
|
||||
|
@@ -25,8 +25,15 @@
|
||||
*/
|
||||
package org.alfresco.rest.rules;
|
||||
|
||||
import static org.alfresco.rest.rules.RulesTestsUtils.ID;
|
||||
import static org.alfresco.rest.rules.RulesTestsUtils.INBOUND;
|
||||
import static org.alfresco.rest.rules.RulesTestsUtils.IS_SHARED;
|
||||
import static org.alfresco.rest.rules.RulesTestsUtils.RULE_ASYNC_DEFAULT;
|
||||
import static org.alfresco.rest.rules.RulesTestsUtils.RULE_CASCADE_DEFAULT;
|
||||
import static org.alfresco.rest.rules.RulesTestsUtils.RULE_ENABLED_DEFAULT;
|
||||
import static org.alfresco.rest.rules.RulesTestsUtils.createDefaultActionModel;
|
||||
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModel;
|
||||
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModelWithModifiedValues;
|
||||
import static org.alfresco.utility.constants.UserRole.SiteCollaborator;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||
@@ -35,7 +42,9 @@ import static org.springframework.http.HttpStatus.NOT_FOUND;
|
||||
import static org.springframework.http.HttpStatus.OK;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.alfresco.rest.RestTest;
|
||||
import org.alfresco.rest.model.RestActionBodyExecTemplateModel;
|
||||
import org.alfresco.rest.model.RestRuleModel;
|
||||
@@ -80,9 +89,9 @@ public class UpdateRulesTests extends RestTest
|
||||
.updateRule(rule.getId(), updatedRuleModel);
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
updatedRule.assertThat().field("id").is(rule.getId())
|
||||
updatedRule.assertThat().field(ID).is(rule.getId())
|
||||
.assertThat().field("name").is("Updated rule name")
|
||||
.assertThat().field("isShared").isNull();
|
||||
.assertThat().field(IS_SHARED).isNull();
|
||||
}
|
||||
|
||||
/** Check we get a 404 if trying to update a rule in a folder that doesn't exist. */
|
||||
@@ -180,7 +189,7 @@ public class UpdateRulesTests extends RestTest
|
||||
RestRuleModel updatedRule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.updateRule(rule.getId(), updatedRuleModel);
|
||||
|
||||
updatedRule.assertThat().field("id").is(rule.getId());
|
||||
updatedRule.assertThat().field(ID).is(rule.getId());
|
||||
}
|
||||
|
||||
/** Check we can update a rule and get the included fields. */
|
||||
@@ -192,10 +201,98 @@ public class UpdateRulesTests extends RestTest
|
||||
STEP("Try to update the rule.");
|
||||
RestRuleModel updatedRuleModel = createRuleModel("Updated rule name");
|
||||
RestRuleModel updatedRule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.include("isShared")
|
||||
.include(IS_SHARED)
|
||||
.updateRule(rule.getId(), updatedRuleModel);
|
||||
|
||||
updatedRule.assertThat().field("isShared").isNotNull();
|
||||
updatedRule.assertThat().field(IS_SHARED).isNotNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check we get error when attempt to update a rule to one without any actions.
|
||||
*/
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void updateRuleWithoutActionsShouldFail()
|
||||
{
|
||||
RestRuleModel rule = createAndSaveRule("Rule name");
|
||||
|
||||
STEP("Try to update the rule - set no actions.");
|
||||
rule.setActions(null);
|
||||
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.include(IS_SHARED)
|
||||
.updateRule(rule.getId(), rule);
|
||||
|
||||
restClient.assertStatusCodeIs(BAD_REQUEST);
|
||||
restClient.assertLastError().containsSummary("A rule must have at least one action");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check we get error when attempt to update a rule to one with invalid action.
|
||||
*/
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void updateRuleWithInvalidActionsShouldFail()
|
||||
{
|
||||
RestRuleModel rule = createAndSaveRule("Rule name");
|
||||
|
||||
STEP("Try to update the rule - set no actions.");
|
||||
final RestActionBodyExecTemplateModel invalidAction = new RestActionBodyExecTemplateModel();
|
||||
final String actionDefinitionId = "invalid-definition-value";
|
||||
invalidAction.setActionDefinitionId(actionDefinitionId);
|
||||
invalidAction.setParams(Map.of("dummy-key", "dummy-value"));
|
||||
rule.setActions(List.of(invalidAction));
|
||||
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.include(IS_SHARED)
|
||||
.updateRule(rule.getId(), rule);
|
||||
|
||||
restClient.assertStatusCodeIs(NOT_FOUND);
|
||||
restClient.assertLastError().containsSummary(actionDefinitionId);
|
||||
}
|
||||
|
||||
/** Check we can use the POST response to create the new rule. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
|
||||
public void updateCopyRuleWithResponseFromPOST()
|
||||
{
|
||||
FolderModel destination = dataContent.usingUser(user).usingSite(site).createFolder();
|
||||
|
||||
RestActionBodyExecTemplateModel copyAction = new RestActionBodyExecTemplateModel();
|
||||
copyAction.setActionDefinitionId("copy");
|
||||
copyAction.setParams(ImmutableMap.of("destination-folder", destination.getNodeRef()));
|
||||
RestRuleModel rule = createAndSaveRule("Rule name", List.of(copyAction));
|
||||
|
||||
STEP("Try to update the rule.");
|
||||
rule.setName("Updated rule name");
|
||||
RestRuleModel updatedRule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.include(IS_SHARED)
|
||||
.updateRule(rule.getId(), rule);
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
updatedRule.assertThat().field("name").is("Updated rule name")
|
||||
.assertThat().field("actions.actionDefinitionId").is(List.of("copy"))
|
||||
.assertThat().field("actions.params").is(List.of(ImmutableMap.of("destination-folder", destination.getNodeRef())));
|
||||
}
|
||||
|
||||
/** Check we can use the POST response and update rule fields. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
|
||||
public void updateRuleFields()
|
||||
{
|
||||
final RestRuleModel rule = createAndSaveRule(createRuleModelWithModifiedValues());
|
||||
|
||||
STEP("Try to update the rule fields.");
|
||||
rule.setName("Updated rule name");
|
||||
rule.setTriggers(List.of(INBOUND));
|
||||
final String updatedDescription = "Updated description";
|
||||
rule.setDescription(updatedDescription);
|
||||
rule.setEnabled(!RULE_ENABLED_DEFAULT);
|
||||
rule.setCascade(!RULE_CASCADE_DEFAULT);
|
||||
rule.setAsynchronous(!RULE_ASYNC_DEFAULT);
|
||||
final String updatedErrorScript = "updated-error-script";
|
||||
rule.setErrorScript(updatedErrorScript);
|
||||
final RestRuleModel updatedRule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.include(IS_SHARED)
|
||||
.updateRule(rule.getId(), rule);
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
updatedRule.assertThat().isEqualTo(rule, ID, IS_SHARED)
|
||||
.assertThat().field(ID).isNotNull();
|
||||
}
|
||||
|
||||
private RestRuleModel createAndSaveRule(String name)
|
||||
@@ -217,4 +314,17 @@ public class UpdateRulesTests extends RestTest
|
||||
return restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.createSingleRule(ruleModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a rule for folder and store it.
|
||||
*
|
||||
* @param ruleModel RuleModel used as create request
|
||||
* @return The created rule.
|
||||
*/
|
||||
private RestRuleModel createAndSaveRule(final RestRuleModel ruleModel)
|
||||
{
|
||||
STEP("Create a rule: " + ruleModel);
|
||||
return restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.createSingleRule(ruleModel);
|
||||
}
|
||||
}
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>17.102-SNAPSHOT</version>
|
||||
<version>17.118</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>17.102-SNAPSHOT</version>
|
||||
<version>17.118</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
38
pom.xml
38
pom.xml
@@ -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>17.102-SNAPSHOT</version>
|
||||
<version>17.118</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>Alfresco Community Repo Parent</name>
|
||||
|
||||
@@ -51,8 +51,8 @@
|
||||
<dependency.alfresco-log-sanitizer.version>0.2</dependency.alfresco-log-sanitizer.version>
|
||||
<dependency.activiti-engine.version>5.23.0</dependency.activiti-engine.version>
|
||||
<dependency.activiti.version>5.23.0</dependency.activiti.version>
|
||||
<dependency.alfresco-transform-service.version>1.5.4-A3</dependency.alfresco-transform-service.version>
|
||||
<dependency.alfresco-transform-core.version>2.7.0-A1</dependency.alfresco-transform-core.version>
|
||||
<dependency.alfresco-transform-service.version>2.0.0-A2</dependency.alfresco-transform-service.version>
|
||||
<dependency.alfresco-transform-core.version>3.0.0-A2</dependency.alfresco-transform-core.version>
|
||||
<dependency.alfresco-greenmail.version>6.4</dependency.alfresco-greenmail.version>
|
||||
<dependency.acs-event-model.version>0.0.16</dependency.acs-event-model.version>
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
<dependency.jackson-databind.version>2.13.3</dependency.jackson-databind.version>
|
||||
<dependency.cxf.version>3.5.3</dependency.cxf.version>
|
||||
<dependency.opencmis.version>1.0.0</dependency.opencmis.version>
|
||||
<dependency.webscripts.version>8.31</dependency.webscripts.version>
|
||||
<dependency.webscripts.version>8.32</dependency.webscripts.version>
|
||||
<dependency.bouncycastle.version>1.70</dependency.bouncycastle.version>
|
||||
<dependency.mockito-core.version>4.6.1</dependency.mockito-core.version>
|
||||
<dependency.assertj.version>3.23.1</dependency.assertj.version>
|
||||
@@ -75,7 +75,7 @@
|
||||
<dependency.commons-httpclient.version>3.1-HTTPCLIENT-1265</dependency.commons-httpclient.version>
|
||||
<dependency.xercesImpl.version>2.12.2</dependency.xercesImpl.version>
|
||||
<dependency.slf4j.version>1.7.36</dependency.slf4j.version>
|
||||
<dependency.gytheio.version>0.16</dependency.gytheio.version>
|
||||
<dependency.gytheio.version>0.17</dependency.gytheio.version>
|
||||
<dependency.groovy.version>3.0.12</dependency.groovy.version>
|
||||
<dependency.tika.version>2.4.1</dependency.tika.version>
|
||||
<dependency.spring-security.version>5.7.2</dependency.spring-security.version>
|
||||
@@ -84,7 +84,10 @@
|
||||
<dependency.ooxml-schemas.version>1.4</dependency.ooxml-schemas.version>
|
||||
<dependency.keycloak.version>18.0.0</dependency.keycloak.version>
|
||||
<dependency.jboss.logging.version>3.5.0.Final</dependency.jboss.logging.version>
|
||||
<dependency.camel.version>3.15.0</dependency.camel.version> <!-- when bumping this version, please keep track/sync with included netty.io dependencies (can cause dependency conflicts)-->
|
||||
<dependency.camel.version>3.18.2</dependency.camel.version> <!-- when bumping this version, please keep track/sync with included netty.io dependencies -->
|
||||
<dependency.netty.version>4.1.79.Final</dependency.netty.version> <!-- must be in sync with camels transitive dependencies, e.g.: netty-common -->
|
||||
<dependency.netty.qpid.version>4.1.72.Final</dependency.netty.qpid.version> <!-- must be in sync with camels transitive dependencies: native-unix-common/native-epoll/native-kqueue -->
|
||||
<dependency.netty-tcnative.version>2.0.53.Final</dependency.netty-tcnative.version> <!-- must be in sync with camels transitive dependencies -->
|
||||
<dependency.activemq.version>5.17.1</dependency.activemq.version>
|
||||
<dependency.apache-compress.version>1.21</dependency.apache-compress.version>
|
||||
<dependency.apache.taglibs.version>1.2.5</dependency.apache.taglibs.version>
|
||||
@@ -107,7 +110,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.2.2</alfresco.googledrive.version>
|
||||
<alfresco.googledrive.version>3.2.3-A2</alfresco.googledrive.version>
|
||||
<alfresco.aos-module.version>1.4.1</alfresco.aos-module.version>
|
||||
<alfresco.api-explorer.version>7.2.1</alfresco.api-explorer.version> <!-- Also in alfresco-enterprise-share -->
|
||||
|
||||
@@ -120,7 +123,7 @@
|
||||
<dependency.mariadb.version>2.7.4</dependency.mariadb.version>
|
||||
<dependency.tas-utility.version>3.0.49</dependency.tas-utility.version>
|
||||
<dependency.rest-assured.version>5.1.1</dependency.rest-assured.version>
|
||||
<dependency.tas-restapi.version>1.115</dependency.tas-restapi.version>
|
||||
<dependency.tas-restapi.version>1.117</dependency.tas-restapi.version>
|
||||
<dependency.tas-cmis.version>1.32</dependency.tas-cmis.version>
|
||||
<dependency.tas-email.version>1.9</dependency.tas-email.version>
|
||||
<dependency.tas-webdav.version>1.7</dependency.tas-webdav.version>
|
||||
@@ -148,7 +151,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>HEAD</tag>
|
||||
<tag>17.118</tag>
|
||||
</scm>
|
||||
|
||||
<distributionManagement>
|
||||
@@ -513,6 +516,11 @@
|
||||
<artifactId>jackson-dataformat-yaml</artifactId>
|
||||
<version>${dependency.jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>1.32</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
@@ -851,6 +859,18 @@
|
||||
<artifactId>camel-mock</artifactId>
|
||||
<version>${dependency.camel.version}</version>
|
||||
</dependency>
|
||||
<!-- Netty non-transitive dependencies declared for depending projects usage in conjunction with Camel's other transitive netty dependencies -->
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-handler-proxy</artifactId>
|
||||
<version>${dependency.netty.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-tcnative-classes</artifactId>
|
||||
<version>${dependency.netty-tcnative.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.taglibs</groupId>
|
||||
<artifactId>taglibs-standard-spec</artifactId>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>17.102-SNAPSHOT</version>
|
||||
<version>17.118</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* 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
|
||||
@@ -36,7 +36,7 @@ import org.alfresco.repo.content.metadata.MetadataExtracter;
|
||||
import org.alfresco.repo.content.metadata.MetadataExtracterRegistry;
|
||||
import org.alfresco.repo.content.transform.LocalTransformServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
import org.alfresco.transform.client.registry.TransformServiceRegistry;
|
||||
import org.alfresco.transform.registry.TransformServiceRegistry;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.DeclarativeWebScript;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
|
@@ -48,6 +48,7 @@ import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
|
||||
@Experimental
|
||||
public class ActionParameterConverter
|
||||
@@ -67,9 +68,15 @@ public class ActionParameterConverter
|
||||
Map<String, Serializable> getConvertedParams(Map<String, Serializable> params, String name)
|
||||
{
|
||||
final Map<String, Serializable> parameters = new HashMap<>(params.size());
|
||||
final ParameterizedItemDefinition definition = actionService.getActionDefinition(name);
|
||||
if (definition == null)
|
||||
final ParameterizedItemDefinition definition;
|
||||
try
|
||||
{
|
||||
definition = actionService.getActionDefinition(name);
|
||||
if (definition == null)
|
||||
{
|
||||
throw new NotFoundException(NotFoundException.DEFAULT_MESSAGE_ID, new String[]{name});
|
||||
}
|
||||
} catch (NoSuchBeanDefinitionException e) {
|
||||
throw new NotFoundException(NotFoundException.DEFAULT_MESSAGE_ID, new String[]{name});
|
||||
}
|
||||
|
||||
|
@@ -180,6 +180,12 @@ public class NodeValidator
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies if rule set node or folder node's default rule set is shared
|
||||
* @param ruleSetNodeRef
|
||||
* @param folderNodeRef
|
||||
* @return
|
||||
*/
|
||||
public boolean isRuleSetNotNullAndShared(final NodeRef ruleSetNodeRef, final NodeRef folderNodeRef)
|
||||
{
|
||||
if (ruleSetNodeRef == null && folderNodeRef != null)
|
||||
|
@@ -31,6 +31,7 @@ import org.alfresco.rest.api.model.rules.Rule;
|
||||
import org.alfresco.service.Experimental;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.rule.RuleService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
|
||||
/** Responsible for creating {@link Rule} objects. */
|
||||
@Experimental
|
||||
@@ -39,10 +40,11 @@ public class RuleLoader
|
||||
public static final String IS_SHARED = "isShared";
|
||||
private RuleService ruleService;
|
||||
private NodeValidator nodeValidator;
|
||||
private NamespaceService namespaceService;
|
||||
|
||||
public Rule loadRule(org.alfresco.service.cmr.rule.Rule ruleModel, List<String> includes)
|
||||
{
|
||||
Rule rule = Rule.from(ruleModel);
|
||||
Rule rule = Rule.from(ruleModel, namespaceService);
|
||||
if (includes != null && includes.contains(IS_SHARED))
|
||||
{
|
||||
NodeRef ruleSet = ruleService.getRuleSetNode(ruleModel.getNodeRef());
|
||||
@@ -61,4 +63,9 @@ public class RuleLoader
|
||||
{
|
||||
this.nodeValidator = nodeValidator;
|
||||
}
|
||||
|
||||
public void setNamespaceService(NamespaceService namespaceService)
|
||||
{
|
||||
this.namespaceService = namespaceService;
|
||||
}
|
||||
}
|
||||
|
@@ -36,6 +36,7 @@ import org.alfresco.service.Experimental;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.rule.RuleService;
|
||||
|
||||
/** Responsible for converting a NodeRef into a {@link RuleSet} object. */
|
||||
@Experimental
|
||||
@@ -43,7 +44,10 @@ public class RuleSetLoader
|
||||
{
|
||||
protected static final String OWNING_FOLDER = "owningFolder";
|
||||
protected static final String INCLUSION_TYPE = "inclusionType";
|
||||
protected static final String INHERITED_BY = "inheritedBy";
|
||||
public static final int MAX_INHERITED_BY_SIZE = 100;
|
||||
private NodeService nodeService;
|
||||
private RuleService ruleService;
|
||||
|
||||
/**
|
||||
* Load a rule set for the given node ref.
|
||||
@@ -79,12 +83,26 @@ public class RuleSetLoader
|
||||
ruleSet.setInclusionType(linked ? LINKED : INHERITED);
|
||||
}
|
||||
}
|
||||
if (includes.contains(INHERITED_BY))
|
||||
{
|
||||
ruleSet.setInheritedBy(loadInheritedBy(ruleSetNodeRef));
|
||||
}
|
||||
}
|
||||
return ruleSet;
|
||||
}
|
||||
|
||||
private List<NodeRef> loadInheritedBy(NodeRef ruleSetNodeRef)
|
||||
{
|
||||
return ruleService.getFoldersInheritingRuleSet(ruleSetNodeRef, MAX_INHERITED_BY_SIZE);
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setRuleService(RuleService ruleService)
|
||||
{
|
||||
this.ruleService = ruleService;
|
||||
}
|
||||
}
|
||||
|
@@ -29,7 +29,7 @@ package org.alfresco.rest.api.impl.rules;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.alfresco.repo.rule.RuleModel;
|
||||
import org.alfresco.repo.rule.RuntimeRuleService;
|
||||
@@ -59,10 +59,13 @@ public class RuleSetsImpl implements RuleSets
|
||||
{
|
||||
NodeRef folderNode = validator.validateFolderNode(folderNodeId, false);
|
||||
|
||||
NodeRef ruleSetNode = ruleService.getRuleSetNode(folderNode);
|
||||
List<RuleSet> ruleSets = Optional.ofNullable(ruleSetNode)
|
||||
.map(nodeRef -> ruleSetLoader.loadRuleSet(nodeRef, folderNode, includes))
|
||||
.stream().collect(toList());
|
||||
List<RuleSet> ruleSets = ruleService.getNodesSupplyingRuleSets(folderNode)
|
||||
.stream()
|
||||
.map(ruleService::getRuleSetNode)
|
||||
.filter(Objects::nonNull)
|
||||
.map(nodeRef -> ruleSetLoader.loadRuleSet(nodeRef, folderNode, includes))
|
||||
.distinct()
|
||||
.collect(toList());
|
||||
|
||||
return ListPage.of(ruleSets, paging);
|
||||
}
|
||||
@@ -93,7 +96,7 @@ public class RuleSetsImpl implements RuleSets
|
||||
|
||||
//The folder shouldn't have any pre-existing rules
|
||||
if (ruleService.hasRules(folderNodeRef)) {
|
||||
throw new InvalidArgumentException("Unable to link to a ruleset because the folder has pre-existing rules or is already linked to a ruleset.");
|
||||
throw new InvalidArgumentException("Unable to link to a rule set because the folder has pre-existing rules or is already linked to a rule set.");
|
||||
}
|
||||
|
||||
// Create the destination folder as a secondary child of the first
|
||||
|
@@ -34,6 +34,7 @@ import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.Rules;
|
||||
import org.alfresco.rest.api.model.rules.Rule;
|
||||
import org.alfresco.rest.api.model.rules.RuleSet;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.ListPage;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
@@ -41,6 +42,8 @@ import org.alfresco.service.Experimental;
|
||||
import org.alfresco.service.cmr.action.CompositeAction;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.rule.RuleService;
|
||||
import org.alfresco.util.collections.CollectionUtils;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -48,6 +51,7 @@ import org.slf4j.LoggerFactory;
|
||||
public class RulesImpl implements Rules
|
||||
{
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(RulesImpl.class);
|
||||
private static final String MUST_HAVE_AT_LEAST_ONE_ACTION = "A rule must have at least one action";
|
||||
|
||||
private Nodes nodes;
|
||||
private RuleService ruleService;
|
||||
@@ -55,6 +59,7 @@ public class RulesImpl implements Rules
|
||||
private RuleLoader ruleLoader;
|
||||
private ActionParameterConverter actionParameterConverter;
|
||||
private ActionPermissionValidator actionPermissionValidator;
|
||||
private NamespaceService namespaceService;
|
||||
|
||||
@Override
|
||||
public CollectionWithPagingInfo<Rule> getRules(final String folderNodeId,
|
||||
@@ -63,9 +68,10 @@ public class RulesImpl implements Rules
|
||||
final Paging paging)
|
||||
{
|
||||
final NodeRef folderNodeRef = validator.validateFolderNode(folderNodeId, false);
|
||||
validator.validateRuleSetNode(ruleSetId, folderNodeRef);
|
||||
NodeRef ruleSetNode = validator.validateRuleSetNode(ruleSetId, folderNodeRef);
|
||||
NodeRef owningFolder = ruleService.getOwningNodeRef(ruleSetNode);
|
||||
|
||||
final List<Rule> rules = ruleService.getRules(folderNodeRef).stream()
|
||||
final List<Rule> rules = ruleService.getRules(owningFolder, false).stream()
|
||||
.map(ruleModel -> loadRuleAndConvertActionParams(ruleModel, includes))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
@@ -123,7 +129,11 @@ public class RulesImpl implements Rules
|
||||
|
||||
private org.alfresco.service.cmr.rule.Rule mapToServiceModelAndValidateActions(Rule rule)
|
||||
{
|
||||
final org.alfresco.service.cmr.rule.Rule serviceModelRule = rule.toServiceModel(nodes);
|
||||
if (CollectionUtils.isEmpty(rule.getActions()))
|
||||
{
|
||||
throw new InvalidArgumentException(MUST_HAVE_AT_LEAST_ONE_ACTION);
|
||||
}
|
||||
final org.alfresco.service.cmr.rule.Rule serviceModelRule = rule.toServiceModel(nodes, namespaceService);
|
||||
final CompositeAction compositeAction = (CompositeAction) serviceModelRule.getAction();
|
||||
compositeAction.getActions().forEach(action -> action.setParameterValues(
|
||||
actionParameterConverter.getConvertedParams(action.getParameterValues(), action.getActionDefinitionName())));
|
||||
@@ -133,7 +143,6 @@ public class RulesImpl implements Rules
|
||||
|
||||
private Rule loadRuleAndConvertActionParams(org.alfresco.service.cmr.rule.Rule ruleModel, List<String> includes)
|
||||
{
|
||||
|
||||
final Rule rule = ruleLoader.loadRule(ruleModel, includes);
|
||||
rule.getActions()
|
||||
.forEach(a -> a.setParams(a.getParams().entrySet()
|
||||
@@ -174,4 +183,9 @@ public class RulesImpl implements Rules
|
||||
{
|
||||
this.actionPermissionValidator = actionPermissionValidator;
|
||||
}
|
||||
|
||||
public void setNamespaceService(NamespaceService namespaceService)
|
||||
{
|
||||
this.namespaceService = namespaceService;
|
||||
}
|
||||
}
|
||||
|
@@ -26,6 +26,8 @@
|
||||
|
||||
package org.alfresco.rest.api.model.rules;
|
||||
|
||||
import static org.alfresco.repo.action.access.ActionAccessRestriction.ACTION_CONTEXT_PARAM_NAME;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -60,7 +62,9 @@ public class Action
|
||||
final Action.Builder builder = builder().actionDefinitionId(actionModel.getActionDefinitionName());
|
||||
if (actionModel.getParameterValues() != null)
|
||||
{
|
||||
builder.params(new HashMap<>(actionModel.getParameterValues()));
|
||||
Map<String, Serializable> params = new HashMap<>(actionModel.getParameterValues());
|
||||
params.remove(ACTION_CONTEXT_PARAM_NAME);
|
||||
builder.params(params);
|
||||
}
|
||||
|
||||
return builder.create();
|
||||
|
@@ -32,8 +32,10 @@ import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.service.Experimental;
|
||||
import org.alfresco.service.cmr.action.ActionCondition;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
|
||||
@Experimental
|
||||
@@ -50,7 +52,7 @@ public class CompositeCondition
|
||||
* @param actionConditions - list of {@link ActionCondition} service POJOs
|
||||
* @return {@link CompositeCondition} REST model
|
||||
*/
|
||||
public static CompositeCondition from(final List<ActionCondition> actionConditions)
|
||||
public static CompositeCondition from(final List<ActionCondition> actionConditions, final NamespaceService namespaceService)
|
||||
{
|
||||
if (actionConditions == null)
|
||||
{
|
||||
@@ -62,7 +64,7 @@ public class CompositeCondition
|
||||
// group action conditions by inversion flag
|
||||
actionConditions.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(ActionCondition::getInvertCondition))
|
||||
// map action condition sub lists
|
||||
.forEach((inverted, actionConditionsPart) -> Optional.ofNullable(CompositeCondition.ofActionConditions(actionConditionsPart, inverted, ConditionOperator.AND))
|
||||
.forEach((inverted, actionConditionsPart) -> Optional.ofNullable(CompositeCondition.ofActionConditions(actionConditionsPart, namespaceService, inverted, ConditionOperator.AND))
|
||||
// if composite condition present add to final list
|
||||
.ifPresent(compositeCondition -> conditions.compositeConditions.add(compositeCondition)));
|
||||
|
||||
@@ -73,14 +75,14 @@ public class CompositeCondition
|
||||
return conditions;
|
||||
}
|
||||
|
||||
private static CompositeCondition ofActionConditions(final List<ActionCondition> actionConditions, final boolean inverted, final ConditionOperator conditionOperator)
|
||||
private static CompositeCondition ofActionConditions(final List<ActionCondition> actionConditions, final NamespaceService namespaceService, final boolean inverted, final ConditionOperator conditionOperator)
|
||||
{
|
||||
if (actionConditions == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return ofSimpleConditions(SimpleCondition.listOf(actionConditions), inverted, conditionOperator);
|
||||
return ofSimpleConditions(SimpleCondition.listOf(actionConditions, namespaceService), inverted, conditionOperator);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,6 +114,21 @@ public class CompositeCondition
|
||||
.create();
|
||||
}
|
||||
|
||||
public List<ActionCondition> toServiceModels(final Nodes nodes, final NamespaceService namespaceService)
|
||||
{
|
||||
final List<ActionCondition> actionConditions = new ArrayList<>();
|
||||
if (CollectionUtils.isNotEmpty(simpleConditions))
|
||||
{
|
||||
simpleConditions.forEach(simpleCondition -> actionConditions.add(simpleCondition.toServiceModel(inverted, nodes, namespaceService)));
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(compositeConditions))
|
||||
{
|
||||
compositeConditions.forEach(compositeCondition -> actionConditions.addAll(compositeCondition.toServiceModels(nodes, namespaceService)));
|
||||
}
|
||||
|
||||
return actionConditions;
|
||||
}
|
||||
|
||||
public boolean isInverted()
|
||||
{
|
||||
return inverted;
|
||||
@@ -131,6 +148,14 @@ public class CompositeCondition
|
||||
return booleanMode.name().toLowerCase();
|
||||
}
|
||||
|
||||
public void setBooleanMode(String booleanMode)
|
||||
{
|
||||
if (booleanMode != null)
|
||||
{
|
||||
this.booleanMode = ConditionOperator.valueOf(booleanMode.toUpperCase());
|
||||
}
|
||||
}
|
||||
|
||||
public void setBooleanMode(ConditionOperator booleanMode)
|
||||
{
|
||||
this.booleanMode = booleanMode;
|
||||
|
@@ -37,6 +37,7 @@ import org.alfresco.rest.framework.resource.UniqueId;
|
||||
import org.alfresco.service.Experimental;
|
||||
import org.alfresco.service.cmr.action.CompositeAction;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.util.GUID;
|
||||
|
||||
@Experimental
|
||||
@@ -60,7 +61,7 @@ public class Rule
|
||||
* @param ruleModel - {@link org.alfresco.service.cmr.rule.Rule} service POJO
|
||||
* @return {@link Rule} REST model
|
||||
*/
|
||||
public static Rule from(final org.alfresco.service.cmr.rule.Rule ruleModel)
|
||||
public static Rule from(final org.alfresco.service.cmr.rule.Rule ruleModel, final NamespaceService namespaceService)
|
||||
{
|
||||
if (ruleModel == null)
|
||||
{
|
||||
@@ -83,7 +84,7 @@ public class Rule
|
||||
}
|
||||
if (ruleModel.getAction() != null)
|
||||
{
|
||||
builder.conditions(CompositeCondition.from(ruleModel.getAction().getActionConditions()));
|
||||
builder.conditions(CompositeCondition.from(ruleModel.getAction().getActionConditions(), namespaceService));
|
||||
if (ruleModel.getAction().getCompensatingAction() != null && ruleModel.getAction().getCompensatingAction().getParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF) != null)
|
||||
{
|
||||
builder.errorScript(ruleModel.getAction().getCompensatingAction().getParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF).toString());
|
||||
@@ -103,7 +104,7 @@ public class Rule
|
||||
* @param nodes The nodes API.
|
||||
* @return The rule service POJO.
|
||||
*/
|
||||
public org.alfresco.service.cmr.rule.Rule toServiceModel(Nodes nodes)
|
||||
public org.alfresco.service.cmr.rule.Rule toServiceModel(final Nodes nodes, final NamespaceService namespaceService)
|
||||
{
|
||||
final org.alfresco.service.cmr.rule.Rule ruleModel = new org.alfresco.service.cmr.rule.Rule();
|
||||
final NodeRef nodeRef = (id != null) ? nodes.validateOrLookupNode(id, null) : null;
|
||||
@@ -124,6 +125,10 @@ public class Rule
|
||||
compensatingAction.setParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF, errorScript);
|
||||
ruleModel.getAction().setCompensatingAction(compensatingAction);
|
||||
}
|
||||
if (conditions != null)
|
||||
{
|
||||
conditions.toServiceModels(nodes, namespaceService).forEach(condition -> ruleModel.getAction().addActionCondition(condition));
|
||||
}
|
||||
|
||||
return ruleModel;
|
||||
}
|
||||
|
@@ -26,6 +26,7 @@
|
||||
|
||||
package org.alfresco.rest.api.model.rules;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
@@ -40,6 +41,7 @@ public class RuleSet
|
||||
private String id;
|
||||
private NodeRef owningFolder;
|
||||
private InclusionType inclusionType;
|
||||
private List<NodeRef> inheritedBy;
|
||||
|
||||
public static RuleSet of(String id)
|
||||
{
|
||||
@@ -86,6 +88,16 @@ public class RuleSet
|
||||
this.inclusionType = inclusionType;
|
||||
}
|
||||
|
||||
public List<NodeRef> getInheritedBy()
|
||||
{
|
||||
return inheritedBy;
|
||||
}
|
||||
|
||||
public void setInheritedBy(List<NodeRef> inheritedBy)
|
||||
{
|
||||
this.inheritedBy = inheritedBy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
@@ -94,6 +106,7 @@ public class RuleSet
|
||||
.add("id='" + id + "'")
|
||||
.add("owningFolder='" + owningFolder + "'")
|
||||
.add("inclusionType='" + inclusionType + "'")
|
||||
.add("inheritedBy='" + inheritedBy + "'")
|
||||
.toString()
|
||||
+ '}';
|
||||
}
|
||||
@@ -108,13 +121,14 @@ public class RuleSet
|
||||
RuleSet ruleSet = (RuleSet) o;
|
||||
return Objects.equals(id, ruleSet.id)
|
||||
&& Objects.equals(owningFolder, ruleSet.owningFolder)
|
||||
&& inclusionType == ruleSet.inclusionType;
|
||||
&& inclusionType == ruleSet.inclusionType
|
||||
&& Objects.equals(inheritedBy, ruleSet.inheritedBy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(id, owningFolder, inclusionType);
|
||||
return Objects.hash(id, owningFolder, inclusionType, inheritedBy);
|
||||
}
|
||||
|
||||
public static Builder builder()
|
||||
@@ -127,6 +141,7 @@ public class RuleSet
|
||||
private String id;
|
||||
private NodeRef owningFolder;
|
||||
private InclusionType inclusionType;
|
||||
private List<NodeRef> inheritedBy;
|
||||
|
||||
public Builder id(String id)
|
||||
{
|
||||
@@ -146,12 +161,19 @@ public class RuleSet
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder inheritedBy(List<NodeRef> inheritedBy)
|
||||
{
|
||||
this.inheritedBy = inheritedBy;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RuleSet create()
|
||||
{
|
||||
final RuleSet ruleSet = new RuleSet();
|
||||
ruleSet.setId(id);
|
||||
ruleSet.setOwningFolder(owningFolder);
|
||||
ruleSet.setInclusionType(inclusionType);
|
||||
ruleSet.setInheritedBy(inheritedBy);
|
||||
return ruleSet;
|
||||
}
|
||||
}
|
||||
|
@@ -30,7 +30,7 @@ public class RuleSetLink
|
||||
{
|
||||
|
||||
/**
|
||||
* This id is referring to the node id of the linked-to-folder which contains the ruleset(s)
|
||||
* This id is referring to the node id of the linked-to-folder which contains the rule set(s)
|
||||
*/
|
||||
private String id;
|
||||
|
||||
|
@@ -26,27 +26,41 @@
|
||||
|
||||
package org.alfresco.rest.api.model.rules;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.action.ActionConditionImpl;
|
||||
import org.alfresco.repo.action.evaluator.CompareMimeTypeEvaluator;
|
||||
import org.alfresco.repo.action.evaluator.ComparePropertyValueEvaluator;
|
||||
import org.alfresco.repo.action.evaluator.HasAspectEvaluator;
|
||||
import org.alfresco.repo.action.evaluator.HasChildEvaluator;
|
||||
import org.alfresco.repo.action.evaluator.HasTagEvaluator;
|
||||
import org.alfresco.repo.action.evaluator.HasVersionHistoryEvaluator;
|
||||
import org.alfresco.repo.action.evaluator.InCategoryEvaluator;
|
||||
import org.alfresco.repo.action.evaluator.IsSubTypeEvaluator;
|
||||
import org.alfresco.repo.action.evaluator.NoConditionEvaluator;
|
||||
import org.alfresco.repo.action.evaluator.compare.ComparePropertyValueOperation;
|
||||
import org.alfresco.repo.action.evaluator.compare.ContentPropertyName;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.service.Experimental;
|
||||
import org.alfresco.service.cmr.action.ActionCondition;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
|
||||
@Experimental
|
||||
public class SimpleCondition
|
||||
{
|
||||
private static final String COMPARATOR_EQUALS = "equals";
|
||||
private static final String CATEGORY_INVALID_MSG = "Category in condition is invalid";
|
||||
public static final String PARAM_CATEGORY = "category";
|
||||
public static final String PARAM_MIMETYPE = "mimetype";
|
||||
|
||||
private String field;
|
||||
private String comparator;
|
||||
@@ -58,7 +72,7 @@ public class SimpleCondition
|
||||
* @param actionConditions - list of {@link ActionCondition} service POJOs
|
||||
* @return list of {@link SimpleCondition} REST models
|
||||
*/
|
||||
public static List<SimpleCondition> listOf(final List<ActionCondition> actionConditions)
|
||||
public static List<SimpleCondition> listOf(final List<ActionCondition> actionConditions, final NamespaceService namespaceService)
|
||||
{
|
||||
if (CollectionUtils.isEmpty(actionConditions))
|
||||
{
|
||||
@@ -66,7 +80,7 @@ public class SimpleCondition
|
||||
}
|
||||
|
||||
return actionConditions.stream()
|
||||
.map(SimpleCondition::from)
|
||||
.map(actionCondition -> from(actionCondition, namespaceService))
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
@@ -77,7 +91,7 @@ public class SimpleCondition
|
||||
* @param actionCondition - {@link ActionCondition} service POJO
|
||||
* @return {@link SimpleCondition} REST model
|
||||
*/
|
||||
public static SimpleCondition from(final ActionCondition actionCondition)
|
||||
public static SimpleCondition from(final ActionCondition actionCondition, final NamespaceService namespaceService)
|
||||
{
|
||||
if (actionCondition == null || actionCondition.getActionConditionDefinitionName() == null || actionCondition.getParameterValues() == null)
|
||||
{
|
||||
@@ -87,27 +101,86 @@ public class SimpleCondition
|
||||
switch (actionCondition.getActionConditionDefinitionName())
|
||||
{
|
||||
case ComparePropertyValueEvaluator.NAME:
|
||||
return createComparePropertyValueCondition(actionCondition);
|
||||
return createComparePropertyValueCondition(actionCondition, namespaceService);
|
||||
case CompareMimeTypeEvaluator.NAME:
|
||||
return createCompareMimeTypeCondition(actionCondition);
|
||||
case HasAspectEvaluator.NAME:
|
||||
return createHasAspectCondition(actionCondition);
|
||||
case HasChildEvaluator.NAME:
|
||||
return createHasChildCondition(actionCondition);
|
||||
return createHasAspectCondition(actionCondition, namespaceService);
|
||||
case HasTagEvaluator.NAME:
|
||||
return createHasTagCondition(actionCondition);
|
||||
case HasVersionHistoryEvaluator.NAME:
|
||||
return createHasVersionHistoryCondition(actionCondition);
|
||||
case InCategoryEvaluator.NAME:
|
||||
return createInCategoryCondition(actionCondition);
|
||||
case IsSubTypeEvaluator.NAME:
|
||||
return createIsSubtypeCondition(actionCondition);
|
||||
return createIsSubtypeCondition(actionCondition, namespaceService);
|
||||
case NoConditionEvaluator.NAME:
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public ActionCondition toServiceModel(final boolean inverted, final Nodes nodes, final NamespaceService namespaceService)
|
||||
{
|
||||
if (field == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Map<String, Serializable> parameterValues = new HashMap<>();
|
||||
String conditionDefinitionId;
|
||||
|
||||
switch (field)
|
||||
{
|
||||
case HasAspectEvaluator.PARAM_ASPECT:
|
||||
conditionDefinitionId = HasAspectEvaluator.NAME;
|
||||
parameterValues.put(HasAspectEvaluator.PARAM_ASPECT, QName.createQName(parameter, namespaceService));
|
||||
break;
|
||||
case HasTagEvaluator.PARAM_TAG:
|
||||
conditionDefinitionId = HasTagEvaluator.NAME;
|
||||
parameterValues.put(HasTagEvaluator.PARAM_TAG, parameter);
|
||||
break;
|
||||
case PARAM_CATEGORY:
|
||||
conditionDefinitionId = InCategoryEvaluator.NAME;
|
||||
parameterValues.put(InCategoryEvaluator.PARAM_CATEGORY_ASPECT, ContentModel.ASPECT_GEN_CLASSIFIABLE);
|
||||
try
|
||||
{
|
||||
parameterValues.put(InCategoryEvaluator.PARAM_CATEGORY_VALUE, nodes.validateOrLookupNode(parameter, null));
|
||||
} catch (EntityNotFoundException e) {
|
||||
throw new InvalidArgumentException(CATEGORY_INVALID_MSG);
|
||||
}
|
||||
break;
|
||||
case IsSubTypeEvaluator.PARAM_TYPE:
|
||||
conditionDefinitionId = IsSubTypeEvaluator.NAME;
|
||||
parameterValues.put(IsSubTypeEvaluator.PARAM_TYPE, QName.createQName(parameter, namespaceService));
|
||||
break;
|
||||
case PARAM_MIMETYPE:
|
||||
conditionDefinitionId = CompareMimeTypeEvaluator.NAME;
|
||||
parameterValues.put(ComparePropertyValueEvaluator.PARAM_PROPERTY, ContentModel.TYPE_CONTENT);
|
||||
parameterValues.put(ComparePropertyValueEvaluator.PARAM_VALUE, parameter);
|
||||
break;
|
||||
default:
|
||||
conditionDefinitionId = ComparePropertyValueEvaluator.NAME;
|
||||
try
|
||||
{
|
||||
// if size or encoding create content property evaluator
|
||||
ContentPropertyName.valueOf(field.toUpperCase());
|
||||
parameterValues.put(ComparePropertyValueEvaluator.PARAM_CONTENT_PROPERTY, field.toUpperCase());
|
||||
parameterValues.put(ComparePropertyValueEvaluator.PARAM_PROPERTY, ContentModel.TYPE_CONTENT);
|
||||
}
|
||||
catch (IllegalArgumentException ignore)
|
||||
{
|
||||
// else create common property evaluator
|
||||
parameterValues.put(ComparePropertyValueEvaluator.PARAM_PROPERTY, QName.createQName(field, namespaceService));
|
||||
}
|
||||
parameterValues.put(ComparePropertyValueEvaluator.PARAM_OPERATION, comparator.toUpperCase());
|
||||
parameterValues.put(ComparePropertyValueEvaluator.PARAM_VALUE, parameter);
|
||||
break;
|
||||
}
|
||||
|
||||
final ActionCondition actionCondition = new ActionConditionImpl(UUID.randomUUID().toString(), conditionDefinitionId, parameterValues);
|
||||
actionCondition.setInvertCondition(inverted);
|
||||
return actionCondition;
|
||||
}
|
||||
|
||||
public String getField()
|
||||
{
|
||||
return field;
|
||||
@@ -161,13 +234,14 @@ public class SimpleCondition
|
||||
return Objects.hash(field, comparator, parameter);
|
||||
}
|
||||
|
||||
private static SimpleCondition createComparePropertyValueCondition(final ActionCondition actionCondition) {
|
||||
private static SimpleCondition createComparePropertyValueCondition(final ActionCondition actionCondition, final NamespaceService namespaceService)
|
||||
{
|
||||
final SimpleCondition.Builder builder = builder();
|
||||
if (actionCondition.getParameterValues().get(ComparePropertyValueEvaluator.PARAM_CONTENT_PROPERTY) != null)
|
||||
{
|
||||
builder.field(actionCondition.getParameterValues().get(ComparePropertyValueEvaluator.PARAM_CONTENT_PROPERTY).toString().toLowerCase());
|
||||
} else {
|
||||
builder.field(actionCondition.getParameterValues().get(ComparePropertyValueEvaluator.PARAM_PROPERTY).toString().toLowerCase());
|
||||
builder.field(((QName) actionCondition.getParameterValues().get(ComparePropertyValueEvaluator.PARAM_PROPERTY)).toPrefixString(namespaceService));
|
||||
}
|
||||
return builder
|
||||
.comparator(actionCondition.getParameterValues().get(ComparePropertyValueEvaluator.PARAM_OPERATION).toString().toLowerCase())
|
||||
@@ -175,65 +249,48 @@ public class SimpleCondition
|
||||
.create();
|
||||
}
|
||||
|
||||
private static SimpleCondition createCompareMimeTypeCondition(final ActionCondition actionCondition) {
|
||||
private static SimpleCondition createCompareMimeTypeCondition(final ActionCondition actionCondition)
|
||||
{
|
||||
return builder()
|
||||
.field(actionCondition.getParameterValues().get(ComparePropertyValueEvaluator.PARAM_PROPERTY).toString().toLowerCase())
|
||||
.comparator(COMPARATOR_EQUALS)
|
||||
.field(PARAM_MIMETYPE)
|
||||
.comparator(ComparePropertyValueOperation.EQUALS.toString().toLowerCase())
|
||||
.parameter(actionCondition.getParameterValues().get(ComparePropertyValueEvaluator.PARAM_VALUE).toString())
|
||||
.create();
|
||||
}
|
||||
|
||||
private static SimpleCondition createHasAspectCondition(final ActionCondition actionCondition) {
|
||||
private static SimpleCondition createHasAspectCondition(final ActionCondition actionCondition, final NamespaceService namespaceService)
|
||||
{
|
||||
return builder()
|
||||
.field(HasAspectEvaluator.PARAM_ASPECT)
|
||||
.comparator(COMPARATOR_EQUALS)
|
||||
.parameter(actionCondition.getParameterValues().get(HasAspectEvaluator.PARAM_ASPECT).toString())
|
||||
.comparator(ComparePropertyValueOperation.EQUALS.toString().toLowerCase())
|
||||
.parameter(((QName) actionCondition.getParameterValues().get(HasAspectEvaluator.PARAM_ASPECT)).toPrefixString(namespaceService))
|
||||
.create();
|
||||
}
|
||||
|
||||
private static SimpleCondition createHasChildCondition(final ActionCondition actionCondition) {
|
||||
final SimpleCondition.Builder builder = builder();
|
||||
if (actionCondition.getParameterValues().get(HasChildEvaluator.PARAM_ASSOC_TYPE) != null)
|
||||
{
|
||||
builder.field(actionCondition.getParameterValues().get(HasChildEvaluator.PARAM_ASSOC_TYPE).toString().toLowerCase());
|
||||
} else {
|
||||
builder.field(actionCondition.getParameterValues().get(HasChildEvaluator.PARAM_ASSOC_NAME).toString().toLowerCase());
|
||||
}
|
||||
return builder
|
||||
.comparator(COMPARATOR_EQUALS)
|
||||
.parameter(actionCondition.getParameterValues().get(ComparePropertyValueEvaluator.PARAM_VALUE).toString())
|
||||
.create();
|
||||
}
|
||||
|
||||
private static SimpleCondition createHasTagCondition(final ActionCondition actionCondition) {
|
||||
private static SimpleCondition createHasTagCondition(final ActionCondition actionCondition)
|
||||
{
|
||||
return builder()
|
||||
.field(HasTagEvaluator.PARAM_TAG)
|
||||
.comparator(COMPARATOR_EQUALS)
|
||||
.comparator(ComparePropertyValueOperation.EQUALS.toString().toLowerCase())
|
||||
.parameter(actionCondition.getParameterValues().get(HasTagEvaluator.PARAM_TAG).toString())
|
||||
.create();
|
||||
}
|
||||
|
||||
private static SimpleCondition createHasVersionHistoryCondition(final ActionCondition actionCondition) {
|
||||
private static SimpleCondition createInCategoryCondition(final ActionCondition actionCondition)
|
||||
{
|
||||
return builder()
|
||||
.field(actionCondition.getParameterValues().get(ComparePropertyValueEvaluator.PARAM_PROPERTY).toString().toLowerCase())
|
||||
.comparator(actionCondition.getParameterValues().get(ComparePropertyValueEvaluator.PARAM_OPERATION).toString().toLowerCase())
|
||||
.parameter(actionCondition.getParameterValues().get(ComparePropertyValueEvaluator.PARAM_VALUE).toString())
|
||||
.field(PARAM_CATEGORY)
|
||||
.comparator(ComparePropertyValueOperation.EQUALS.toString().toLowerCase())
|
||||
.parameter(((NodeRef) actionCondition.getParameterValues().get(InCategoryEvaluator.PARAM_CATEGORY_VALUE)).getId())
|
||||
.create();
|
||||
}
|
||||
|
||||
private static SimpleCondition createInCategoryCondition(final ActionCondition actionCondition) {
|
||||
return builder()
|
||||
.field(actionCondition.getParameterValues().get(InCategoryEvaluator.PARAM_CATEGORY_ASPECT).toString().toLowerCase())
|
||||
.comparator(COMPARATOR_EQUALS)
|
||||
.parameter(actionCondition.getParameterValues().get(InCategoryEvaluator.PARAM_CATEGORY_VALUE).toString())
|
||||
.create();
|
||||
}
|
||||
|
||||
private static SimpleCondition createIsSubtypeCondition(final ActionCondition actionCondition) {
|
||||
private static SimpleCondition createIsSubtypeCondition(final ActionCondition actionCondition, final NamespaceService namespaceService)
|
||||
{
|
||||
return builder()
|
||||
.field(IsSubTypeEvaluator.PARAM_TYPE)
|
||||
.comparator(COMPARATOR_EQUALS)
|
||||
.parameter(actionCondition.getParameterValues().get(IsSubTypeEvaluator.PARAM_TYPE).toString())
|
||||
.comparator(ComparePropertyValueOperation.EQUALS.toString().toLowerCase())
|
||||
.parameter(((QName) actionCondition.getParameterValues().get(IsSubTypeEvaluator.PARAM_TYPE)).toPrefixString(namespaceService))
|
||||
.create();
|
||||
}
|
||||
|
||||
|
@@ -65,7 +65,7 @@ public class NodeRulesRelation implements RelationshipResourceAction.Read<Rule>,
|
||||
|
||||
/**
|
||||
* List folder rules for given folder node's and rule set's IDs as a page.
|
||||
*
|
||||
* <p>
|
||||
* - GET /nodes/{folderNodeId}/rule-sets/{ruleSetId}/rules
|
||||
*
|
||||
* @param folderNodeId - entity resource context for this relationship
|
||||
@@ -87,7 +87,7 @@ public class NodeRulesRelation implements RelationshipResourceAction.Read<Rule>,
|
||||
|
||||
/**
|
||||
* Get single folder rule for given node's, rule set's and rule's IDs.
|
||||
*
|
||||
* <p>
|
||||
* - GET /nodes/{folderNodeId}/rule-sets/{ruleSetId}/rules/{ruleId}
|
||||
*
|
||||
* @param folderNodeId - entity resource context for this relationship
|
||||
@@ -158,7 +158,7 @@ public class NodeRulesRelation implements RelationshipResourceAction.Read<Rule>,
|
||||
|
||||
/**
|
||||
* Delete single folder rule for given node's, rule set's and rule's IDs.
|
||||
*
|
||||
* <p>
|
||||
* - DELETE /nodes/{folderNodeId}/rule-sets/{ruleSetId}/rules/{ruleId}
|
||||
*
|
||||
* @param folderNodeId - entity resource context for this relationship
|
||||
|
@@ -863,6 +863,7 @@
|
||||
|
||||
<bean id="ruleSetLoader" class="org.alfresco.rest.api.impl.rules.RuleSetLoader">
|
||||
<property name="nodeService" ref="NodeService" />
|
||||
<property name="ruleService" ref="RuleService" />
|
||||
</bean>
|
||||
|
||||
<bean id="ruleSets" class="org.alfresco.rest.api.impl.rules.RuleSetsImpl">
|
||||
@@ -886,6 +887,7 @@
|
||||
<bean id="ruleLoader" class="org.alfresco.rest.api.impl.rules.RuleLoader">
|
||||
<property name="ruleService" ref="RuleService" />
|
||||
<property name="nodeValidator" ref="nodeValidator" />
|
||||
<property name="namespaceService" ref="NamespaceService"/>
|
||||
</bean>
|
||||
|
||||
<bean class="org.alfresco.rest.api.nodes.NodeRuleSetsRelation">
|
||||
@@ -909,6 +911,7 @@
|
||||
<property name="ruleLoader" ref="ruleLoader"/>
|
||||
<property name="actionParameterConverter" ref="actionParameterConverter"/>
|
||||
<property name="actionPermissionValidator" ref="actionPermissionValidator"/>
|
||||
<property name="namespaceService" ref="NamespaceService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="Rules" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
|
@@ -309,7 +309,7 @@ function sortByName(a, b)
|
||||
|
||||
function findUsers(searchTerm, maxResults, results)
|
||||
{
|
||||
var personRefs = people.getPeople(searchTerm, maxResults, "lastName", true);
|
||||
var personRefs = people.getPeople(searchTerm+ " [hint:useCQ]", maxResults, "lastName", true);
|
||||
|
||||
// create person object for each result
|
||||
for each(var personRef in personRefs)
|
||||
|
@@ -55,10 +55,14 @@ public class PreferenceServiceTest extends BaseWebScriptTest
|
||||
private PersonService personService;
|
||||
|
||||
private static final String USER_ONE = "PreferenceTestOne" + System.currentTimeMillis();
|
||||
|
||||
private static final String USER_TWO = "PreferenceTestTwo" + System.currentTimeMillis();
|
||||
private static final String USER_BAD = "PreferenceTestBad" + System.currentTimeMillis();
|
||||
|
||||
private static final String URL = "/api/people/" + USER_ONE + "/preferences";;
|
||||
private static final String URL = "/api/people/" + USER_ONE + "/preferences";
|
||||
private static final String URL2 = "/api/people/" + USER_TWO + "/preferences";
|
||||
|
||||
private static final int NUM_THREADS = 3;
|
||||
private static Integer THREADS_FINISHED = 0;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception
|
||||
@@ -75,6 +79,7 @@ public class PreferenceServiceTest extends BaseWebScriptTest
|
||||
|
||||
// Create users
|
||||
createUser(USER_ONE);
|
||||
createUser(USER_TWO);
|
||||
createUser(USER_BAD);
|
||||
|
||||
// Do tests as user one
|
||||
@@ -103,7 +108,6 @@ public class PreferenceServiceTest extends BaseWebScriptTest
|
||||
{
|
||||
super.tearDown();
|
||||
this.authenticationComponent.setCurrentUser(AuthenticationUtil.getAdminUserName());
|
||||
|
||||
}
|
||||
|
||||
public void testPreferences() throws Exception
|
||||
@@ -193,6 +197,64 @@ public class PreferenceServiceTest extends BaseWebScriptTest
|
||||
sendRequest(new GetRequest("/api/people/noExistUser/preferences"), 404);
|
||||
}
|
||||
|
||||
public void testPreferencesMNT21901() throws Exception
|
||||
{
|
||||
String[] body = {
|
||||
"{\"org\":{\"alfresco\":{\"share\":{\"forum\":{\"summary\":{\"dashlet\":{\"component-1-5\":{\"topics\":\"mine\"}}}}}}}}",
|
||||
"{\"org\":{\"alfresco\":{\"share\":{\"forum\":{\"summary\":{\"dashlet\":{\"component-2-5\":{\"topics\":\"mine\"}}}}}}}}",
|
||||
"{\"org\":{\"alfresco\":{\"share\":{\"forum\":{\"summary\":{\"dashlet\":{\"component-2-5\":{\"history\":\"1\"}}}}}}}}"
|
||||
};
|
||||
|
||||
Thread[] threads = new Thread[NUM_THREADS];
|
||||
|
||||
for (int i = 0; i < NUM_THREADS; i++)
|
||||
{
|
||||
UpdatePreferencesThread t = new UpdatePreferencesThread(i, body[i]);
|
||||
threads[i] = t;
|
||||
t.start();
|
||||
}
|
||||
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
{
|
||||
threads[i].join();
|
||||
}
|
||||
|
||||
authenticationComponent.setCurrentUser(USER_ONE);
|
||||
|
||||
if (THREADS_FINISHED != NUM_THREADS)
|
||||
{
|
||||
fail("An error has occurred when updating preferences in concurrency context");
|
||||
}
|
||||
}
|
||||
|
||||
private class UpdatePreferencesThread extends Thread
|
||||
{
|
||||
private String body;
|
||||
|
||||
UpdatePreferencesThread(int threadNum, String body)
|
||||
{
|
||||
super(UpdatePreferencesThread.class.getSimpleName() + "-" + threadNum);
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
authenticationComponent.setCurrentUser(USER_TWO);
|
||||
|
||||
try
|
||||
{
|
||||
Response resp = sendRequest(new PostRequest(URL2, body, "application/json"), 200);
|
||||
assertEquals(0, resp.getContentLength());
|
||||
THREADS_FINISHED++;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Intentionally empty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private JSONObject getPreferenceObj() throws JSONException
|
||||
{
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
@@ -208,5 +270,4 @@ public class PreferenceServiceTest extends BaseWebScriptTest
|
||||
assertEquals(10, jsonObject.get("numberValue"));
|
||||
assertEquals(BigDecimal.valueOf(3.142), jsonObject.get("numberValue2"));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -29,6 +29,7 @@ package org.alfresco.rest.api.impl.rules;
|
||||
import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
@@ -49,6 +50,7 @@ import org.alfresco.repo.action.executer.RemoveFeaturesActionExecuter;
|
||||
import org.alfresco.repo.action.executer.ScriptActionExecuter;
|
||||
import org.alfresco.repo.action.executer.SetPropertyValueActionExecuter;
|
||||
import org.alfresco.repo.action.executer.SimpleWorkflowActionExecuter;
|
||||
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
|
||||
import org.alfresco.service.Experimental;
|
||||
import org.alfresco.service.cmr.action.ActionDefinition;
|
||||
import org.alfresco.service.cmr.action.ActionService;
|
||||
@@ -553,6 +555,19 @@ public class ActionParameterConverterTest
|
||||
assertEquals(propType, convertedPropTypeParam);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidActionDefinitionConversion() {
|
||||
final String invalidName = "dummy-definition";
|
||||
final Map<String, Serializable> params = Map.of("dummy-key", "dummy-value");
|
||||
given(actionService.getActionDefinition(invalidName)).willReturn(null);
|
||||
//when-then
|
||||
assertThrows(NotFoundException.class, () ->objectUnderTest.getConvertedParams(params, invalidName));
|
||||
|
||||
given(actionService.getActionDefinition(invalidName)).willThrow(NotFoundException.class);
|
||||
//when-then
|
||||
assertThrows(NotFoundException.class, () ->objectUnderTest.getConvertedParams(params, invalidName));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQnameServiceModelParamConversion() {
|
||||
given(namespaceService.getPrefixes(any())).willReturn(List.of("cm"));
|
||||
|
@@ -26,11 +26,14 @@
|
||||
package org.alfresco.rest.api.impl.rules;
|
||||
|
||||
import static org.alfresco.rest.api.impl.rules.RuleSetLoader.INCLUSION_TYPE;
|
||||
import static org.alfresco.rest.api.impl.rules.RuleSetLoader.INHERITED_BY;
|
||||
import static org.alfresco.rest.api.impl.rules.RuleSetLoader.OWNING_FOLDER;
|
||||
import static org.alfresco.rest.api.model.rules.InclusionType.INHERITED;
|
||||
import static org.alfresco.rest.api.model.rules.InclusionType.LINKED;
|
||||
import static org.alfresco.rest.api.model.rules.InclusionType.OWNED;
|
||||
import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
|
||||
import java.util.List;
|
||||
@@ -41,6 +44,7 @@ import org.alfresco.service.Experimental;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.rule.RuleService;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -66,6 +70,8 @@ public class RuleSetLoaderTest extends TestCase
|
||||
@Mock
|
||||
private NodeService nodeServiceMock;
|
||||
@Mock
|
||||
private RuleService ruleServiceMock;
|
||||
@Mock
|
||||
private ChildAssociationRef ruleSetAssociationMock;
|
||||
@Mock
|
||||
private ChildAssociationRef linkAssociationMock;
|
||||
@@ -79,6 +85,8 @@ public class RuleSetLoaderTest extends TestCase
|
||||
|
||||
given(linkAssociationMock.getParentRef()).willReturn(LINKING_FOLDER);
|
||||
given(nodeServiceMock.getParentAssocs(RULE_SET_NODE)).willReturn(List.of(ruleSetAssociationMock, linkAssociationMock));
|
||||
|
||||
given(ruleServiceMock.getFoldersInheritingRuleSet(eq(RULE_SET_NODE), anyInt())).willReturn(List.of(INHERITING_FOLDER));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -130,4 +138,14 @@ public class RuleSetLoaderTest extends TestCase
|
||||
RuleSet expected = RuleSet.builder().id(RULE_SET_ID).inclusionType(INHERITED).create();
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadRuleSet_inheritedBy()
|
||||
{
|
||||
// Call the method under test.
|
||||
RuleSet actual = ruleSetLoader.loadRuleSet(RULE_SET_NODE, INHERITING_FOLDER, List.of(INHERITED_BY));
|
||||
|
||||
RuleSet expected = RuleSet.builder().id(RULE_SET_ID).inheritedBy(List.of(INHERITING_FOLDER)).create();
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
}
|
||||
|
@@ -33,6 +33,7 @@ import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -101,6 +102,8 @@ public class RuleSetsImplTest extends TestCase
|
||||
given(nodeValidatorMock.validateRuleSetNode(RULE_SET_ID, FOLDER_NODE)).willReturn(RULE_SET_NODE);
|
||||
|
||||
given(ruleServiceMock.getRuleSetNode(FOLDER_NODE)).willReturn(RULE_SET_NODE);
|
||||
given(ruleServiceMock.getNodesSupplyingRuleSets(FOLDER_NODE)).willReturn(List.of(FOLDER_NODE));
|
||||
|
||||
given(ruleSetLoaderMock.loadRuleSet(RULE_SET_NODE, FOLDER_NODE, INCLUDES)).willReturn(ruleSetMock);
|
||||
}
|
||||
|
||||
@@ -113,6 +116,7 @@ public class RuleSetsImplTest extends TestCase
|
||||
then(nodeValidatorMock).should().validateFolderNode(FOLDER_ID, false);
|
||||
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
then(ruleServiceMock).should().getNodesSupplyingRuleSets(FOLDER_NODE);
|
||||
then(ruleServiceMock).should().getRuleSetNode(FOLDER_NODE);
|
||||
then(ruleServiceMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
@@ -133,6 +137,7 @@ public class RuleSetsImplTest extends TestCase
|
||||
then(nodeValidatorMock).should().validateFolderNode(FOLDER_ID, false);
|
||||
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
then(ruleServiceMock).should().getNodesSupplyingRuleSets(FOLDER_NODE);
|
||||
then(ruleServiceMock).should().getRuleSetNode(FOLDER_NODE);
|
||||
then(ruleServiceMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
@@ -140,6 +145,62 @@ public class RuleSetsImplTest extends TestCase
|
||||
assertEquals(PAGING, actual.getPaging());
|
||||
}
|
||||
|
||||
/** Check that a folder with a parent and grandparent can inherit rule sets from the grandparent, even if the parent has no rules. */
|
||||
@Test
|
||||
public void testGetInheritedRuleSets()
|
||||
{
|
||||
// Simulate a parent node without a rule set.
|
||||
NodeRef parentNode = new NodeRef("parent://node/");
|
||||
// Simulate a grandparent node providing a rule set.
|
||||
NodeRef grandparentNode = new NodeRef("grandparent://node/");
|
||||
RuleSet grandparentRuleSet = mock(RuleSet.class);
|
||||
NodeRef grandparentRuleSetNode = new NodeRef("grandparent://rule-set/");
|
||||
given(ruleServiceMock.getRuleSetNode(grandparentNode)).willReturn(grandparentRuleSetNode);
|
||||
given(ruleSetLoaderMock.loadRuleSet(grandparentRuleSetNode, FOLDER_NODE, INCLUDES)).willReturn(grandparentRuleSet);
|
||||
// These should be returned with the highest in hierarchy first.
|
||||
given(ruleServiceMock.getNodesSupplyingRuleSets(FOLDER_NODE)).willReturn(List.of(grandparentNode, parentNode, FOLDER_NODE));
|
||||
|
||||
// Call the method under test.
|
||||
CollectionWithPagingInfo<RuleSet> actual = ruleSets.getRuleSets(FOLDER_ID, INCLUDES, PAGING);
|
||||
|
||||
then(nodeValidatorMock).should().validateFolderNode(FOLDER_ID, false);
|
||||
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
then(ruleServiceMock).should().getNodesSupplyingRuleSets(FOLDER_NODE);
|
||||
then(ruleServiceMock).should().getRuleSetNode(grandparentNode);
|
||||
then(ruleServiceMock).should().getRuleSetNode(parentNode);
|
||||
then(ruleServiceMock).should().getRuleSetNode(FOLDER_NODE);
|
||||
then(ruleServiceMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
Collection<RuleSet> expected = List.of(grandparentRuleSet, ruleSetMock);
|
||||
assertEquals(expected, actual.getCollection());
|
||||
assertEquals(PAGING, actual.getPaging());
|
||||
}
|
||||
|
||||
/** When getting rule sets then only the first instance of each rule set should be included (ancestor first). */
|
||||
@Test
|
||||
public void testGetDuplicateRuleSets()
|
||||
{
|
||||
// Simulate a grandparent, parent and child with the grandparent linking to the child's rule set.
|
||||
NodeRef grandparentNode = new NodeRef("grandparent://node/");
|
||||
given(ruleServiceMock.getRuleSetNode(grandparentNode)).willReturn(RULE_SET_NODE);
|
||||
NodeRef parentNode = new NodeRef("parent://node/");
|
||||
RuleSet parentRuleSet = mock(RuleSet.class);
|
||||
NodeRef parentRuleSetNode = new NodeRef("parent://rule-set/");
|
||||
given(ruleServiceMock.getRuleSetNode(parentNode)).willReturn(parentRuleSetNode);
|
||||
given(ruleSetLoaderMock.loadRuleSet(parentRuleSetNode, FOLDER_NODE, INCLUDES)).willReturn(parentRuleSet);
|
||||
// These should be returned with the highest in hierarchy first.
|
||||
given(ruleServiceMock.getNodesSupplyingRuleSets(FOLDER_NODE)).willReturn(List.of(grandparentNode, parentNode, FOLDER_NODE));
|
||||
|
||||
// Call the method under test.
|
||||
CollectionWithPagingInfo<RuleSet> actual = ruleSets.getRuleSets(FOLDER_ID, INCLUDES, PAGING);
|
||||
|
||||
// The grandparent's linked rule set should be first and only appear once.
|
||||
Collection<RuleSet> expected = List.of(ruleSetMock, parentRuleSet);
|
||||
assertEquals(expected, actual.getCollection());
|
||||
assertEquals(PAGING, actual.getPaging());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRuleSetById()
|
||||
{
|
||||
|
@@ -49,6 +49,7 @@ import junit.framework.TestCase;
|
||||
import org.alfresco.repo.action.ActionImpl;
|
||||
import org.alfresco.repo.action.CompositeActionImpl;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.model.rules.Action;
|
||||
import org.alfresco.rest.api.model.rules.Rule;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
@@ -61,6 +62,7 @@ import org.alfresco.service.cmr.action.CompositeAction;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.rule.RuleService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -87,6 +89,8 @@ public class RulesImplTest extends TestCase
|
||||
@Mock
|
||||
private Nodes nodesMock;
|
||||
@Mock
|
||||
private NamespaceService namespaceService;
|
||||
@Mock
|
||||
private NodeValidator nodeValidatorMock;
|
||||
@Mock
|
||||
private RuleService ruleServiceMock;
|
||||
@@ -100,6 +104,9 @@ public class RulesImplTest extends TestCase
|
||||
private org.alfresco.service.cmr.rule.Rule serviceRuleMock;
|
||||
@Mock
|
||||
private Rule ruleMock;
|
||||
@Mock
|
||||
private Action actionMock;
|
||||
|
||||
private org.alfresco.service.cmr.rule.Rule ruleModel = createRule(RULE_ID);
|
||||
private CompositeAction compositeAction = new CompositeActionImpl(RULE_NODE_REF, "compositeActionId");
|
||||
|
||||
@@ -115,7 +122,8 @@ public class RulesImplTest extends TestCase
|
||||
given(nodeValidatorMock.validateRuleNode(any(), any())).willReturn(RULE_NODE_REF);
|
||||
|
||||
given(ruleServiceMock.getRule(RULE_NODE_REF)).willReturn(ruleModel);
|
||||
given(ruleServiceMock.getRules(FOLDER_NODE_REF)).willReturn(List.of(ruleModel));
|
||||
given(ruleServiceMock.getRules(FOLDER_NODE_REF, false)).willReturn(List.of(ruleModel));
|
||||
given(ruleServiceMock.getOwningNodeRef(RULE_SET_NODE_REF)).willReturn(FOLDER_NODE_REF);
|
||||
|
||||
given(ruleLoaderMock.loadRule(ruleModel, INCLUDE)).willReturn(ruleMock);
|
||||
|
||||
@@ -126,13 +134,15 @@ public class RulesImplTest extends TestCase
|
||||
public void testGetRules()
|
||||
{
|
||||
given(ruleLoaderMock.loadRule(ruleModel, emptyList())).willReturn(ruleMock);
|
||||
|
||||
// when
|
||||
final CollectionWithPagingInfo<Rule> rulesPage = rules.getRules(FOLDER_NODE_ID, RULE_SET_ID, INCLUDE, PAGING);
|
||||
|
||||
then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, false);
|
||||
then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
|
||||
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
|
||||
then(ruleServiceMock).should().getRules(FOLDER_NODE_REF);
|
||||
then(ruleServiceMock).should().getOwningNodeRef(RULE_SET_NODE_REF);
|
||||
then(ruleServiceMock).should().getRules(FOLDER_NODE_REF, false);
|
||||
then(ruleServiceMock).shouldHaveNoMoreInteractions();
|
||||
then(ruleLoaderMock).should().loadRule(ruleModel, emptyList());
|
||||
then(ruleLoaderMock).shouldHaveNoMoreInteractions();
|
||||
@@ -148,12 +158,13 @@ public class RulesImplTest extends TestCase
|
||||
@Test
|
||||
public void testGetRules_emptyResult()
|
||||
{
|
||||
given(ruleServiceMock.getRules(any())).willReturn(emptyList());
|
||||
given(ruleServiceMock.getRules(FOLDER_NODE_REF, false)).willReturn(emptyList());
|
||||
|
||||
// when
|
||||
final CollectionWithPagingInfo<Rule> rulesPage = rules.getRules(FOLDER_NODE_ID, RULE_SET_ID, INCLUDE, PAGING);
|
||||
|
||||
then(ruleServiceMock).should().getRules(FOLDER_NODE_REF);
|
||||
then(ruleServiceMock).should().getOwningNodeRef(RULE_SET_NODE_REF);
|
||||
then(ruleServiceMock).should().getRules(FOLDER_NODE_REF, false);
|
||||
then(ruleServiceMock).shouldHaveNoMoreInteractions();
|
||||
assertThat(rulesPage)
|
||||
.isNotNull()
|
||||
@@ -284,7 +295,8 @@ public class RulesImplTest extends TestCase
|
||||
public void testCreateRules()
|
||||
{
|
||||
List<Rule> ruleList = List.of(ruleMock);
|
||||
given(ruleMock.toServiceModel(nodesMock)).willReturn(serviceRuleMock);
|
||||
given(ruleMock.toServiceModel(nodesMock, namespaceService)).willReturn(serviceRuleMock);
|
||||
given(ruleMock.getActions()).willReturn(List.of(actionMock));
|
||||
given(serviceRuleMock.getAction()).willReturn(compositeAction);
|
||||
given(ruleServiceMock.saveRule(FOLDER_NODE_REF, serviceRuleMock)).willAnswer(arg -> arg.getArguments()[1]);
|
||||
given(ruleLoaderMock.loadRule(serviceRuleMock, INCLUDE)).willReturn(ruleMock);
|
||||
@@ -300,7 +312,7 @@ public class RulesImplTest extends TestCase
|
||||
then(actionParameterConverterMock).shouldHaveNoMoreInteractions();
|
||||
then(actionPermissionValidatorMock).should().validateRulePermissions(serviceRuleMock);
|
||||
then(actionPermissionValidatorMock).shouldHaveNoMoreInteractions();
|
||||
then(ruleServiceMock).should().saveRule(FOLDER_NODE_REF, ruleMock.toServiceModel(nodesMock));
|
||||
then(ruleServiceMock).should().saveRule(FOLDER_NODE_REF, ruleMock.toServiceModel(nodesMock, namespaceService));
|
||||
then(ruleServiceMock).shouldHaveNoMoreInteractions();
|
||||
List<Rule> expected = List.of(ruleMock);
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
@@ -313,7 +325,8 @@ public class RulesImplTest extends TestCase
|
||||
public void testCreateRules_defaultRuleSet()
|
||||
{
|
||||
List<Rule> ruleList = List.of(ruleMock);
|
||||
given(ruleMock.toServiceModel(nodesMock)).willReturn(serviceRuleMock);
|
||||
given(ruleMock.toServiceModel(nodesMock, namespaceService)).willReturn(serviceRuleMock);
|
||||
given(ruleMock.getActions()).willReturn(List.of(actionMock));
|
||||
given(ruleServiceMock.saveRule(FOLDER_NODE_REF, serviceRuleMock)).willAnswer(arg -> arg.getArguments()[1]);
|
||||
given(ruleLoaderMock.loadRule(serviceRuleMock, INCLUDE)).willReturn(ruleMock);
|
||||
given(serviceRuleMock.getAction()).willReturn(compositeAction);
|
||||
@@ -328,7 +341,7 @@ public class RulesImplTest extends TestCase
|
||||
then(actionParameterConverterMock).shouldHaveNoMoreInteractions();
|
||||
then(actionPermissionValidatorMock).should().validateRulePermissions(serviceRuleMock);
|
||||
then(actionPermissionValidatorMock).shouldHaveNoMoreInteractions();
|
||||
then(ruleServiceMock).should().saveRule(FOLDER_NODE_REF, ruleMock.toServiceModel(nodesMock));
|
||||
then(ruleServiceMock).should().saveRule(FOLDER_NODE_REF, ruleMock.toServiceModel(nodesMock, namespaceService));
|
||||
then(ruleServiceMock).shouldHaveNoMoreInteractions();
|
||||
List<Rule> expected = List.of(ruleMock);
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
@@ -356,9 +369,10 @@ public class RulesImplTest extends TestCase
|
||||
List<Rule> expected = new ArrayList<>();
|
||||
IntStream.range(0, 3).forEach(i -> {
|
||||
Rule ruleBodyMock = mock(Rule.class);
|
||||
given(ruleBodyMock.getActions()).willReturn(List.of(actionMock));
|
||||
ruleBodyList.add(ruleBodyMock);
|
||||
org.alfresco.service.cmr.rule.Rule serviceRuleMockInner = mock(org.alfresco.service.cmr.rule.Rule.class);
|
||||
given(ruleBodyMock.toServiceModel(nodesMock)).willReturn(serviceRuleMockInner);
|
||||
given(ruleBodyMock.toServiceModel(nodesMock, namespaceService)).willReturn(serviceRuleMockInner);
|
||||
final CompositeAction compositeActionInner = new CompositeActionImpl(RULE_NODE_REF, "compositeActionInnerId");
|
||||
compositeActionInner.addAction(new ActionImpl(FOLDER_NODE_REF, "actionInnerId", ACTION_DEFINITION_NAME, DUMMY_PARAMS));
|
||||
given(serviceRuleMockInner.getAction()).willReturn(compositeActionInner);
|
||||
@@ -377,8 +391,8 @@ public class RulesImplTest extends TestCase
|
||||
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
|
||||
for (Rule ruleBody : ruleBodyList)
|
||||
{
|
||||
then(actionPermissionValidatorMock).should().validateRulePermissions(ruleBody.toServiceModel(nodesMock));
|
||||
then(ruleServiceMock).should().saveRule(FOLDER_NODE_REF, ruleBody.toServiceModel(nodesMock));
|
||||
then(actionPermissionValidatorMock).should().validateRulePermissions(ruleBody.toServiceModel(nodesMock, namespaceService));
|
||||
then(ruleServiceMock).should().saveRule(FOLDER_NODE_REF, ruleBody.toServiceModel(nodesMock, namespaceService));
|
||||
}
|
||||
then(actionParameterConverterMock).should(times(3)).getConvertedParams(DUMMY_PARAMS, ACTION_DEFINITION_NAME);
|
||||
then(actionParameterConverterMock).shouldHaveNoMoreInteractions();
|
||||
@@ -425,13 +439,35 @@ public class RulesImplTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fail on create a rule without any actions.
|
||||
*/
|
||||
@Test
|
||||
public void testCreateRuleWithoutActionsShouldFail()
|
||||
{
|
||||
List<Rule> ruleList = List.of(ruleMock);
|
||||
given(ruleMock.getActions()).willReturn(null);
|
||||
|
||||
// when
|
||||
assertThatExceptionOfType(InvalidArgumentException.class)
|
||||
.isThrownBy(() -> rules.createRules(FOLDER_NODE_REF.getId(), RULE_SET_NODE_REF.getId(), ruleList, INCLUDE));
|
||||
|
||||
then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
|
||||
then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
|
||||
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
|
||||
then(actionParameterConverterMock).shouldHaveNoInteractions();
|
||||
then(actionPermissionValidatorMock).shouldHaveNoInteractions();
|
||||
then(ruleServiceMock).shouldHaveNoInteractions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that we can update a rule.
|
||||
*/
|
||||
@Test
|
||||
public void testUpdateRuleById()
|
||||
{
|
||||
given(ruleMock.toServiceModel(nodesMock)).willReturn(serviceRuleMock);
|
||||
given(ruleMock.toServiceModel(nodesMock, namespaceService)).willReturn(serviceRuleMock);
|
||||
given(ruleMock.getActions()).willReturn(List.of(actionMock));
|
||||
given(ruleServiceMock.saveRule(FOLDER_NODE_REF, serviceRuleMock)).willAnswer(a -> a.getArguments()[1]);
|
||||
given(serviceRuleMock.getAction()).willReturn(compositeAction);
|
||||
given(ruleLoaderMock.loadRule(serviceRuleMock, INCLUDE)).willReturn(ruleMock);
|
||||
@@ -513,6 +549,28 @@ public class RulesImplTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fail on update a rule without any actions.
|
||||
*/
|
||||
@Test
|
||||
public void testUpdateRuleWithoutActionShouldFail()
|
||||
{
|
||||
given(ruleMock.getActions()).willReturn(emptyList());
|
||||
|
||||
// when
|
||||
assertThatExceptionOfType(InvalidArgumentException.class)
|
||||
.isThrownBy(() -> rules.updateRuleById(FOLDER_NODE_REF.getId(), RULE_SET_NODE_REF.getId(), RULE_ID, ruleMock, INCLUDE));
|
||||
|
||||
then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
|
||||
then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
|
||||
then(nodeValidatorMock).should().validateRuleNode(RULE_ID, RULE_SET_NODE_REF);
|
||||
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
then(ruleServiceMock).shouldHaveNoInteractions();
|
||||
then(actionParameterConverterMock).shouldHaveNoInteractions();
|
||||
then(actionPermissionValidatorMock).shouldHaveNoInteractions();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteRuleById()
|
||||
{
|
||||
|
@@ -27,6 +27,7 @@
|
||||
package org.alfresco.rest.api.model.rules;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
@@ -39,12 +40,18 @@ import org.alfresco.repo.action.ActionConditionImpl;
|
||||
import org.alfresco.repo.action.evaluator.ComparePropertyValueEvaluator;
|
||||
import org.alfresco.service.Experimental;
|
||||
import org.alfresco.service.cmr.action.ActionCondition;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@Experimental
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class CompositeConditionTest
|
||||
{
|
||||
|
||||
private final NamespaceService namespaceService = mock(NamespaceService.class);
|
||||
|
||||
@Test
|
||||
public void testFrom()
|
||||
{
|
||||
@@ -64,7 +71,7 @@ public class CompositeConditionTest
|
||||
));
|
||||
|
||||
// when
|
||||
final CompositeCondition actualCompositeCondition = CompositeCondition.from(actionConditions);
|
||||
final CompositeCondition actualCompositeCondition = CompositeCondition.from(actionConditions, namespaceService);
|
||||
|
||||
assertThat(actualCompositeCondition).isNotNull().usingRecursiveComparison().isEqualTo(expectedCompositeCondition);
|
||||
}
|
||||
@@ -76,7 +83,7 @@ public class CompositeConditionTest
|
||||
final CompositeCondition expectedCompositeCondition = CompositeCondition.builder().create();
|
||||
|
||||
// when
|
||||
final CompositeCondition actualCompositeCondition = CompositeCondition.from(actionConditions);
|
||||
final CompositeCondition actualCompositeCondition = CompositeCondition.from(actionConditions, namespaceService);
|
||||
|
||||
assertThat(actualCompositeCondition).isNotNull().usingRecursiveComparison().isEqualTo(expectedCompositeCondition);
|
||||
}
|
||||
@@ -85,7 +92,7 @@ public class CompositeConditionTest
|
||||
public void testFromNullValue()
|
||||
{
|
||||
// when
|
||||
final CompositeCondition actualCompositeCondition = CompositeCondition.from(null);
|
||||
final CompositeCondition actualCompositeCondition = CompositeCondition.from(null, namespaceService);
|
||||
|
||||
assertThat(actualCompositeCondition).isNull();
|
||||
}
|
||||
@@ -98,7 +105,7 @@ public class CompositeConditionTest
|
||||
final CompositeCondition expectedCompositeCondition = CompositeCondition.builder().create();
|
||||
|
||||
// when
|
||||
final CompositeCondition actualCompositeCondition = CompositeCondition.from(actionConditions);
|
||||
final CompositeCondition actualCompositeCondition = CompositeCondition.from(actionConditions, namespaceService);
|
||||
|
||||
assertThat(actualCompositeCondition).isNotNull().usingRecursiveComparison().isEqualTo(expectedCompositeCondition);
|
||||
}
|
||||
|
@@ -42,6 +42,7 @@ import org.alfresco.service.cmr.action.ActionCondition;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.rule.RuleType;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
@@ -60,6 +61,8 @@ public class RuleTest
|
||||
private static final String ACTION_DEFINITION_NAME = "action-def-name";
|
||||
private static final String ERROR_SCRIPT = "error-script-ref";
|
||||
|
||||
private final NamespaceService namespaceService = mock(NamespaceService.class);
|
||||
|
||||
@Test
|
||||
public void testFrom()
|
||||
{
|
||||
@@ -67,7 +70,7 @@ public class RuleTest
|
||||
final Rule expectedRule = createRuleWithDefaultValues();
|
||||
|
||||
// when
|
||||
final Rule actualRule = Rule.from(ruleModel);
|
||||
final Rule actualRule = Rule.from(ruleModel, namespaceService);
|
||||
|
||||
assertThat(actualRule).isNotNull().usingRecursiveComparison().isEqualTo(expectedRule);
|
||||
|
||||
@@ -80,7 +83,7 @@ public class RuleTest
|
||||
final Rule expectedRule = Rule.builder().enabled(true).create();
|
||||
|
||||
// when
|
||||
final Rule actualRule = Rule.from(ruleModel);
|
||||
final Rule actualRule = Rule.from(ruleModel, namespaceService);
|
||||
|
||||
assertThat(actualRule).isNotNull().usingRecursiveComparison().isEqualTo(expectedRule);
|
||||
|
||||
@@ -96,7 +99,7 @@ public class RuleTest
|
||||
final org.alfresco.service.cmr.action.Action expectedCompensatingActionModel = createCompensatingActionModel();
|
||||
|
||||
// when
|
||||
final org.alfresco.service.cmr.rule.Rule actualRuleModel = rule.toServiceModel(nodesMock);
|
||||
final org.alfresco.service.cmr.rule.Rule actualRuleModel = rule.toServiceModel(nodesMock, namespaceService);
|
||||
|
||||
then(nodesMock).should().validateOrLookupNode(RULE_ID, null);
|
||||
then(nodesMock).shouldHaveNoMoreInteractions();
|
||||
@@ -121,7 +124,7 @@ public class RuleTest
|
||||
expectedRuleModel.setRuleDisabled(true);
|
||||
|
||||
// when
|
||||
final org.alfresco.service.cmr.rule.Rule actualRuleModel = rule.toServiceModel(nodesMock);
|
||||
final org.alfresco.service.cmr.rule.Rule actualRuleModel = rule.toServiceModel(nodesMock, namespaceService);
|
||||
|
||||
then(nodesMock).shouldHaveNoInteractions();
|
||||
assertThat(actualRuleModel)
|
||||
@@ -131,6 +134,20 @@ public class RuleTest
|
||||
.isEqualTo(expectedRuleModel);
|
||||
}
|
||||
|
||||
private Rule createRuleWithDefaultValues() {
|
||||
return Rule.builder()
|
||||
.id(RULE_ID)
|
||||
.name(RULE_NAME)
|
||||
.description(RULE_DESCRIPTION)
|
||||
.enabled(RULE_ENABLED)
|
||||
.cascade(RULE_CASCADE)
|
||||
.asynchronous(RULE_ASYNC)
|
||||
.triggers(List.of(RuleTrigger.INBOUND, RuleTrigger.UPDATE))
|
||||
.errorScript(ERROR_SCRIPT)
|
||||
.conditions(CompositeCondition.from(Collections.emptyList(), namespaceService))
|
||||
.create();
|
||||
}
|
||||
|
||||
private static org.alfresco.service.cmr.rule.Rule createRuleModel() {
|
||||
final NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, RULE_ID);
|
||||
final org.alfresco.service.cmr.rule.Rule ruleModel = new org.alfresco.service.cmr.rule.Rule(nodeRef);
|
||||
@@ -160,18 +177,4 @@ public class RuleTest
|
||||
|
||||
return compensatingActionModel;
|
||||
}
|
||||
|
||||
private static Rule createRuleWithDefaultValues() {
|
||||
return Rule.builder()
|
||||
.id(RULE_ID)
|
||||
.name(RULE_NAME)
|
||||
.description(RULE_DESCRIPTION)
|
||||
.enabled(RULE_ENABLED)
|
||||
.cascade(RULE_CASCADE)
|
||||
.asynchronous(RULE_ASYNC)
|
||||
.triggers(List.of(RuleTrigger.INBOUND, RuleTrigger.UPDATE))
|
||||
.errorScript(ERROR_SCRIPT)
|
||||
.conditions(CompositeCondition.from(Collections.emptyList()))
|
||||
.create();
|
||||
}
|
||||
}
|
@@ -27,6 +27,8 @@
|
||||
package org.alfresco.rest.api.model.rules;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
@@ -36,6 +38,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.action.ActionConditionImpl;
|
||||
import org.alfresco.repo.action.evaluator.CompareMimeTypeEvaluator;
|
||||
import org.alfresco.repo.action.evaluator.ComparePropertyValueEvaluator;
|
||||
@@ -46,28 +49,54 @@ import org.alfresco.repo.action.evaluator.HasVersionHistoryEvaluator;
|
||||
import org.alfresco.repo.action.evaluator.InCategoryEvaluator;
|
||||
import org.alfresco.repo.action.evaluator.IsSubTypeEvaluator;
|
||||
import org.alfresco.repo.action.evaluator.NoConditionEvaluator;
|
||||
import org.alfresco.repo.action.evaluator.compare.ComparePropertyValueOperation;
|
||||
import org.alfresco.repo.action.evaluator.compare.ContentPropertyName;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.service.Experimental;
|
||||
import org.alfresco.service.cmr.action.ActionCondition;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@Experimental
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SimpleConditionTest
|
||||
{
|
||||
private static final boolean NULL_RESULT = true;
|
||||
private static final boolean NOT_INVERTED = false;
|
||||
private static final String PARAMETER_DEFAULT = "value";
|
||||
|
||||
private final Nodes nodes = mock(Nodes.class);
|
||||
private final NamespaceService namespaceService = mock(NamespaceService.class);
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
given(namespaceService.getPrefixes(NamespaceService.CONTENT_MODEL_1_0_URI)).willReturn(List.of(NamespaceService.CONTENT_MODEL_PREFIX));
|
||||
given(namespaceService.getNamespaceURI(NamespaceService.CONTENT_MODEL_PREFIX)).willReturn(NamespaceService.CONTENT_MODEL_1_0_URI);
|
||||
given(namespaceService.getPrefixes(NamespaceService.AUDIO_MODEL_1_0_URI)).willReturn(List.of(NamespaceService.AUDIO_MODEL_PREFIX));
|
||||
given(namespaceService.getNamespaceURI(NamespaceService.AUDIO_MODEL_PREFIX)).willReturn(NamespaceService.AUDIO_MODEL_1_0_URI);
|
||||
}
|
||||
|
||||
private static List<TestData> getTestData() {
|
||||
return List.of(
|
||||
TestData.of(ComparePropertyValueEvaluator.NAME),
|
||||
TestData.of(CompareMimeTypeEvaluator.NAME),
|
||||
TestData.of(HasAspectEvaluator.NAME),
|
||||
TestData.of(HasChildEvaluator.NAME),
|
||||
TestData.of(HasChildEvaluator.NAME, NULL_RESULT),
|
||||
TestData.of(HasTagEvaluator.NAME),
|
||||
TestData.of(HasVersionHistoryEvaluator.NAME),
|
||||
TestData.of(HasVersionHistoryEvaluator.NAME, NULL_RESULT),
|
||||
TestData.of(InCategoryEvaluator.NAME),
|
||||
TestData.of(IsSubTypeEvaluator.NAME),
|
||||
TestData.of(NoConditionEvaluator.NAME, true),
|
||||
TestData.of("fake-definition-name", true),
|
||||
TestData.of("", true),
|
||||
TestData.of(null, true)
|
||||
TestData.of(NoConditionEvaluator.NAME, NULL_RESULT),
|
||||
TestData.of("fake-definition-name", NULL_RESULT),
|
||||
TestData.of("", NULL_RESULT),
|
||||
TestData.of(null, NULL_RESULT)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -76,10 +105,10 @@ public class SimpleConditionTest
|
||||
{
|
||||
for (TestData testData : getTestData())
|
||||
{
|
||||
final ActionCondition actionCondition = createActionCondition(testData.actionDefinitionName);
|
||||
final ActionCondition actionCondition = createActionCondition(testData.conditionDefinitionName);
|
||||
|
||||
// when
|
||||
final SimpleCondition actualSimpleCondition = SimpleCondition.from(actionCondition);
|
||||
final SimpleCondition actualSimpleCondition = SimpleCondition.from(actionCondition, namespaceService);
|
||||
|
||||
assertThat(Objects.isNull(actualSimpleCondition)).isEqualTo(testData.isNullResult);
|
||||
if (!testData.isNullResult)
|
||||
@@ -95,7 +124,7 @@ public class SimpleConditionTest
|
||||
public void testFromNullValue()
|
||||
{
|
||||
// when
|
||||
final SimpleCondition actualSimpleCondition = SimpleCondition.from(null);
|
||||
final SimpleCondition actualSimpleCondition = SimpleCondition.from(null, namespaceService);
|
||||
|
||||
assertThat(actualSimpleCondition).isNull();
|
||||
}
|
||||
@@ -106,7 +135,7 @@ public class SimpleConditionTest
|
||||
final ActionCondition actionCondition = new ActionConditionImpl("fake-id", null, createParameterValues());
|
||||
|
||||
// when
|
||||
final SimpleCondition actualSimpleCondition = SimpleCondition.from(actionCondition);
|
||||
final SimpleCondition actualSimpleCondition = SimpleCondition.from(actionCondition, namespaceService);
|
||||
|
||||
assertThat(actualSimpleCondition).isNull();
|
||||
}
|
||||
@@ -117,7 +146,7 @@ public class SimpleConditionTest
|
||||
final ActionCondition actionCondition = new ActionConditionImpl("fake-id", "fake-def-name", null);
|
||||
|
||||
// when
|
||||
final SimpleCondition actualSimpleCondition = SimpleCondition.from(actionCondition);
|
||||
final SimpleCondition actualSimpleCondition = SimpleCondition.from(actionCondition, namespaceService);
|
||||
|
||||
assertThat(actualSimpleCondition).isNull();
|
||||
}
|
||||
@@ -129,14 +158,22 @@ public class SimpleConditionTest
|
||||
createActionCondition(ComparePropertyValueEvaluator.NAME),
|
||||
createActionCondition(CompareMimeTypeEvaluator.NAME)
|
||||
);
|
||||
final List<SimpleCondition> expectedSimpleConditions = List.of(
|
||||
SimpleCondition.builder().field("content-property").comparator("operation").parameter("value").create(),
|
||||
SimpleCondition.builder().field("property").comparator("equals").parameter("value").create()
|
||||
);
|
||||
|
||||
// when
|
||||
final List<SimpleCondition> actualSimpleConditions = SimpleCondition.listOf(actionConditions);
|
||||
final List<SimpleCondition> actualSimpleConditions = SimpleCondition.listOf(actionConditions, namespaceService);
|
||||
|
||||
final List<SimpleCondition> expectedSimpleConditions = List.of(
|
||||
SimpleCondition.builder()
|
||||
.field("content-property")
|
||||
.comparator("operation")
|
||||
.parameter("value")
|
||||
.create(),
|
||||
SimpleCondition.builder()
|
||||
.field(SimpleCondition.PARAM_MIMETYPE)
|
||||
.comparator(ComparePropertyValueOperation.EQUALS.toString().toLowerCase())
|
||||
.parameter("value")
|
||||
.create()
|
||||
);
|
||||
assertThat(actualSimpleConditions)
|
||||
.isNotNull()
|
||||
.containsExactlyElementsOf(expectedSimpleConditions);
|
||||
@@ -145,7 +182,8 @@ public class SimpleConditionTest
|
||||
@Test
|
||||
public void testListOfEmptyActionConditions()
|
||||
{
|
||||
final List<SimpleCondition> actualSimpleConditions = SimpleCondition.listOf(Collections.emptyList());
|
||||
// when
|
||||
final List<SimpleCondition> actualSimpleConditions = SimpleCondition.listOf(Collections.emptyList(), namespaceService);
|
||||
|
||||
assertThat(actualSimpleConditions).isNull();
|
||||
}
|
||||
@@ -153,7 +191,8 @@ public class SimpleConditionTest
|
||||
@Test
|
||||
public void testListOfNullActionConditions()
|
||||
{
|
||||
final List<SimpleCondition> actualSimpleConditions = SimpleCondition.listOf(null);
|
||||
// when
|
||||
final List<SimpleCondition> actualSimpleConditions = SimpleCondition.listOf(null, namespaceService);
|
||||
|
||||
assertThat(actualSimpleConditions).isNull();
|
||||
}
|
||||
@@ -164,50 +203,207 @@ public class SimpleConditionTest
|
||||
final List<ActionCondition> actionConditions = new ArrayList<>();
|
||||
actionConditions.add(null);
|
||||
|
||||
final List<SimpleCondition> actualSimpleConditions = SimpleCondition.listOf(actionConditions);
|
||||
// when
|
||||
final List<SimpleCondition> actualSimpleConditions = SimpleCondition.listOf(actionConditions, namespaceService);
|
||||
|
||||
assertThat(actualSimpleConditions).isNotNull().isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToServiceModel_withSizeContentProperty()
|
||||
{
|
||||
final SimpleCondition simpleCondition = createSimpleCondition(ContentPropertyName.SIZE.toString().toLowerCase());
|
||||
|
||||
// when
|
||||
final ActionCondition actualActionCondition = simpleCondition.toServiceModel(NOT_INVERTED, nodes, namespaceService);
|
||||
|
||||
final Map<String, Serializable> expectedParameterValues = new HashMap<>();
|
||||
expectedParameterValues.put(ComparePropertyValueEvaluator.PARAM_CONTENT_PROPERTY, ContentPropertyName.SIZE.toString());
|
||||
expectedParameterValues.put(ComparePropertyValueEvaluator.PARAM_PROPERTY, ContentModel.TYPE_CONTENT);
|
||||
expectedParameterValues.put(ComparePropertyValueEvaluator.PARAM_OPERATION, ComparePropertyValueOperation.EQUALS.toString());
|
||||
expectedParameterValues.put(ComparePropertyValueEvaluator.PARAM_VALUE, PARAMETER_DEFAULT);
|
||||
ActionCondition expectedActionCondition = new ActionConditionImpl(null, ComparePropertyValueEvaluator.NAME, expectedParameterValues);
|
||||
assertThat(actualActionCondition)
|
||||
.isNotNull().usingRecursiveComparison().ignoringFields("id")
|
||||
.isEqualTo(expectedActionCondition);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToServiceModel_withoutContentProperty()
|
||||
{
|
||||
final SimpleCondition simpleCondition = createSimpleCondition(ContentModel.PROP_DESCRIPTION.toPrefixString(namespaceService));
|
||||
|
||||
// when
|
||||
final ActionCondition actualActionCondition = simpleCondition.toServiceModel(NOT_INVERTED, nodes, namespaceService);
|
||||
|
||||
final Map<String, Serializable> expectedParameterValues = new HashMap<>();
|
||||
expectedParameterValues.put(ComparePropertyValueEvaluator.PARAM_PROPERTY, ContentModel.PROP_DESCRIPTION);
|
||||
expectedParameterValues.put(ComparePropertyValueEvaluator.PARAM_OPERATION, ComparePropertyValueOperation.EQUALS.toString());
|
||||
expectedParameterValues.put(ComparePropertyValueEvaluator.PARAM_VALUE, PARAMETER_DEFAULT);
|
||||
final ActionCondition expectedActionCondition = new ActionConditionImpl(null, ComparePropertyValueEvaluator.NAME, expectedParameterValues);
|
||||
assertThat(actualActionCondition)
|
||||
.isNotNull().usingRecursiveComparison().ignoringFields("id", "parameterValues.property.prefix")
|
||||
.isEqualTo(expectedActionCondition);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToServiceModel_compareMimetype()
|
||||
{
|
||||
final SimpleCondition simpleCondition = createSimpleCondition(SimpleCondition.PARAM_MIMETYPE);
|
||||
|
||||
// when
|
||||
final ActionCondition actualActionCondition = simpleCondition.toServiceModel(NOT_INVERTED, nodes, namespaceService);
|
||||
|
||||
final Map<String, Serializable> expectedParameterValues = new HashMap<>();
|
||||
expectedParameterValues.put(ComparePropertyValueEvaluator.PARAM_PROPERTY, ContentModel.TYPE_CONTENT);
|
||||
expectedParameterValues.put(ComparePropertyValueEvaluator.PARAM_VALUE, PARAMETER_DEFAULT);
|
||||
final ActionCondition expectedActionCondition = new ActionConditionImpl(null, CompareMimeTypeEvaluator.NAME, expectedParameterValues);
|
||||
assertThat(actualActionCondition)
|
||||
.isNotNull().usingRecursiveComparison().ignoringFields("id")
|
||||
.isEqualTo(expectedActionCondition);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToServiceModel_hasAspect()
|
||||
{
|
||||
final QName audioAspect = QName.createQName(NamespaceService.AUDIO_MODEL_1_0_URI, NamespaceService.AUDIO_MODEL_PREFIX);
|
||||
final SimpleCondition simpleCondition = createSimpleCondition(HasAspectEvaluator.PARAM_ASPECT, audioAspect.toPrefixString(namespaceService));
|
||||
|
||||
// when
|
||||
final ActionCondition actualActionCondition = simpleCondition.toServiceModel(NOT_INVERTED, nodes, namespaceService);
|
||||
|
||||
final Map<String, Serializable> expectedParameterValues = new HashMap<>();
|
||||
expectedParameterValues.put(HasAspectEvaluator.PARAM_ASPECT, audioAspect);
|
||||
final ActionCondition expectedActionCondition = new ActionConditionImpl(null, HasAspectEvaluator.NAME, expectedParameterValues);
|
||||
assertThat(actualActionCondition)
|
||||
.isNotNull().usingRecursiveComparison().ignoringFields("id", "parameterValues.aspect.prefix")
|
||||
.isEqualTo(expectedActionCondition);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToServiceModel_hasTag()
|
||||
{
|
||||
final String tag = "some tag";
|
||||
final SimpleCondition simpleCondition = createSimpleCondition(HasTagEvaluator.PARAM_TAG, tag);
|
||||
|
||||
// when
|
||||
final ActionCondition actualActionCondition = simpleCondition.toServiceModel(NOT_INVERTED, nodes, namespaceService);
|
||||
|
||||
final Map<String, Serializable> expectedParameterValues = new HashMap<>();
|
||||
expectedParameterValues.put(HasTagEvaluator.PARAM_TAG, tag);
|
||||
final ActionCondition expectedActionCondition = new ActionConditionImpl(null, HasTagEvaluator.NAME, expectedParameterValues);
|
||||
assertThat(actualActionCondition)
|
||||
.isNotNull().usingRecursiveComparison().ignoringFields("id")
|
||||
.isEqualTo(expectedActionCondition);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToServiceModel_inCategory()
|
||||
{
|
||||
final SimpleCondition simpleCondition = createSimpleCondition(SimpleCondition.PARAM_CATEGORY);
|
||||
final NodeRef defaultNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, PARAMETER_DEFAULT);
|
||||
given(nodes.validateOrLookupNode(PARAMETER_DEFAULT, null)).willReturn(defaultNodeRef);
|
||||
|
||||
// when
|
||||
final ActionCondition actualActionCondition = simpleCondition.toServiceModel(NOT_INVERTED, nodes, namespaceService);
|
||||
|
||||
final Map<String, Serializable> expectedParameterValues = new HashMap<>();
|
||||
expectedParameterValues.put(InCategoryEvaluator.PARAM_CATEGORY_ASPECT, ContentModel.ASPECT_GEN_CLASSIFIABLE);
|
||||
expectedParameterValues.put(InCategoryEvaluator.PARAM_CATEGORY_VALUE, defaultNodeRef);
|
||||
final ActionCondition expectedActionCondition = new ActionConditionImpl(null, InCategoryEvaluator.NAME, expectedParameterValues);
|
||||
assertThat(actualActionCondition)
|
||||
.isNotNull().usingRecursiveComparison().ignoringFields("id")
|
||||
.isEqualTo(expectedActionCondition);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToServiceModel_isSubType()
|
||||
{
|
||||
final SimpleCondition simpleCondition = createSimpleCondition(IsSubTypeEvaluator.PARAM_TYPE, ContentModel.TYPE_FOLDER.toPrefixString(namespaceService));
|
||||
|
||||
// when
|
||||
final ActionCondition actualActionCondition = simpleCondition.toServiceModel(NOT_INVERTED, nodes, namespaceService);
|
||||
|
||||
final Map<String, Serializable> expectedParameterValues = new HashMap<>();
|
||||
expectedParameterValues.put(IsSubTypeEvaluator.PARAM_TYPE, ContentModel.TYPE_FOLDER);
|
||||
final ActionCondition expectedActionCondition = new ActionConditionImpl(null, IsSubTypeEvaluator.NAME, expectedParameterValues);
|
||||
assertThat(actualActionCondition)
|
||||
.isNotNull().usingRecursiveComparison().ignoringFields("id", "parameterValues.type.prefix")
|
||||
.isEqualTo(expectedActionCondition);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToServiceModel_inverted()
|
||||
{
|
||||
final SimpleCondition simpleCondition = createSimpleCondition(ContentModel.PROP_DESCRIPTION.toPrefixString(namespaceService));
|
||||
|
||||
// when
|
||||
final ActionCondition actualActionCondition = simpleCondition.toServiceModel(!NOT_INVERTED, nodes, namespaceService);
|
||||
|
||||
final Map<String, Serializable> expectedParameterValues = new HashMap<>();
|
||||
expectedParameterValues.put(ComparePropertyValueEvaluator.PARAM_PROPERTY, ContentModel.PROP_DESCRIPTION);
|
||||
expectedParameterValues.put(ComparePropertyValueEvaluator.PARAM_OPERATION, ComparePropertyValueOperation.EQUALS.toString());
|
||||
expectedParameterValues.put(ComparePropertyValueEvaluator.PARAM_VALUE, PARAMETER_DEFAULT);
|
||||
final ActionCondition expectedActionCondition = new ActionConditionImpl(null, ComparePropertyValueEvaluator.NAME, expectedParameterValues);
|
||||
expectedActionCondition.setInvertCondition(!NOT_INVERTED);
|
||||
assertThat(actualActionCondition)
|
||||
.isNotNull().usingRecursiveComparison().ignoringFields("id", "parameterValues.property.prefix")
|
||||
.isEqualTo(expectedActionCondition);
|
||||
}
|
||||
|
||||
private static SimpleCondition createSimpleCondition(final String field)
|
||||
{
|
||||
return createSimpleCondition(field, PARAMETER_DEFAULT);
|
||||
}
|
||||
|
||||
private static SimpleCondition createSimpleCondition(final String field, final String parameter)
|
||||
{
|
||||
return SimpleCondition.builder()
|
||||
.field(field)
|
||||
.comparator(ComparePropertyValueOperation.EQUALS.toString().toLowerCase())
|
||||
.parameter(parameter)
|
||||
.create();
|
||||
}
|
||||
|
||||
private static ActionCondition createActionCondition(final String actionDefinitionName)
|
||||
{
|
||||
return new ActionConditionImpl("fake-id", actionDefinitionName, createParameterValues());
|
||||
}
|
||||
|
||||
private static Map<String, Serializable> createParameterValues() {
|
||||
final QName audioAspect = QName.createQName(NamespaceService.AUDIO_MODEL_1_0_URI, NamespaceService.AUDIO_MODEL_PREFIX);
|
||||
final NodeRef defaultNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, PARAMETER_DEFAULT);
|
||||
final Map<String, Serializable> parameterValues = new HashMap<>();
|
||||
parameterValues.put(ComparePropertyValueEvaluator.PARAM_CONTENT_PROPERTY, "content-property");
|
||||
parameterValues.put(HasChildEvaluator.PARAM_ASSOC_TYPE, "assoc-type");
|
||||
parameterValues.put(ComparePropertyValueEvaluator.PARAM_PROPERTY, "property");
|
||||
parameterValues.put(ComparePropertyValueEvaluator.PARAM_PROPERTY, ContentModel.TYPE_CONTENT);
|
||||
parameterValues.put(ComparePropertyValueEvaluator.PARAM_OPERATION, "operation");
|
||||
parameterValues.put(ComparePropertyValueEvaluator.PARAM_VALUE, "value");
|
||||
parameterValues.put(HasAspectEvaluator.PARAM_ASPECT, "aspect");
|
||||
parameterValues.put(HasChildEvaluator.PARAM_ASSOC_NAME, "assoc-name");
|
||||
parameterValues.put(HasAspectEvaluator.PARAM_ASPECT, audioAspect);
|
||||
parameterValues.put(HasTagEvaluator.PARAM_TAG, "tag");
|
||||
parameterValues.put(InCategoryEvaluator.PARAM_CATEGORY_ASPECT, "category-aspect");
|
||||
parameterValues.put(InCategoryEvaluator.PARAM_CATEGORY_VALUE, "category-value");
|
||||
parameterValues.put(IsSubTypeEvaluator.PARAM_TYPE, "type");
|
||||
parameterValues.put(InCategoryEvaluator.PARAM_CATEGORY_VALUE, defaultNodeRef);
|
||||
parameterValues.put(IsSubTypeEvaluator.PARAM_TYPE, ContentModel.TYPE_FOLDER);
|
||||
|
||||
return parameterValues;
|
||||
}
|
||||
|
||||
private static class TestData
|
||||
{
|
||||
String actionDefinitionName;
|
||||
String conditionDefinitionName;
|
||||
boolean isNullResult;
|
||||
|
||||
public TestData(String actionDefinitionName, boolean isNullResult)
|
||||
public TestData(String conditionDefinitionName, boolean isNullResult)
|
||||
{
|
||||
this.actionDefinitionName = actionDefinitionName;
|
||||
this.conditionDefinitionName = conditionDefinitionName;
|
||||
this.isNullResult = isNullResult;
|
||||
}
|
||||
|
||||
public static TestData of(String actionDefinitionName) {
|
||||
return new TestData(actionDefinitionName, false);
|
||||
public static TestData of(String conditionDefinitionName) {
|
||||
return new TestData(conditionDefinitionName, false);
|
||||
}
|
||||
|
||||
public static TestData of(String actionDefinitionName, boolean isNullResult) {
|
||||
return new TestData(actionDefinitionName, isNullResult);
|
||||
public static TestData of(String conditionDefinitionName, boolean isNullResult) {
|
||||
return new TestData(conditionDefinitionName, isNullResult);
|
||||
}
|
||||
}
|
||||
}
|
@@ -106,6 +106,7 @@ import org.apache.commons.collections.map.MultiValueMap;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
@@ -3611,6 +3612,7 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest
|
||||
* {@literal <host>:<port>/alfresco/api/-default-/public/alfresco/versions/1/nodes/<nodeId>/content}
|
||||
*/
|
||||
@Test
|
||||
@Ignore("ACS-3531 Frequent intermittent failure")
|
||||
public void testDownloadFileContent() throws Exception
|
||||
{
|
||||
setRequestContext(user1);
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>17.102-SNAPSHOT</version>
|
||||
<version>17.118</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
@@ -691,6 +691,16 @@
|
||||
<artifactId>camel-mock</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- Netty non-transitive dependencies declared for depending projects usage in conjunction with Camel's other transitive netty dependencies -->
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-handler-proxy</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-tcnative-classes</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-client</artifactId>
|
||||
|
@@ -1,33 +1,34 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 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%
|
||||
*/
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 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.repo.action;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.alfresco.service.cmr.action.ParameterizedItem;
|
||||
|
||||
@@ -38,8 +39,8 @@ import org.alfresco.service.cmr.action.ParameterizedItem;
|
||||
*/
|
||||
public abstract class ParameterizedItemImpl implements ParameterizedItem, Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 3578052215076397741L;
|
||||
|
||||
private static final long serialVersionUID = 3578052215076397741L;
|
||||
|
||||
/**
|
||||
* The id
|
||||
*/
|
||||
@@ -50,23 +51,23 @@ public abstract class ParameterizedItemImpl implements ParameterizedItem, Serial
|
||||
*/
|
||||
private Map<String, Serializable> parameterValues = new HashMap<String, Serializable>();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param id the id
|
||||
*/
|
||||
public ParameterizedItemImpl(String id)
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param id the id
|
||||
*/
|
||||
public ParameterizedItemImpl(String id)
|
||||
{
|
||||
this(id, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param id the rule item
|
||||
* @param parameterValues the parameter values
|
||||
*/
|
||||
public ParameterizedItemImpl(String id, Map<String, Serializable> parameterValues)
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param id the rule item
|
||||
* @param parameterValues the parameter values
|
||||
*/
|
||||
public ParameterizedItemImpl(String id, Map<String, Serializable> parameterValues)
|
||||
{
|
||||
// Set the action id
|
||||
this.id = id;
|
||||
@@ -135,7 +136,7 @@ public abstract class ParameterizedItemImpl implements ParameterizedItem, Serial
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return this.id.hashCode();
|
||||
return Objects.hashCode(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2021 Alfresco Software Limited
|
||||
* Copyright (C) 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
|
||||
@@ -50,7 +50,7 @@ import org.alfresco.service.namespace.NamespaceException;
|
||||
import org.alfresco.service.namespace.NamespacePrefixResolver;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.transform.client.registry.TransformServiceRegistry;
|
||||
import org.alfresco.transform.registry.TransformServiceRegistry;
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.apache.commons.csv.CSVParser;
|
||||
import org.apache.commons.csv.CSVRecord;
|
||||
|
@@ -31,9 +31,9 @@ import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.transform.client.model.config.TransformOption;
|
||||
import org.alfresco.transform.client.model.config.TransformOptionGroup;
|
||||
import org.alfresco.transform.client.model.config.TransformOptionValue;
|
||||
import org.alfresco.transform.config.TransformOption;
|
||||
import org.alfresco.transform.config.TransformOptionGroup;
|
||||
import org.alfresco.transform.config.TransformOptionValue;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2019 Alfresco Software Limited
|
||||
* 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
|
||||
@@ -37,8 +37,8 @@ import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.transform.client.registry.SupportedTransform;
|
||||
import org.alfresco.transform.client.registry.TransformServiceRegistry;
|
||||
import org.alfresco.transform.registry.SupportedTransform;
|
||||
import org.alfresco.transform.registry.TransformServiceRegistry;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
import org.alfresco.util.TempFileProvider;
|
||||
import org.springframework.beans.BeansException;
|
||||
|
@@ -25,8 +25,8 @@
|
||||
*/
|
||||
package org.alfresco.repo.content.transform;
|
||||
|
||||
import org.alfresco.transform.client.model.config.CoreFunction;
|
||||
import org.alfresco.transform.client.registry.TransformServiceRegistry;
|
||||
import org.alfresco.transform.config.CoreFunction;
|
||||
import org.alfresco.transform.registry.TransformServiceRegistry;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2019 Alfresco Software Limited
|
||||
* Copyright (C) 2019-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
|
||||
@@ -31,7 +31,7 @@ import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.transform.client.model.config.TransformOption;
|
||||
import org.alfresco.transform.config.TransformOption;
|
||||
import org.alfresco.util.TempFileProvider;
|
||||
|
||||
import java.io.File;
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||
* 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
|
||||
@@ -31,11 +31,11 @@ import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.transform.client.model.config.SupportedSourceAndTarget;
|
||||
import org.alfresco.transform.client.model.config.TransformOption;
|
||||
import org.alfresco.transform.client.model.config.Transformer;
|
||||
import org.alfresco.transform.client.registry.AbstractTransformRegistry;
|
||||
import org.alfresco.transform.client.registry.CombinedConfig;
|
||||
import org.alfresco.transform.config.SupportedSourceAndTarget;
|
||||
import org.alfresco.transform.config.TransformOption;
|
||||
import org.alfresco.transform.config.Transformer;
|
||||
import org.alfresco.transform.registry.AbstractTransformRegistry;
|
||||
import org.alfresco.transform.registry.CombinedConfig;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
@@ -30,7 +30,7 @@ import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.transform.client.model.config.TransformOption;
|
||||
import org.alfresco.transform.config.TransformOption;
|
||||
import org.alfresco.util.TempFileProvider;
|
||||
|
||||
import java.io.File;
|
||||
@@ -39,7 +39,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.alfresco.transform.client.util.RequestParamMap.DIRECT_ACCESS_URL;
|
||||
import static org.alfresco.transform.common.RequestParamMap.DIRECT_ACCESS_URL;
|
||||
|
||||
/**
|
||||
* Transformer that passes a document through a pipeline of transformations to arrive at an target mimetype.
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||
* 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
|
||||
@@ -31,7 +31,7 @@ import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.transform.client.model.config.TransformOption;
|
||||
import org.alfresco.transform.config.TransformOption;
|
||||
import org.alfresco.util.Pair;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@@ -36,14 +36,14 @@ import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
import org.alfresco.transform.client.model.config.CoreFunction;
|
||||
import org.alfresco.transform.client.model.config.TransformOptionGroup;
|
||||
import org.alfresco.transform.client.registry.CombinedConfig;
|
||||
import org.alfresco.transform.client.model.config.TransformOption;
|
||||
import org.alfresco.transform.client.registry.TransformServiceRegistryImpl;
|
||||
import org.alfresco.transform.client.model.config.TransformStep;
|
||||
import org.alfresco.transform.client.model.config.Transformer;
|
||||
import org.alfresco.transform.client.registry.TransformServiceRegistry;
|
||||
import org.alfresco.transform.config.CoreFunction;
|
||||
import org.alfresco.transform.config.TransformOptionGroup;
|
||||
import org.alfresco.transform.registry.CombinedConfig;
|
||||
import org.alfresco.transform.config.TransformOption;
|
||||
import org.alfresco.transform.registry.TransformServiceRegistryImpl;
|
||||
import org.alfresco.transform.config.TransformStep;
|
||||
import org.alfresco.transform.config.Transformer;
|
||||
import org.alfresco.transform.registry.TransformServiceRegistry;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
@@ -220,6 +220,7 @@ public class DeleteNotExistsExecutor implements StatementExecutor
|
||||
{
|
||||
// Process batch
|
||||
primaryId = processPrimaryTableResultSet(primaryPrepStmt, secondaryPrepStmts, deletePrepStmt, deleteIds, primaryTableName, primaryColumnName, tableColumn);
|
||||
connection.commit();
|
||||
|
||||
if (primaryId == null)
|
||||
{
|
||||
@@ -298,7 +299,6 @@ public class DeleteNotExistsExecutor implements StatementExecutor
|
||||
if (deleteIds.size() == deleteBatchSize)
|
||||
{
|
||||
deleteFromPrimaryTable(deletePrepStmt, deleteIds, primaryTableName);
|
||||
connection.commit();
|
||||
}
|
||||
|
||||
if (!resultSet.next())
|
||||
|
@@ -117,6 +117,7 @@ public class MySQLDeleteNotExistsExecutor extends DeleteNotExistsExecutor
|
||||
{
|
||||
// Process batch
|
||||
primaryId = processPrimaryTableResultSet(primaryPrepStmt, secondaryPrepStmts, deletePrepStmt, deleteIds, primaryTableName, primaryColumnName, tableColumn);
|
||||
connection.commit();
|
||||
|
||||
if (primaryId == null)
|
||||
{
|
||||
|
@@ -33,7 +33,7 @@ import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.DirectAccessUrl;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.transform.client.model.config.CoreFunction;
|
||||
import org.alfresco.transform.config.CoreFunction;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -43,7 +43,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.alfresco.model.ContentModel.PROP_CONTENT;
|
||||
import static org.alfresco.transform.client.util.RequestParamMap.DIRECT_ACCESS_URL;
|
||||
import static org.alfresco.transform.common.RequestParamMap.DIRECT_ACCESS_URL;
|
||||
|
||||
/**
|
||||
* Request synchronous transforms.
|
||||
|
@@ -35,7 +35,7 @@ import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.DirectAccessUrl;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.transform.client.model.config.CoreFunction;
|
||||
import org.alfresco.transform.config.CoreFunction;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -48,7 +48,7 @@ import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import static org.alfresco.model.ContentModel.PROP_CONTENT;
|
||||
import static org.alfresco.transform.client.util.RequestParamMap.DIRECT_ACCESS_URL;
|
||||
import static org.alfresco.transform.common.RequestParamMap.DIRECT_ACCESS_URL;
|
||||
|
||||
/**
|
||||
* Requests rendition transforms take place using transforms available on the local machine (based on
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
* 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
|
||||
@@ -27,7 +27,7 @@ package org.alfresco.repo.rendition2;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.alfresco.transform.client.registry.TransformServiceRegistry;
|
||||
import org.alfresco.transform.registry.TransformServiceRegistry;
|
||||
import org.alfresco.util.ConfigFileFinder;
|
||||
import org.alfresco.util.ConfigScheduler;
|
||||
import org.alfresco.util.Pair;
|
||||
|
@@ -25,8 +25,8 @@
|
||||
*/
|
||||
package org.alfresco.repo.rendition2;
|
||||
|
||||
import org.alfresco.transform.client.model.config.CoreFunction;
|
||||
import org.alfresco.transform.client.registry.TransformServiceRegistry;
|
||||
import org.alfresco.transform.config.CoreFunction;
|
||||
import org.alfresco.transform.registry.TransformServiceRegistry;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
@@ -25,14 +25,25 @@
|
||||
*/
|
||||
package org.alfresco.repo.rule;
|
||||
|
||||
import static org.alfresco.model.ContentModel.ASSOC_CONTAINS;
|
||||
import static org.alfresco.repo.rule.RuleModel.ASPECT_IGNORE_INHERITED_RULES;
|
||||
import static org.alfresco.repo.rule.RuleModel.ASSOC_RULE_FOLDER;
|
||||
import static org.alfresco.service.cmr.security.AccessStatus.ALLOWED;
|
||||
import static org.alfresco.service.namespace.RegexQNamePattern.MATCH_ALL;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.action.ActionImpl;
|
||||
@@ -64,7 +75,6 @@ import org.alfresco.service.cmr.rule.Rule;
|
||||
import org.alfresco.service.cmr.rule.RuleService;
|
||||
import org.alfresco.service.cmr.rule.RuleServiceException;
|
||||
import org.alfresco.service.cmr.rule.RuleType;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.namespace.QNamePattern;
|
||||
@@ -255,7 +265,7 @@ public class RuleServiceImpl
|
||||
policyComponent.bindAssociationBehaviour(
|
||||
NodeServicePolicies.OnCreateChildAssociationPolicy.QNAME,
|
||||
RuleModel.ASPECT_RULES,
|
||||
RuleModel.ASSOC_RULE_FOLDER,
|
||||
ASSOC_RULE_FOLDER,
|
||||
new JavaBehaviour(this, "onCreateChildAssociation"));
|
||||
policyComponent.bindClassBehaviour(
|
||||
NodeServicePolicies.OnAddAspectPolicy.QNAME,
|
||||
@@ -347,8 +357,8 @@ public class RuleServiceImpl
|
||||
|
||||
List<ChildAssociationRef> assocs = this.runtimeNodeService.getChildAssocs(
|
||||
nodeRef,
|
||||
RuleModel.ASSOC_RULE_FOLDER,
|
||||
RuleModel.ASSOC_RULE_FOLDER);
|
||||
ASSOC_RULE_FOLDER,
|
||||
ASSOC_RULE_FOLDER);
|
||||
if (assocs.size() > 1)
|
||||
{
|
||||
throw new ActionServiceException("There is more than one rule folder, which is invalid.");
|
||||
@@ -479,7 +489,7 @@ public class RuleServiceImpl
|
||||
// Node has gone or is not the correct type
|
||||
return rules;
|
||||
}
|
||||
if (includeInherited == true && runtimeNodeService.hasAspect(nodeRef, RuleModel.ASPECT_IGNORE_INHERITED_RULES) == false)
|
||||
if (includeInherited && !runtimeNodeService.hasAspect(nodeRef, ASPECT_IGNORE_INHERITED_RULES))
|
||||
{
|
||||
// Get any inherited rules
|
||||
for (Rule rule : getInheritedRules(nodeRef, ruleTypeName, null))
|
||||
@@ -514,7 +524,7 @@ public class RuleServiceImpl
|
||||
// https://issues.alfresco.com/browse/ETWOTWO-438
|
||||
|
||||
if (!runtimeNodeService.hasAspect(nodeRef, RuleModel.ASPECT_RULES) ||
|
||||
permissionService.hasPermission(nodeRef, PermissionService.READ) != AccessStatus.ALLOWED)
|
||||
permissionService.hasPermission(nodeRef, PermissionService.READ) != ALLOWED)
|
||||
{
|
||||
// Doesn't have the aspect or the user doesn't have access
|
||||
return Collections.emptyList();
|
||||
@@ -532,7 +542,7 @@ public class RuleServiceImpl
|
||||
{
|
||||
// Get the rules for this node
|
||||
List<ChildAssociationRef> ruleChildAssocRefs =
|
||||
this.runtimeNodeService.getChildAssocs(ruleFolder, RegexQNamePattern.MATCH_ALL, ASSOC_NAME_RULES_REGEX);
|
||||
this.runtimeNodeService.getChildAssocs(ruleFolder, MATCH_ALL, ASSOC_NAME_RULES_REGEX);
|
||||
for (ChildAssociationRef ruleChildAssocRef : ruleChildAssocRefs)
|
||||
{
|
||||
// Create the rule and add to the list
|
||||
@@ -561,7 +571,7 @@ public class RuleServiceImpl
|
||||
{
|
||||
// Get the rules for this node
|
||||
List<ChildAssociationRef> ruleChildAssocRefs =
|
||||
this.runtimeNodeService.getChildAssocs(ruleFolder, RegexQNamePattern.MATCH_ALL, ASSOC_NAME_RULES_REGEX);
|
||||
this.runtimeNodeService.getChildAssocs(ruleFolder, MATCH_ALL, ASSOC_NAME_RULES_REGEX);
|
||||
|
||||
ruleCount = ruleChildAssocRefs.size();
|
||||
}
|
||||
@@ -597,10 +607,91 @@ public class RuleServiceImpl
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
@Experimental
|
||||
public List<NodeRef> getNodesSupplyingRuleSets(NodeRef nodeRef)
|
||||
{
|
||||
return getNodesSupplyingRuleSets(nodeRef, new ArrayList<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverse the folder hierarchy find all the folder nodes that could supply rules by inheritance.
|
||||
* <p>
|
||||
* The order of nodes returned by this methods has to match the order used by {@link #getInheritedRules}.
|
||||
*
|
||||
* @param nodeRef The starting node ref.
|
||||
* @param visitedNodeRefs All the visited node refs (will be modified).
|
||||
* @return A list of node refs, starting with the first parent of the first parent of ... and ending with the object generated by the
|
||||
* given node ref.
|
||||
*/
|
||||
private List<NodeRef> getNodesSupplyingRuleSets(NodeRef nodeRef, List<NodeRef> visitedNodeRefs)
|
||||
{
|
||||
List<NodeRef> returnList = new ArrayList<>();
|
||||
// This check prevents stack over flow when we have a cyclic node graph
|
||||
if (!visitedNodeRefs.contains(nodeRef))
|
||||
{
|
||||
visitedNodeRefs.add(nodeRef);
|
||||
if (!runtimeNodeService.hasAspect(nodeRef, ASPECT_IGNORE_INHERITED_RULES))
|
||||
{
|
||||
List<ChildAssociationRef> parents = runtimeNodeService.getParentAssocs(nodeRef);
|
||||
for (ChildAssociationRef parent : parents)
|
||||
{
|
||||
// We are not interested in following potentially massive person group membership trees!
|
||||
if (!IGNORE_PARENT_ASSOC_TYPES.contains(parent.getTypeQName()))
|
||||
{
|
||||
// Update visitedNodeRefs with all the ancestors.
|
||||
returnList.addAll(getNodesSupplyingRuleSets(parent.getParentRef(), visitedNodeRefs));
|
||||
}
|
||||
}
|
||||
}
|
||||
returnList.add(nodeRef);
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
@Experimental
|
||||
public List<NodeRef> getFoldersInheritingRuleSet(NodeRef ruleSet, int maxFoldersToReturn)
|
||||
{
|
||||
// Seed stack with all folders owning or linking to the rule set.
|
||||
Deque<NodeRef> stack = new LinkedList<>();
|
||||
for (ChildAssociationRef parentAssociation : runtimeNodeService.getParentAssocs(ruleSet))
|
||||
{
|
||||
stack.add(parentAssociation.getParentRef());
|
||||
}
|
||||
// Process child folders to find all that inherit the rules.
|
||||
List<NodeRef> inheritors = new ArrayList<>();
|
||||
while (!stack.isEmpty() && inheritors.size() < maxFoldersToReturn)
|
||||
{
|
||||
NodeRef folder = stack.pop();
|
||||
runtimeNodeService.getChildAssocs(folder, ASSOC_CONTAINS, MATCH_ALL).stream().map(ChildAssociationRef::getChildRef).forEach(childNode -> {
|
||||
QName childType = runtimeNodeService.getType(childNode);
|
||||
if (dictionaryService.isSubClass(childType, ContentModel.TYPE_FOLDER)
|
||||
&& !runtimeNodeService.hasAspect(childNode, ASPECT_IGNORE_INHERITED_RULES))
|
||||
{
|
||||
stack.add(childNode);
|
||||
// Only return nodes that the user has permission to view.
|
||||
if (permissionService.hasReadPermission(childNode) == ALLOWED)
|
||||
{
|
||||
inheritors.add(childNode);
|
||||
if (inheritors.size() == maxFoldersToReturn)
|
||||
{
|
||||
// Return once we've hit the limit.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return inheritors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the inherited rules for a given node reference
|
||||
*
|
||||
*
|
||||
* @param nodeRef the nodeRef
|
||||
* @param ruleTypeName the rule type (null if all applicable)
|
||||
* @return a list of inherited rules (empty if none)
|
||||
@@ -608,20 +699,20 @@ public class RuleServiceImpl
|
||||
private List<Rule> getInheritedRules(NodeRef nodeRef, String ruleTypeName, Set<NodeRef> visitedNodeRefs)
|
||||
{
|
||||
List<Rule> inheritedRules = new ArrayList<Rule>();
|
||||
|
||||
|
||||
if (this.runtimeNodeService.hasAspect(nodeRef, RuleModel.ASPECT_IGNORE_INHERITED_RULES) == false)
|
||||
{
|
||||
{
|
||||
// Create the visited nodes set if it has not already been created
|
||||
if (visitedNodeRefs == null)
|
||||
{
|
||||
visitedNodeRefs = new HashSet<NodeRef>();
|
||||
}
|
||||
|
||||
|
||||
// This check prevents stack over flow when we have a cyclic node graph
|
||||
if (visitedNodeRefs.contains(nodeRef) == false)
|
||||
{
|
||||
visitedNodeRefs.add(nodeRef);
|
||||
|
||||
|
||||
List<Rule> allInheritedRules = new ArrayList<Rule>();
|
||||
List<ChildAssociationRef> parents = this.runtimeNodeService.getParentAssocs(nodeRef);
|
||||
for (ChildAssociationRef parent : parents)
|
||||
@@ -641,7 +732,7 @@ public class RuleServiceImpl
|
||||
allInheritedRules.add(rule);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
List<Rule> rules = getRules(parent.getParentRef(), false);
|
||||
for (Rule rule : rules)
|
||||
{
|
||||
@@ -652,7 +743,7 @@ public class RuleServiceImpl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (ruleTypeName == null)
|
||||
{
|
||||
inheritedRules = allInheritedRules;
|
||||
@@ -670,7 +761,7 @@ public class RuleServiceImpl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return inheritedRules;
|
||||
}
|
||||
|
||||
@@ -749,7 +840,7 @@ public class RuleServiceImpl
|
||||
{
|
||||
checkForLinkedRules(nodeRef);
|
||||
|
||||
if (this.permissionService.hasPermission(nodeRef, PermissionService.CHANGE_PERMISSIONS) != AccessStatus.ALLOWED)
|
||||
if (this.permissionService.hasPermission(nodeRef, PermissionService.CHANGE_PERMISSIONS) != ALLOWED)
|
||||
{
|
||||
throw new RuleServiceException("Insufficient permissions to save a rule.");
|
||||
}
|
||||
@@ -774,7 +865,7 @@ public class RuleServiceImpl
|
||||
// Create the action node
|
||||
ruleNodeRef = this.nodeService.createNode(
|
||||
getSavedRuleFolderRef(nodeRef),
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
ASSOC_CONTAINS,
|
||||
QName.createQName(RuleModel.RULE_MODEL_URI, ASSOC_NAME_RULES_PREFIX + GUID.generate()),
|
||||
RuleModel.TYPE_RULE).getChildRef();
|
||||
|
||||
@@ -817,7 +908,7 @@ public class RuleServiceImpl
|
||||
NodeRef ruleFolder = getSavedRuleFolderRef(nodeRef);
|
||||
if (ruleFolder != null)
|
||||
{
|
||||
List<ChildAssociationRef> assocs = this.runtimeNodeService.getChildAssocs(ruleFolder, RegexQNamePattern.MATCH_ALL, ASSOC_NAME_RULES_REGEX);
|
||||
List<ChildAssociationRef> assocs = this.runtimeNodeService.getChildAssocs(ruleFolder, MATCH_ALL, ASSOC_NAME_RULES_REGEX);
|
||||
List<ChildAssociationRef> orderedAssocs = new ArrayList<ChildAssociationRef>(assocs.size());
|
||||
ChildAssociationRef movedAssoc = null;
|
||||
for (ChildAssociationRef assoc : assocs)
|
||||
@@ -899,7 +990,7 @@ public class RuleServiceImpl
|
||||
{
|
||||
checkForLinkedRules(nodeRef);
|
||||
|
||||
if (permissionService.hasPermission(nodeRef, PermissionService.CHANGE_PERMISSIONS) == AccessStatus.ALLOWED)
|
||||
if (permissionService.hasPermission(nodeRef, PermissionService.CHANGE_PERMISSIONS) == ALLOWED)
|
||||
{
|
||||
if (nodeService.exists(nodeRef) && nodeService.hasAspect(nodeRef, RuleModel.ASPECT_RULES))
|
||||
{
|
||||
@@ -962,7 +1053,7 @@ public class RuleServiceImpl
|
||||
{
|
||||
checkForLinkedRules(nodeRef);
|
||||
|
||||
if (this.permissionService.hasPermission(nodeRef, PermissionService.CHANGE_PERMISSIONS) == AccessStatus.ALLOWED)
|
||||
if (this.permissionService.hasPermission(nodeRef, PermissionService.CHANGE_PERMISSIONS) == ALLOWED)
|
||||
{
|
||||
if (this.nodeService.exists(nodeRef) == true &&
|
||||
this.nodeService.hasAspect(nodeRef, RuleModel.ASPECT_RULES) == true)
|
||||
@@ -972,7 +1063,7 @@ public class RuleServiceImpl
|
||||
{
|
||||
List<ChildAssociationRef> ruleChildAssocs = this.nodeService.getChildAssocs(
|
||||
folder,
|
||||
RegexQNamePattern.MATCH_ALL, ASSOC_NAME_RULES_REGEX);
|
||||
MATCH_ALL, ASSOC_NAME_RULES_REGEX);
|
||||
for (ChildAssociationRef ruleChildAssoc : ruleChildAssocs)
|
||||
{
|
||||
this.nodeService.removeChild(folder, ruleChildAssoc.getChildRef());
|
||||
@@ -1322,7 +1413,7 @@ public class RuleServiceImpl
|
||||
{
|
||||
boolean result = true;
|
||||
if (this.nodeService.exists(actionedUponNodeRef)
|
||||
&& this.permissionService.hasPermission(actionedUponNodeRef, PermissionService.READ).equals(AccessStatus.ALLOWED))
|
||||
&& this.permissionService.hasPermission(actionedUponNodeRef, PermissionService.READ).equals(ALLOWED))
|
||||
{
|
||||
NodeRef copiedFrom = copyService.getOriginal(actionedUponNodeRef);
|
||||
if (logger.isDebugEnabled() == true)
|
||||
@@ -1523,6 +1614,12 @@ public class RuleServiceImpl
|
||||
return this.nodeService.getPrimaryParent(systemFolder).getParentRef();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeRef getOwningNodeRef(NodeRef ruleSet)
|
||||
{
|
||||
return nodeService.getPrimaryParent(ruleSet).getParentRef();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeRef getOwningNodeRef(final Action action)
|
||||
{
|
||||
@@ -1615,7 +1712,7 @@ public class RuleServiceImpl
|
||||
@Experimental
|
||||
public NodeRef getRuleSetNode(final NodeRef folderNodeRef)
|
||||
{
|
||||
return runtimeNodeService.getChildAssocs(folderNodeRef, RuleModel.ASSOC_RULE_FOLDER, RuleModel.ASSOC_RULE_FOLDER).stream()
|
||||
return runtimeNodeService.getChildAssocs(folderNodeRef, ASSOC_RULE_FOLDER, ASSOC_RULE_FOLDER).stream()
|
||||
.map(ChildAssociationRef::getChildRef)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
@@ -1625,7 +1722,10 @@ public class RuleServiceImpl
|
||||
@Experimental
|
||||
public boolean isRuleSetAssociatedWithFolder(final NodeRef ruleSetNodeRef, final NodeRef folderNodeRef)
|
||||
{
|
||||
return isChildOf(ruleSetNodeRef, RuleModel.ASSOC_RULE_FOLDER, folderNodeRef);
|
||||
List<ChildAssociationRef> associations = runtimeNodeService.getParentAssocs(ruleSetNodeRef, ASSOC_RULE_FOLDER, ASSOC_RULE_FOLDER);
|
||||
Set<NodeRef> associatedFolders = associations.stream().map(ChildAssociationRef::getParentRef).collect(Collectors.toSet());
|
||||
Set<NodeRef> supplyingFolders = new HashSet<>(getNodesSupplyingRuleSets(folderNodeRef));
|
||||
return !Sets.intersection(associatedFolders, supplyingFolders).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -25,54 +25,54 @@
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication.ldap;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Hashtable;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.naming.AuthenticationNotSupportedException;
|
||||
import javax.naming.CommunicationException;
|
||||
import javax.naming.Context;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.Attribute;
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.BasicAttribute;
|
||||
import javax.naming.directory.BasicAttributes;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.InitialDirContext;
|
||||
import javax.naming.ldap.Control;
|
||||
import javax.naming.ldap.InitialLdapContext;
|
||||
import javax.naming.ldap.LdapContext;
|
||||
import javax.naming.ldap.PagedResultsControl;
|
||||
import javax.naming.ldap.PagedResultsResponseControl;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.repo.security.authentication.AlfrescoSSLSocketFactory;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationDiagnostic;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Hashtable;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.naming.AuthenticationNotSupportedException;
|
||||
import javax.naming.CommunicationException;
|
||||
import javax.naming.Context;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.Attribute;
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.BasicAttribute;
|
||||
import javax.naming.directory.BasicAttributes;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.InitialDirContext;
|
||||
import javax.naming.ldap.Control;
|
||||
import javax.naming.ldap.InitialLdapContext;
|
||||
import javax.naming.ldap.LdapContext;
|
||||
import javax.naming.ldap.PagedResultsControl;
|
||||
import javax.naming.ldap.PagedResultsResponseControl;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.repo.cache.SimpleCache;
|
||||
import org.alfresco.repo.security.authentication.AlfrescoSSLSocketFactory;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationDiagnostic;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
public class LDAPInitialDirContextFactoryImpl implements LDAPInitialDirContextFactory, InitializingBean
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(LDAPInitialDirContextFactoryImpl.class);
|
||||
|
||||
private static Set<Map<String, String>> checkedEnvs = Collections.synchronizedSet(new HashSet<Map<String, String>>(
|
||||
11));
|
||||
private SimpleCache<String, Set<Map<String, String>>> ldapInitialDirContextCache;
|
||||
|
||||
private Map<String, String> defaultEnvironment = Collections.<String, String> emptyMap();
|
||||
private Map<String, String> authenticatedEnvironment = Collections.<String, String> emptyMap();
|
||||
@@ -80,6 +80,13 @@ public class LDAPInitialDirContextFactoryImpl implements LDAPInitialDirContextFa
|
||||
private String trustStorePath;
|
||||
private String trustStoreType;
|
||||
private String trustStorePassPhrase;
|
||||
|
||||
private boolean initialChecksEnabled = true;
|
||||
|
||||
private final String ANONYMOUS_CHECK = "anonymous_check";
|
||||
private final String SIMPLE_DN_CHECK = "simple_dn_check";
|
||||
private final String DN_CHECK = "dn_check";
|
||||
private final String PRINCIPAL_CHECK = "principal_check";
|
||||
|
||||
public String getTrustStorePath()
|
||||
{
|
||||
@@ -475,159 +482,202 @@ public class LDAPInitialDirContextFactoryImpl implements LDAPInitialDirContextFa
|
||||
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception
|
||||
{
|
||||
logger.debug("after Properties Set");
|
||||
// Check Anonymous bind
|
||||
|
||||
Hashtable<String, String> env = new Hashtable<String, String>(authenticatedEnvironment.size());
|
||||
env.putAll(authenticatedEnvironment);
|
||||
env.remove(Context.SECURITY_PRINCIPAL);
|
||||
env.remove(Context.SECURITY_CREDENTIALS);
|
||||
if (isSSLSocketFactoryRequired())
|
||||
{
|
||||
KeyStore trustStore = initTrustStore();
|
||||
AlfrescoSSLSocketFactory.initTrustedSSLSocketFactory(trustStore);
|
||||
env.put("java.naming.ldap.factory.socket", AlfrescoSSLSocketFactory.class.getName());
|
||||
}
|
||||
try
|
||||
{
|
||||
new InitialDirContext(env);
|
||||
|
||||
logger.warn("LDAP server supports anonymous bind " + env.get(Context.PROVIDER_URL));
|
||||
}
|
||||
catch (javax.naming.AuthenticationException ax)
|
||||
{
|
||||
|
||||
}
|
||||
catch (AuthenticationNotSupportedException e)
|
||||
{
|
||||
|
||||
}
|
||||
catch (NamingException nx)
|
||||
{
|
||||
logger.error("Unable to connect to LDAP Server; check LDAP configuration", nx);
|
||||
return;
|
||||
}
|
||||
|
||||
// Simple DN and password
|
||||
|
||||
env = new Hashtable<String, String>(authenticatedEnvironment.size());
|
||||
env.putAll(authenticatedEnvironment);
|
||||
env.put(Context.SECURITY_PRINCIPAL, "daftAsABrush");
|
||||
env.put(Context.SECURITY_CREDENTIALS, "daftAsABrush");
|
||||
if (isSSLSocketFactoryRequired())
|
||||
{
|
||||
KeyStore trustStore = initTrustStore();
|
||||
AlfrescoSSLSocketFactory.initTrustedSSLSocketFactory(trustStore);
|
||||
env.put("java.naming.ldap.factory.socket", AlfrescoSSLSocketFactory.class.getName());
|
||||
}
|
||||
try
|
||||
{
|
||||
|
||||
new InitialDirContext(env);
|
||||
|
||||
throw new AuthenticationException(
|
||||
"The ldap server at "
|
||||
+ env.get(Context.PROVIDER_URL)
|
||||
+ " falls back to use anonymous bind if invalid security credentials are presented. This is not supported.");
|
||||
}
|
||||
catch (javax.naming.AuthenticationException ax)
|
||||
{
|
||||
logger.info("LDAP server does not fall back to anonymous bind for a string uid and password at " + env.get(Context.PROVIDER_URL));
|
||||
}
|
||||
catch (AuthenticationNotSupportedException e)
|
||||
{
|
||||
logger.info("LDAP server does not fall back to anonymous bind for a string uid and password at " + env.get(Context.PROVIDER_URL));
|
||||
}
|
||||
catch (NamingException nx)
|
||||
{
|
||||
logger.info("LDAP server does not support simple string user ids and invalid credentials at "+ env.get(Context.PROVIDER_URL));
|
||||
}
|
||||
|
||||
// DN and password
|
||||
|
||||
env = new Hashtable<String, String>(authenticatedEnvironment.size());
|
||||
env.putAll(authenticatedEnvironment);
|
||||
env.put(Context.SECURITY_PRINCIPAL, "cn=daftAsABrush,dc=woof");
|
||||
env.put(Context.SECURITY_CREDENTIALS, "daftAsABrush");
|
||||
if (isSSLSocketFactoryRequired())
|
||||
{
|
||||
KeyStore trustStore = initTrustStore();
|
||||
AlfrescoSSLSocketFactory.initTrustedSSLSocketFactory(trustStore);
|
||||
env.put("java.naming.ldap.factory.socket", AlfrescoSSLSocketFactory.class.getName());
|
||||
}
|
||||
try
|
||||
{
|
||||
|
||||
new InitialDirContext(env);
|
||||
|
||||
throw new AuthenticationException(
|
||||
"The ldap server at "
|
||||
+ env.get(Context.PROVIDER_URL)
|
||||
+ " falls back to use anonymous bind if invalid security credentials are presented. This is not supported.");
|
||||
}
|
||||
catch (javax.naming.AuthenticationException ax)
|
||||
{
|
||||
logger.info("LDAP server does not fall back to anonymous bind for a simple dn and password at " + env.get(Context.PROVIDER_URL));
|
||||
}
|
||||
catch (AuthenticationNotSupportedException e)
|
||||
{
|
||||
logger.info("LDAP server does not fall back to anonymous bind for a simple dn and password at " + env.get(Context.PROVIDER_URL));
|
||||
}
|
||||
catch (NamingException nx)
|
||||
{
|
||||
logger.info("LDAP server does not support simple DN and invalid password at "+ env.get(Context.PROVIDER_URL));
|
||||
}
|
||||
|
||||
// Check more if we have a real principal we expect to work
|
||||
|
||||
String principal = defaultEnvironment.get(Context.SECURITY_PRINCIPAL);
|
||||
if (principal != null)
|
||||
{
|
||||
// Correct principal invalid password
|
||||
|
||||
env = new Hashtable<String, String>(authenticatedEnvironment.size());
|
||||
env.putAll(authenticatedEnvironment);
|
||||
env.put(Context.SECURITY_PRINCIPAL, principal);
|
||||
env.put(Context.SECURITY_CREDENTIALS, "sdasdasdasdasd123123123");
|
||||
if (isSSLSocketFactoryRequired())
|
||||
{
|
||||
KeyStore trustStore = initTrustStore();
|
||||
AlfrescoSSLSocketFactory.initTrustedSSLSocketFactory(trustStore);
|
||||
env.put("java.naming.ldap.factory.socket", AlfrescoSSLSocketFactory.class.getName());
|
||||
}
|
||||
if (!checkedEnvs.contains(env))
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
new InitialDirContext(env);
|
||||
|
||||
throw new AuthenticationException(
|
||||
"The ldap server at "
|
||||
+ env.get(Context.PROVIDER_URL)
|
||||
+ " falls back to use anonymous bind for a known principal if invalid security credentials are presented. This is not supported.");
|
||||
}
|
||||
catch (javax.naming.AuthenticationException ax)
|
||||
{
|
||||
logger.info("LDAP server does not fall back to anonymous bind for known principal and invalid credentials at " + env.get(Context.PROVIDER_URL));
|
||||
}
|
||||
catch (AuthenticationNotSupportedException e)
|
||||
{
|
||||
logger.info("LDAP server does not support the required authentication mechanism");
|
||||
}
|
||||
catch (NamingException nx)
|
||||
{
|
||||
// already done
|
||||
}
|
||||
// Record this environment as checked so that we don't check it again on further restarts / other subsystem
|
||||
// instances
|
||||
checkedEnvs.add(env);
|
||||
}
|
||||
}
|
||||
public void afterPropertiesSet() throws Exception
|
||||
{
|
||||
logger.debug("after Properties Set");
|
||||
|
||||
if (initialChecksEnabled)
|
||||
{
|
||||
checkAnonymousBind();
|
||||
checkSimpleDnAndPassword();
|
||||
checkDnAndPassword();
|
||||
checkPrincipal();
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.info("LDAP checks are disabled");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Anonymous bind
|
||||
*/
|
||||
private void checkAnonymousBind()
|
||||
{
|
||||
Hashtable<String, String> env = new Hashtable<String, String>(authenticatedEnvironment.size());
|
||||
env.putAll(authenticatedEnvironment);
|
||||
env.remove(Context.SECURITY_PRINCIPAL);
|
||||
env.remove(Context.SECURITY_CREDENTIALS);
|
||||
|
||||
if (isSSLSocketFactoryRequired())
|
||||
{
|
||||
KeyStore trustStore = initTrustStore();
|
||||
AlfrescoSSLSocketFactory.initTrustedSSLSocketFactory(trustStore);
|
||||
env.put("java.naming.ldap.factory.socket", AlfrescoSSLSocketFactory.class.getName());
|
||||
}
|
||||
|
||||
if (!isCached(ANONYMOUS_CHECK, env))
|
||||
{
|
||||
logger.debug("Starting check: Anonymous bind");
|
||||
|
||||
try
|
||||
{
|
||||
new InitialDirContext(env);
|
||||
|
||||
logger.warn("LDAP server supports anonymous bind " + env.get(Context.PROVIDER_URL));
|
||||
}
|
||||
catch (javax.naming.AuthenticationException | AuthenticationNotSupportedException e)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
catch (NamingException nx)
|
||||
{
|
||||
logger.error("Unable to connect to LDAP Server; check LDAP configuration", nx);
|
||||
}
|
||||
|
||||
addToCache(ANONYMOUS_CHECK, env);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check simple DN and password
|
||||
*/
|
||||
private void checkSimpleDnAndPassword()
|
||||
{
|
||||
Hashtable<String, String> env = new Hashtable<String, String>(authenticatedEnvironment.size());
|
||||
env.putAll(authenticatedEnvironment);
|
||||
env.put(Context.SECURITY_PRINCIPAL, "daftAsABrush");
|
||||
env.put(Context.SECURITY_CREDENTIALS, "daftAsABrush");
|
||||
|
||||
if (isSSLSocketFactoryRequired())
|
||||
{
|
||||
KeyStore trustStore = initTrustStore();
|
||||
AlfrescoSSLSocketFactory.initTrustedSSLSocketFactory(trustStore);
|
||||
env.put("java.naming.ldap.factory.socket", AlfrescoSSLSocketFactory.class.getName());
|
||||
}
|
||||
|
||||
if (!isCached(SIMPLE_DN_CHECK, env))
|
||||
{
|
||||
logger.debug("Starting check: Simple DN and Password");
|
||||
|
||||
try
|
||||
{
|
||||
new InitialDirContext(env);
|
||||
|
||||
throw new AuthenticationException("The ldap server at " + env.get(Context.PROVIDER_URL)
|
||||
+ " falls back to use anonymous bind if invalid security credentials are presented. This is not supported.");
|
||||
}
|
||||
catch (javax.naming.AuthenticationException | AuthenticationNotSupportedException e)
|
||||
{
|
||||
logger.info("LDAP server does not fall back to anonymous bind for a string uid and password at "
|
||||
+ env.get(Context.PROVIDER_URL));
|
||||
}
|
||||
catch (NamingException nx)
|
||||
{
|
||||
logger.info("LDAP server does not support simple string user ids and invalid credentials at "
|
||||
+ env.get(Context.PROVIDER_URL));
|
||||
}
|
||||
|
||||
addToCache(SIMPLE_DN_CHECK, env);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check DN and Password
|
||||
*/
|
||||
private void checkDnAndPassword()
|
||||
{
|
||||
Hashtable<String, String> env = new Hashtable<String, String>(authenticatedEnvironment.size());
|
||||
env.putAll(authenticatedEnvironment);
|
||||
env.put(Context.SECURITY_PRINCIPAL, "cn=daftAsABrush,dc=woof");
|
||||
env.put(Context.SECURITY_CREDENTIALS, "daftAsABrush");
|
||||
|
||||
if (isSSLSocketFactoryRequired())
|
||||
{
|
||||
KeyStore trustStore = initTrustStore();
|
||||
AlfrescoSSLSocketFactory.initTrustedSSLSocketFactory(trustStore);
|
||||
env.put("java.naming.ldap.factory.socket", AlfrescoSSLSocketFactory.class.getName());
|
||||
}
|
||||
|
||||
if (!isCached(DN_CHECK, env))
|
||||
{
|
||||
logger.debug("Starting check: DN and Password");
|
||||
|
||||
try
|
||||
{
|
||||
new InitialDirContext(env);
|
||||
|
||||
throw new AuthenticationException("The ldap server at " + env.get(Context.PROVIDER_URL)
|
||||
+ " falls back to use anonymous bind if invalid security credentials are presented. This is not supported.");
|
||||
}
|
||||
catch (javax.naming.AuthenticationException | AuthenticationNotSupportedException e)
|
||||
{
|
||||
logger.info("LDAP server does not fall back to anonymous bind for a simple dn and password at "
|
||||
+ env.get(Context.PROVIDER_URL));
|
||||
}
|
||||
catch (NamingException nx)
|
||||
{
|
||||
logger.info("LDAP server does not support simple DN and invalid password at " + env.get(Context.PROVIDER_URL));
|
||||
}
|
||||
|
||||
addToCache(DN_CHECK, env);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check more if we have a real principal we expect to work
|
||||
*/
|
||||
private void checkPrincipal()
|
||||
{
|
||||
String principal = defaultEnvironment.get(Context.SECURITY_PRINCIPAL);
|
||||
|
||||
if (principal != null)
|
||||
{
|
||||
// Correct principal invalid password
|
||||
|
||||
Hashtable<String, String> env = new Hashtable<String, String>(authenticatedEnvironment.size());
|
||||
env.putAll(authenticatedEnvironment);
|
||||
env.put(Context.SECURITY_PRINCIPAL, principal);
|
||||
env.put(Context.SECURITY_CREDENTIALS, "sdasdasdasdasd123123123");
|
||||
|
||||
if (isSSLSocketFactoryRequired())
|
||||
{
|
||||
KeyStore trustStore = initTrustStore();
|
||||
AlfrescoSSLSocketFactory.initTrustedSSLSocketFactory(trustStore);
|
||||
env.put("java.naming.ldap.factory.socket", AlfrescoSSLSocketFactory.class.getName());
|
||||
}
|
||||
|
||||
if (!isCached(PRINCIPAL_CHECK, env))
|
||||
{
|
||||
logger.debug("Starting check: Principal");
|
||||
|
||||
try
|
||||
{
|
||||
new InitialDirContext(env);
|
||||
|
||||
throw new AuthenticationException("The ldap server at " + env.get(Context.PROVIDER_URL)
|
||||
+ " falls back to use anonymous bind for a known principal if invalid security credentials are presented. This is not supported.");
|
||||
}
|
||||
catch (javax.naming.AuthenticationException ax)
|
||||
{
|
||||
logger.info("LDAP server does not fall back to anonymous bind for known principal and invalid credentials at "
|
||||
+ env.get(Context.PROVIDER_URL));
|
||||
}
|
||||
catch (AuthenticationNotSupportedException e)
|
||||
{
|
||||
logger.info("LDAP server does not support the required authentication mechanism");
|
||||
}
|
||||
catch (NamingException nx)
|
||||
{
|
||||
// already done
|
||||
}
|
||||
|
||||
// Record this environment as checked so that we don't check it again on further restarts / other
|
||||
// subsystem instances
|
||||
addToCache(PRINCIPAL_CHECK, env);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if it required to use custom SSL socket factory with custom trustStore.
|
||||
@@ -704,5 +754,69 @@ public class LDAPInitialDirContextFactoryImpl implements LDAPInitialDirContextFa
|
||||
throw new AlfrescoRuntimeException("The certificates cannot be loaded from truststore.", ce);
|
||||
}
|
||||
return ks;
|
||||
}
|
||||
}
|
||||
|
||||
private void addToCache(String key, Map<String, String> value)
|
||||
{
|
||||
Set<Map<String, String>> envs = ldapInitialDirContextCache.get(key);
|
||||
|
||||
if (envs == null)
|
||||
{
|
||||
envs = Collections.synchronizedSet(new HashSet<Map<String, String>>(11));
|
||||
}
|
||||
|
||||
if (!envs.contains(value))
|
||||
{
|
||||
envs.add(value);
|
||||
}
|
||||
|
||||
if (!ldapInitialDirContextCache.contains(key))
|
||||
{
|
||||
ldapInitialDirContextCache.put(key, envs);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeFromCache(String key, Map<String, String> value)
|
||||
{
|
||||
if (ldapInitialDirContextCache != null && ldapInitialDirContextCache.contains(key))
|
||||
{
|
||||
Set<Map<String, String>> envs = ldapInitialDirContextCache.get(key);
|
||||
if (envs != null && envs.contains(value))
|
||||
{
|
||||
envs.remove(value);
|
||||
if (envs.isEmpty())
|
||||
{
|
||||
ldapInitialDirContextCache.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isCached(String key, Map<String, String> value)
|
||||
{
|
||||
boolean isCached = false;
|
||||
|
||||
if (ldapInitialDirContextCache != null && ldapInitialDirContextCache.contains(key))
|
||||
{
|
||||
Set<Map<String, String>> envs = ldapInitialDirContextCache.get(key);
|
||||
if (envs != null && envs.contains(value))
|
||||
{
|
||||
isCached = true;
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug("LDAP check: " + key + " / isCached: " + (isCached ? "yes" : "no"));
|
||||
|
||||
return isCached;
|
||||
}
|
||||
|
||||
public void setLdapInitialDirContextCache(SimpleCache<String, Set<Map<String, String>>> cache)
|
||||
{
|
||||
this.ldapInitialDirContextCache = cache;
|
||||
}
|
||||
|
||||
public void setInitialChecksEnabled(boolean initialChecksEnabled)
|
||||
{
|
||||
this.initialChecksEnabled = initialChecksEnabled;
|
||||
}
|
||||
}
|
||||
|
@@ -2,11 +2,11 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2019 Alfresco Software Limited
|
||||
* 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
|
||||
* 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
|
||||
@@ -44,7 +44,7 @@ import org.alfresco.service.cmr.thumbnail.ThumbnailException;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.transform.client.registry.TransformServiceRegistry;
|
||||
import org.alfresco.transform.registry.TransformServiceRegistry;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
|
@@ -51,6 +51,7 @@ import org.alfresco.service.license.LicenseIntegrityException;
|
||||
import org.alfresco.util.LockHelper.LockTryException;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.ibatis.exceptions.PersistenceException;
|
||||
import org.apache.ibatis.exceptions.TooManyResultsException;
|
||||
import org.springframework.aop.MethodBeforeAdvice;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
@@ -105,7 +106,8 @@ public class RetryingTransactionHelper
|
||||
DataIntegrityViolationException.class,
|
||||
LicenseIntegrityException.class,
|
||||
TooManyResultsException.class, // Expected one result but found multiple (bad key alert)
|
||||
LockTryException.class
|
||||
LockTryException.class,
|
||||
PersistenceException.class
|
||||
};
|
||||
|
||||
List<Class<?>> retryExceptions = new ArrayList<Class<?>>();
|
||||
|
@@ -215,7 +215,30 @@ public interface RuleService
|
||||
*/
|
||||
@Auditable(parameters = {"nodeRef"})
|
||||
public int countRules(NodeRef nodeRef);
|
||||
|
||||
|
||||
/**
|
||||
* Traverse the folder hierarchy find all the folder nodes that could supply rules by inheritance.
|
||||
*
|
||||
* @param nodeRef The starting node ref.
|
||||
* @return A list of node refs, starting with the first parent of the first parent of ... and ending with the object generated by the
|
||||
* given node ref.
|
||||
*/
|
||||
@Auditable (parameters = { "nodeRef" })
|
||||
@Experimental
|
||||
List<NodeRef> getNodesSupplyingRuleSets(NodeRef nodeRef);
|
||||
|
||||
/**
|
||||
* Get a list of folders inheriting the specified rule set.
|
||||
*
|
||||
* @param ruleSet The rule set node.
|
||||
* @param maxFoldersToReturn A limit on the number of folders to return (since otherwise this could traverse a very large proportion of
|
||||
* the repository.
|
||||
* @return The list of the specified
|
||||
*/
|
||||
@Auditable (parameters = { "ruleSet", "maxFoldersToReturn" })
|
||||
@Experimental
|
||||
List<NodeRef> getFoldersInheritingRuleSet(NodeRef ruleSet, int maxFoldersToReturn);
|
||||
|
||||
/**
|
||||
* Get the rule given its node reference
|
||||
*
|
||||
@@ -300,7 +323,17 @@ public interface RuleService
|
||||
*/
|
||||
@Auditable(parameters = {"action"})
|
||||
public NodeRef getOwningNodeRef(Action action);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the owning node reference for a rule.
|
||||
*
|
||||
* @param ruleSet The rule set node.
|
||||
* @return the owning node reference
|
||||
*/
|
||||
@Auditable (parameters = { "ruleSet" })
|
||||
@Experimental
|
||||
NodeRef getOwningNodeRef(NodeRef ruleSet);
|
||||
|
||||
/**
|
||||
* Indicates whether the passed rule node reference is linked to another
|
||||
* rule node.
|
||||
@@ -342,7 +375,7 @@ public interface RuleService
|
||||
NodeRef getRuleSetNode(final NodeRef folderNodeRef);
|
||||
|
||||
/**
|
||||
* Check if rule set's associated parent matches folder node.
|
||||
* Check if rule set is associated (owned/linked/inherited) with the given folder node.
|
||||
*
|
||||
* @param ruleSetNodeRef - node reference of a rule set
|
||||
* @param folderNodeRef - node reference of a folder
|
||||
@@ -364,7 +397,7 @@ public interface RuleService
|
||||
boolean isRuleAssociatedWithRuleSet(final NodeRef ruleNodeRef, final NodeRef ruleSetNodeRef);
|
||||
|
||||
/**
|
||||
* Check if others folders are linked to rule set.
|
||||
* Check if other folders are linked to rule set.
|
||||
*
|
||||
* @param ruleSetNodeRef - node reference of a rule set
|
||||
* @return true if others folders are linked to rule set
|
||||
|
@@ -23,15 +23,15 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.transform.client.registry;
|
||||
package org.alfresco.transform.registry;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.repo.content.transform.LocalPassThroughTransform;
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
import org.alfresco.transform.client.model.config.TransformConfig;
|
||||
import org.alfresco.transform.client.model.config.Transformer;
|
||||
import org.alfresco.transform.config.TransformConfig;
|
||||
import org.alfresco.transform.config.Transformer;
|
||||
import org.alfresco.util.ConfigFileFinder;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.http.HttpEntity;
|
||||
@@ -47,7 +47,7 @@ import java.io.StringReader;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.alfresco.transform.client.util.RequestParamMap.ENDPOINT_TRANSFORM_CONFIG_LATEST;
|
||||
import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_TRANSFORM_CONFIG_LATEST;
|
||||
|
||||
/**
|
||||
* This class reads multiple T-Engine config and local files and registers as if they were all
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
* 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
|
||||
@@ -23,9 +23,12 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.transform.client.registry;
|
||||
package org.alfresco.transform.registry;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.alfresco.transform.registry.AbstractTransformRegistry;
|
||||
import org.alfresco.transform.registry.SupportedTransform;
|
||||
import org.alfresco.transform.registry.TransformCache;
|
||||
import org.alfresco.util.ConfigScheduler;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
import org.alfresco.util.ShutdownIndicator;
|
||||
@@ -38,7 +41,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.alfresco.transform.client.registry.TransformRegistryHelper.retrieveTransformListBySize;
|
||||
import static org.alfresco.transform.registry.TransformRegistryHelper.retrieveTransformListBySize;
|
||||
|
||||
/**
|
||||
* Used by clients to work out if a transformation is supported by the Transform Service.
|
@@ -506,4 +506,12 @@
|
||||
<bean name="queryAcceleratorCache" factory-bean="cacheFactory" factory-method="createCache">
|
||||
<constructor-arg value="cache.queryAcceleratorCache"/>
|
||||
</bean>
|
||||
|
||||
<!-- ===================================== -->
|
||||
<!-- LDAP Initial Dir Context cache -->
|
||||
<!-- ===================================== -->
|
||||
|
||||
<bean name="ldapInitialDirContextCache" factory-bean="cacheFactory" factory-method="createCache">
|
||||
<constructor-arg value="cache.ldapInitialDirContextCache"/>
|
||||
</bean>
|
||||
</beans>
|
||||
|
@@ -699,3 +699,15 @@ cache.queryAcceleratorCache.backup-count=1
|
||||
cache.queryAcceleratorCache.eviction-policy=NONE
|
||||
cache.queryAcceleratorCache.merge-policy=com.hazelcast.map.merge.LatestUpdateMapMergePolicy
|
||||
cache.queryAcceleratorCache.readBackupData=false
|
||||
|
||||
#
|
||||
# LDAP initial dir context checks cluster cache
|
||||
#
|
||||
cache.ldapInitialDirContextCache.maxItems=100
|
||||
cache.ldapInitialDirContextCache.timeToLiveSeconds=0
|
||||
cache.ldapInitialDirContextCache.maxIdleSeconds=0
|
||||
cache.ldapInitialDirContextCache.cluster.type=fully-distributed
|
||||
cache.ldapInitialDirContextCache.backup-count=1
|
||||
cache.ldapInitialDirContextCache.eviction-policy=NONE
|
||||
cache.ldapInitialDirContextCache.merge-policy=com.hazelcast.map.merge.LatestUpdateMapMergePolicy
|
||||
cache.ldapInitialDirContextCache.readBackupData=false
|
@@ -119,7 +119,12 @@
|
||||
-->
|
||||
|
||||
<bean id="ldapInitialDirContextFactory" class="org.alfresco.repo.security.authentication.ldap.LDAPInitialDirContextFactoryImpl">
|
||||
|
||||
<property name="ldapInitialDirContextCache">
|
||||
<ref bean="ldapInitialDirContextCache" />
|
||||
</property>
|
||||
<property name="initialChecksEnabled">
|
||||
<value>${ldap.authentication.initial.checks.enabled}</value>
|
||||
</property>
|
||||
<property name="trustStorePath">
|
||||
<value>${ldap.authentication.truststore.path}</value>
|
||||
</property>
|
||||
|
@@ -175,3 +175,6 @@ ldap.synchronization.userAccountStatusProperty=userAccountControl
|
||||
|
||||
# The Account Status Interpreter bean name
|
||||
ldap.synchronization.userAccountStatusInterpreter=ldapadUserAccountStatusInterpreter
|
||||
|
||||
# Allows to enable or disable LDAP-AD initial checks (anonymous bind, simple dn, dn and principal)
|
||||
ldap.authentication.initial.checks.enabled=true
|
@@ -192,3 +192,6 @@ ldap.synchronization.disabledAccountPropertyValueCanBeNull=true
|
||||
|
||||
# The Account Status Interpreter bean name
|
||||
ldap.synchronization.userAccountStatusInterpreter=ldapUserAccountStatusInterpreter
|
||||
|
||||
# Allows to enable or disable LDAP initial checks (anonymous bind, simple dn, dn and principal)
|
||||
ldap.authentication.initial.checks.enabled=true
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2017 Alfresco Software Limited
|
||||
* 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
|
||||
@@ -50,7 +50,7 @@ import org.junit.runners.Suite;
|
||||
org.alfresco.repo.event2.RepoEvent2ITSuite.class,
|
||||
|
||||
// Requires running transformers
|
||||
org.alfresco.transform.client.registry.LocalTransformServiceRegistryConfigTest.class,
|
||||
org.alfresco.transform.registry.LocalTransformServiceRegistryConfigTest.class,
|
||||
org.alfresco.repo.rendition2.RenditionService2IntegrationTest.class,
|
||||
org.alfresco.repo.rendition2.LocalTransformServiceRegistryIntegrationTest.class,
|
||||
org.alfresco.repo.rendition2.LocalTransformClientIntegrationTest.class,
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||
* 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
|
||||
@@ -58,7 +58,7 @@ import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.test_category.BaseSpringTestsCategory;
|
||||
import org.alfresco.transform.client.registry.TransformServiceRegistry;
|
||||
import org.alfresco.transform.registry.TransformServiceRegistry;
|
||||
import org.alfresco.util.BaseSpringTest;
|
||||
import org.alfresco.util.GUID;
|
||||
import org.junit.After;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user