mirror of
				https://github.com/Alfresco/alfresco-community-repo.git
				synced 2025-10-29 15:21:53 +00:00 
			
		
		
		
	Compare commits
	
		
			60 Commits
		
	
	
		
			20.19
			...
			dev-swapni
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					01d907a3e5 | ||
| 
						 | 
					9ec4323b76 | ||
| 
						 | 
					c954f87706 | ||
| 
						 | 
					6572baf8e1 | ||
| 
						 | 
					f295838c66 | ||
| 
						 | 
					1be88222e1 | ||
| 
						 | 
					ba7be5999b | ||
| 
						 | 
					8503b2c96c | ||
| 
						 | 
					f43806b9f4 | ||
| 
						 | 
					1eebb8ec12 | ||
| 
						 | 
					008b340851 | ||
| 
						 | 
					6d3e249149 | ||
| 
						 | 
					bf276c60d6 | ||
| 
						 | 
					54be23513a | ||
| 
						 | 
					fa0fdff8d4 | ||
| 
						 | 
					c37b26e678 | ||
| 
						 | 
					b5e13e253a | ||
| 
						 | 
					5b5164420f | ||
| 
						 | 
					17c09efb93 | ||
| 
						 | 
					f96304bd28 | ||
| 
						 | 
					499f679c8c | ||
| 
						 | 
					80c6a0127d | ||
| 
						 | 
					74e44acb1c | ||
| 
						 | 
					f4d66debea | ||
| 
						 | 
					af838043c9 | ||
| 
						 | 
					1245647a9f | ||
| 
						 | 
					fe35f312bb | ||
| 
						 | 
					a5f16f1b11 | ||
| 
						 | 
					38a9f6d3e1 | ||
| 
						 | 
					dc512e5ab0 | ||
| 
						 | 
					5c8db99231 | ||
| 
						 | 
					e39a97ed8d | ||
| 
						 | 
					ad0ad081c6 | ||
| 
						 | 
					8b9513ca8f | ||
| 
						 | 
					5b3582c051 | ||
| 
						 | 
					ccba1768bd | ||
| 
						 | 
					f03790e278 | ||
| 
						 | 
					2c979ea71e | ||
| 
						 | 
					227c74a8bd | ||
| 
						 | 
					24aa64c165 | ||
| 
						 | 
					183873166c | ||
| 
						 | 
					1c9419d635 | ||
| 
						 | 
					17b04d7321 | ||
| 
						 | 
					fe5faa3263 | ||
| 
						 | 
					63b0ff8cf4 | ||
| 
						 | 
					15c99b0c10 | ||
| 
						 | 
					0f24f453c8 | ||
| 
						 | 
					03ce7e37d4 | ||
| 
						 | 
					1a5740eec1 | ||
| 
						 | 
					f55602842d | ||
| 
						 | 
					7819e29bcc | ||
| 
						 | 
					91031ca72a | ||
| 
						 | 
					32314480a1 | ||
| 
						 | 
					f49b7a393f | ||
| 
						 | 
					d32ba12405 | ||
| 
						 | 
					7430c80a41 | ||
| 
						 | 
					af2c11063b | ||
| 
						 | 
					0d74540b2b | ||
| 
						 | 
					d68ceb1a4b | ||
| 
						 | 
					379f65db0d | 
@@ -7,7 +7,7 @@
 | 
			
		||||
   <parent>
 | 
			
		||||
      <groupId>org.alfresco</groupId>
 | 
			
		||||
      <artifactId>alfresco-community-repo-amps</artifactId>
 | 
			
		||||
      <version>20.19</version>
 | 
			
		||||
      <version>20.28-SNAPSHOT</version>
 | 
			
		||||
   </parent>
 | 
			
		||||
 | 
			
		||||
   <modules>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
   <parent>
 | 
			
		||||
      <groupId>org.alfresco</groupId>
 | 
			
		||||
      <artifactId>alfresco-governance-services-community-parent</artifactId>
 | 
			
		||||
      <version>20.19</version>
 | 
			
		||||
      <version>20.28-SNAPSHOT</version>
 | 
			
		||||
   </parent>
 | 
			
		||||
 | 
			
		||||
   <modules>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
   <parent>
 | 
			
		||||
      <groupId>org.alfresco</groupId>
 | 
			
		||||
      <artifactId>alfresco-governance-services-automation-community-repo</artifactId>
 | 
			
		||||
      <version>20.19</version>
 | 
			
		||||
      <version>20.28-SNAPSHOT</version>
 | 
			
		||||
   </parent>
 | 
			
		||||
 | 
			
		||||
   <build>
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,118 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%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.rules;
 | 
			
		||||
 | 
			
		||||
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.requests.gscore.api.RecordCategoryAPI;
 | 
			
		||||
import org.alfresco.rest.rm.community.requests.gscore.api.RecordFolderAPI;
 | 
			
		||||
import org.alfresco.rest.rm.community.requests.gscore.api.RecordsAPI;
 | 
			
		||||
import org.alfresco.rest.rm.community.smoke.CreateCategoriesTests;
 | 
			
		||||
import org.alfresco.rest.v0.RulesAPI;
 | 
			
		||||
import org.alfresco.test.AlfrescoTest;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.testng.annotations.Test;
 | 
			
		||||
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
 | 
			
		||||
import static org.alfresco.rest.core.v0.BaseAPI.NODE_PREFIX;
 | 
			
		||||
import static org.alfresco.rest.rm.community.base.TestData.ELECTRONIC_RECORD_NAME;
 | 
			
		||||
import static org.alfresco.rest.rm.community.base.TestData.NONELECTRONIC_RECORD_NAME;
 | 
			
		||||
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.rest.rm.community.utils.FilePlanComponentsUtil.*;
 | 
			
		||||
import static org.alfresco.utility.data.RandomData.getRandomName;
 | 
			
		||||
import static org.alfresco.utility.report.log.Step.STEP;
 | 
			
		||||
import static org.springframework.http.HttpStatus.*;
 | 
			
		||||
 | 
			
		||||
public class CopyToRuleOnFoldersTest extends BaseRMRestTest {
 | 
			
		||||
 | 
			
		||||
    private RecordCategory category;
 | 
			
		||||
    private RecordCategoryChild folder1,folder2;
 | 
			
		||||
    private final static String title = "Run in background";
 | 
			
		||||
    private final String TEST_PREFIX = generateTestPrefix(CopyToRuleOnFoldersTest.class);
 | 
			
		||||
    private final String RM_ADMIN = TEST_PREFIX + "rm_admin";
 | 
			
		||||
    private final String electronicRecord = TEST_PREFIX + "record_electronic_for_copyTo";
 | 
			
		||||
    private final String nonElectronicRecord = TEST_PREFIX + "record_non_electronic_for_copyTo";
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private RulesAPI rulesAPI;
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    @AlfrescoTest(jira = "RM-2994")
 | 
			
		||||
    public void copyToRuleOnFoldersTest()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        RuleDefinition ruleDefinition = RuleDefinition.createNewRule().title("name").description("description1")
 | 
			
		||||
            .runInBackground(true).title(title)
 | 
			
		||||
            .actions(Collections.singletonList(ActionsOnRule.COPY_TO.getActionValue()));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        STEP("Create the RM site if doesn't exist");
 | 
			
		||||
        createRMSiteIfNotExists();
 | 
			
		||||
 | 
			
		||||
        STEP("Create record categories and record folders");
 | 
			
		||||
        category= createRootCategory(getRandomName("recordCategory"));
 | 
			
		||||
        String folder1 = createCategoryFolderInFilePlan().getId();
 | 
			
		||||
        String folder2 = createCategoryFolderInFilePlan().getId();
 | 
			
		||||
 | 
			
		||||
        // create a rule on folder
 | 
			
		||||
        rulesAPI.createRule(getAdminUser().getUsername(), getAdminUser().getPassword(), NODE_PREFIX + folder1, ruleDefinition);
 | 
			
		||||
 | 
			
		||||
        // create electronic record in record folder
 | 
			
		||||
        String electronicRecordId = createElectronicRecord(folder1, ELECTRONIC_RECORD_NAME).getId();
 | 
			
		||||
        assertStatusCode(CREATED);
 | 
			
		||||
 | 
			
		||||
        // create non-electronic record in record folder
 | 
			
		||||
        String nonElectronicRecord = createElectronicRecord(folder1, NONELECTRONIC_RECORD_NAME).getId();
 | 
			
		||||
        assertStatusCode(CREATED);
 | 
			
		||||
 | 
			
		||||
        // Move the electronic and non-electronic records from "Category with records"> "Folder with rule"
 | 
			
		||||
        // to "Copy Category with records" > "Folder with rule"
 | 
			
		||||
       getRestAPIFactory().getNodeAPI(toContentModel(folder1)).copy(createBodyForMoveCopy(category.getId()));
 | 
			
		||||
        getRestAPIFactory().getNodeAPI(toContentModel( electronicRecord)).move(createBodyForMoveCopy(folder2));
 | 
			
		||||
        getRestAPIFactory().getNodeAPI(toContentModel( nonElectronicRecord)).move(createBodyForMoveCopy(folder2));
 | 
			
		||||
 | 
			
		||||
        RecordsAPI recordsAPI = getRestAPIFactory().getRecordsAPI();
 | 
			
		||||
        // Delete the record category
 | 
			
		||||
        RecordCategoryAPI recordCategoryAPI = getRestAPIFactory().getRecordCategoryAPI();
 | 
			
		||||
        String recordCategoryId = category.getId();
 | 
			
		||||
        recordCategoryAPI.deleteRecordCategory(recordCategoryId);
 | 
			
		||||
        recordsAPI.deleteRecord(electronicRecord);
 | 
			
		||||
        recordsAPI.deleteRecord(nonElectronicRecord);
 | 
			
		||||
        assertStatusCode(NO_CONTENT);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,229 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%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.rules;
 | 
			
		||||
 | 
			
		||||
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.rules.ActionsOnRule;
 | 
			
		||||
import org.alfresco.rest.rm.community.model.rules.RuleDefinition;
 | 
			
		||||
import org.alfresco.rest.rm.community.model.unfiledcontainer.UnfiledContainerChildEntry;
 | 
			
		||||
import org.alfresco.rest.rm.community.model.user.UserRoles;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.rest.rm.community.requests.gscore.api.UnfiledContainerAPI;
 | 
			
		||||
import org.alfresco.rest.rm.community.smoke.FileAsRecordTests;
 | 
			
		||||
import org.alfresco.rest.v0.RulesAPI;
 | 
			
		||||
import org.alfresco.rest.v0.service.RoleService;
 | 
			
		||||
import org.alfresco.test.AlfrescoTest;
 | 
			
		||||
import org.alfresco.utility.model.FileModel;
 | 
			
		||||
import org.alfresco.utility.model.FolderModel;
 | 
			
		||||
import org.alfresco.utility.model.UserModel;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.testng.annotations.AfterClass;
 | 
			
		||||
import org.testng.annotations.BeforeClass;
 | 
			
		||||
import org.testng.annotations.Test;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
import static org.alfresco.rest.core.v0.BaseAPI.NODE_PREFIX;
 | 
			
		||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.FILE_PLAN_ALIAS;
 | 
			
		||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.UNFILED_RECORDS_CONTAINER_ALIAS;
 | 
			
		||||
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.http.HttpStatus.CREATED;
 | 
			
		||||
 | 
			
		||||
@AlfrescoTest (jira = "APPS-36")
 | 
			
		||||
public class FileAsRecordRuleTests extends BaseRMRestTest
 | 
			
		||||
{
 | 
			
		||||
    private UserModel nonRMUser, rmManager;
 | 
			
		||||
    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);
 | 
			
		||||
    private FolderModel testFolder;
 | 
			
		||||
    private FileModel document,inPlaceRecord;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private RoleService roleService;
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private RulesAPI rulesAPI;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create preconditions:
 | 
			
		||||
     * 1. RM site is created
 | 
			
		||||
     * 2. Two users: user without RM role and a user with RM manager role
 | 
			
		||||
     * 3. Two Record categories with one folder each
 | 
			
		||||
     * 4. User with RM MANAGER role has Filling permission over one category
 | 
			
		||||
     * 5. A collaboration folder with rule set to declare and file as record to a record folder
 | 
			
		||||
     **/
 | 
			
		||||
    @BeforeClass(alwaysRun = true)
 | 
			
		||||
    public void preconditionForDeclareFileAsRecordRuleTests()
 | 
			
		||||
    {
 | 
			
		||||
        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 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);
 | 
			
		||||
 | 
			
		||||
        STEP("Create a collaboration folder with a rule set to declare and file as record to a record folder");
 | 
			
		||||
        RecordCategoryChild folderWithRule = createFolder(recordCategory.getId(), getRandomName("recordFolder"));
 | 
			
		||||
        RuleDefinition ruleDefinition = RuleDefinition.createNewRule().title("name").description("description")
 | 
			
		||||
            .applyToChildren(true)
 | 
			
		||||
            .actions(Collections.singletonList(ActionsOnRule.DECLARE_AS_RECORD.getActionValue()));
 | 
			
		||||
        rulesAPI.createRule(getAdminUser().getUsername(), getAdminUser().getPassword(), NODE_PREFIX + folderWithRule.getId(), ruleDefinition);
 | 
			
		||||
 | 
			
		||||
        assertStatusCode(CREATED);
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * Given I am a user that can create a rule on a folder in a collaboration site
 | 
			
		||||
     * When I am creating the rule
 | 
			
		||||
     * Then I have the option of adding a "Declare and File as Record" action to the rule
 | 
			
		||||
     * <p>
 | 
			
		||||
     * Given I am creating a rule
 | 
			
		||||
     * When I add the "Declare and File as Record" action to the rule
 | 
			
		||||
     * Then I am able to select the record folder I want the declared record to be filed to
 | 
			
		||||
     * <p>
 | 
			
		||||
     * Given I am configuring a "Declare and File as Record" action within a rule
 | 
			
		||||
     * And I have at least one records management role (eg RM User)
 | 
			
		||||
     * When I am selecting the record folder location to file the declared record to
 | 
			
		||||
     * Then I see the record folders in the file plan that I have file access to as the creator of the record
 | 
			
		||||
     **/
 | 
			
		||||
    @Test
 | 
			
		||||
    public void declareAsRecordRuleAsRMUserWithFilingPermissions() {
 | 
			
		||||
        STEP("Create a collaboration folder");
 | 
			
		||||
        testFolder = dataContent.usingSite(testSite)
 | 
			
		||||
            .usingUser(rmManager)
 | 
			
		||||
            .createFolder();
 | 
			
		||||
 | 
			
		||||
        STEP("Create a rule with Declare as Record action and check that user can select a record folder.");
 | 
			
		||||
        RecordCategory recordCategory = new RecordCategory().builder()
 | 
			
		||||
            .id(category_manager.getId()).build();
 | 
			
		||||
        RecordCategoryChild folderWithRule = createFolder(recordCategory.getId(), getRandomName("recordFolder"));
 | 
			
		||||
        RuleDefinition ruleDefinition = RuleDefinition.createNewRule().title("name").description("description")
 | 
			
		||||
            .applyToChildren(true)
 | 
			
		||||
            .actions(Collections.singletonList(ActionsOnRule.DECLARE_AS_RECORD.getActionValue()));
 | 
			
		||||
        rulesAPI.createRule(getAdminUser().getUsername(), getAdminUser().getPassword(), NODE_PREFIX + folderWithRule.getId(), ruleDefinition);
 | 
			
		||||
 | 
			
		||||
        assertStatusCode(CREATED);
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * Given I am configuring a "Declare and File as Record" action within a rule
 | 
			
		||||
     * And I don't have a records management role
 | 
			
		||||
     * When I am selecting the record folder location to file the declared record to
 | 
			
		||||
     * Then I can see only the file plan
 | 
			
		||||
     */
 | 
			
		||||
    @Test
 | 
			
		||||
    public void declareAsRecordRuleAsNonRMUser()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Create a collaboration folder");
 | 
			
		||||
        testFolder = dataContent.usingSite(testSite)
 | 
			
		||||
            .usingUser(nonRMUser)
 | 
			
		||||
            .createFolder();
 | 
			
		||||
 | 
			
		||||
        STEP("Create a rule with Declare as Record action and check that user can select a record folder.");
 | 
			
		||||
        RecordCategory recordCategory = new RecordCategory().builder()
 | 
			
		||||
            .id(category_manager.getId()).build();
 | 
			
		||||
 | 
			
		||||
        RuleDefinition ruleDefinition = RuleDefinition.createNewRule().title("name").description("description")
 | 
			
		||||
            .applyToChildren(true)
 | 
			
		||||
            .actions(Collections.singletonList(ActionsOnRule.DECLARE_AS_RECORD.getActionValue()));
 | 
			
		||||
        rulesAPI.createRule(nonRMUser.getUsername(), nonRMUser.getPassword(), NODE_PREFIX + testFolder.getNodeRef(), ruleDefinition);
 | 
			
		||||
 | 
			
		||||
        assertStatusCode(CREATED);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Given I have not selected a record folder location
 | 
			
		||||
     * When the rule is triggered
 | 
			
		||||
     * Then the file is declared as record to the UnFiled Records folder
 | 
			
		||||
     */
 | 
			
		||||
    @Test
 | 
			
		||||
    public void triggerDeclareToUnfiledRuleAsNonRMUser()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Create a collaboration folder with a rule set to declare and file as record without a record folder location");
 | 
			
		||||
 | 
			
		||||
        RecordCategory recordCategory = new RecordCategory().builder()
 | 
			
		||||
            .id(category_manager.getId()).build();
 | 
			
		||||
 | 
			
		||||
        RecordCategoryChild folderWithRule = createFolder(recordCategory.getId(), getRandomName("recordFolder"));
 | 
			
		||||
        RuleDefinition ruleDefinition = RuleDefinition.createNewRule().title("name").description("description")
 | 
			
		||||
            .applyToChildren(true)
 | 
			
		||||
            .actions(Collections.singletonList(ActionsOnRule.DECLARE_AS_RECORD.getActionValue()));
 | 
			
		||||
        rulesAPI.createRule(getAdminUser().getUsername(), getAdminUser().getPassword(), NODE_PREFIX + folderWithRule.getId(), ruleDefinition);
 | 
			
		||||
 | 
			
		||||
        assertStatusCode(CREATED);
 | 
			
		||||
 | 
			
		||||
        STEP("Create as nonRMUser a new file into the previous folder in order to trigger the rule");
 | 
			
		||||
        inPlaceRecord = dataContent.usingUser(nonRMUser).usingResource(testFolder).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
 | 
			
		||||
 | 
			
		||||
//      Verify that declared record is in Unfilled Records Folder
 | 
			
		||||
        UnfiledContainerAPI unfiledContainersAPI = getRestAPIFactory().getUnfiledContainersAPI();
 | 
			
		||||
        List<UnfiledContainerChildEntry> matchingRecords = unfiledContainersAPI.getUnfiledContainerChildren(UNFILED_RECORDS_CONTAINER_ALIAS)
 | 
			
		||||
            .getEntries()
 | 
			
		||||
            .stream()
 | 
			
		||||
            .filter(e -> e.getEntry().getId().equals(inPlaceRecord.getNodeRefWithoutVersion()))
 | 
			
		||||
            .collect(Collectors.toList());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @AfterClass(alwaysRun = true)
 | 
			
		||||
    public void cleanupDeclareAsRecordRuleTests()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Delete the collaboration site");
 | 
			
		||||
        dataSite.usingUser(nonRMUser).deleteSite(testSite);
 | 
			
		||||
 | 
			
		||||
        STEP("Delete Users");
 | 
			
		||||
        dataUser.deleteUser(nonRMUser);
 | 
			
		||||
        dataUser.deleteUser(rmManager);
 | 
			
		||||
 | 
			
		||||
        STEP("Delete categories");
 | 
			
		||||
        getRestAPIFactory().getFilePlansAPI().getRootRecordCategories(FILE_PLAN_ALIAS).getEntries().forEach(recordCategoryEntry ->
 | 
			
		||||
            deleteRecordCategory(recordCategoryEntry.getEntry().getId()));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,221 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%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.rules;
 | 
			
		||||
 | 
			
		||||
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.rules.ActionsOnRule;
 | 
			
		||||
import org.alfresco.rest.rm.community.model.rules.RuleDefinition;
 | 
			
		||||
import org.alfresco.rest.rm.community.model.unfiledcontainer.UnfiledContainerChildEntry;
 | 
			
		||||
import org.alfresco.rest.rm.community.model.user.UserRoles;
 | 
			
		||||
import org.alfresco.rest.rm.community.requests.gscore.api.UnfiledContainerAPI;
 | 
			
		||||
import org.alfresco.rest.rm.community.smoke.FileAsRecordTests;
 | 
			
		||||
import org.alfresco.rest.v0.RulesAPI;
 | 
			
		||||
import org.alfresco.rest.v0.service.RoleService;
 | 
			
		||||
import org.alfresco.utility.model.FileModel;
 | 
			
		||||
import org.alfresco.utility.model.FileType;
 | 
			
		||||
import org.alfresco.utility.model.FolderModel;
 | 
			
		||||
import org.alfresco.utility.model.UserModel;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.testng.annotations.AfterClass;
 | 
			
		||||
import org.testng.annotations.BeforeClass;
 | 
			
		||||
import org.testng.annotations.Test;
 | 
			
		||||
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
import static org.alfresco.rest.core.v0.BaseAPI.NODE_PREFIX;
 | 
			
		||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.FILE_PLAN_ALIAS;
 | 
			
		||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.UNFILED_RECORDS_CONTAINER_ALIAS;
 | 
			
		||||
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.http.HttpStatus.CREATED;
 | 
			
		||||
 | 
			
		||||
public class FileVersionAsRecordRuleTest  extends BaseRMRestTest {
 | 
			
		||||
 | 
			
		||||
    private UserModel nonRMuser, rmManager;
 | 
			
		||||
    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);
 | 
			
		||||
    private FolderModel testFolder;
 | 
			
		||||
    private FileModel document,inPlaceRecord;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private RoleService roleService;
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private RulesAPI rulesAPI;
 | 
			
		||||
 | 
			
		||||
    @BeforeClass(alwaysRun = true)
 | 
			
		||||
    public void createTestPrecondition()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        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);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        STEP("Create a collaboration folder with a rule set to declare and file version as record to a record folder");
 | 
			
		||||
        RecordCategoryChild folderWithRule = createFolder(recordCategory.getId(), getRandomName("recordFolder"));
 | 
			
		||||
        RuleDefinition ruleDefinition = RuleDefinition.createNewRule().title("name").description("description")
 | 
			
		||||
            .applyToChildren(true)
 | 
			
		||||
            .actions(Collections.singletonList(ActionsOnRule.DECLARE_AS_RECORD.getActionValue()));
 | 
			
		||||
        rulesAPI.createRule(getAdminUser().getUsername(), getAdminUser().getPassword(), NODE_PREFIX + folderWithRule.getId(), ruleDefinition);
 | 
			
		||||
 | 
			
		||||
        assertStatusCode(CREATED);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void declareVersionAsRecordRuleAsRMUserWithFilingPermissions()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        STEP("Create a collaboration folder");
 | 
			
		||||
        testFolder = dataContent.usingSite(testSite)
 | 
			
		||||
            .usingUser(rmManager)
 | 
			
		||||
            .createFolder();
 | 
			
		||||
 | 
			
		||||
        STEP("Create a rule with Declare as Record action and check that user can select a record folder.");
 | 
			
		||||
        RecordCategory recordCategory = new RecordCategory().builder()
 | 
			
		||||
            .id(category_manager.getId()).build();
 | 
			
		||||
        RecordCategoryChild folderWithRule = createFolder(recordCategory.getId(), getRandomName("recordFolder"));
 | 
			
		||||
        RuleDefinition ruleDefinition = RuleDefinition.createNewRule().title("name").description("description")
 | 
			
		||||
            .applyToChildren(true)
 | 
			
		||||
            .actions(Collections.singletonList(ActionsOnRule.DECLARE_AS_RECORD.getActionValue()));
 | 
			
		||||
        rulesAPI.createRule(rmManager.getUsername(), rmManager.getPassword(), NODE_PREFIX + testFolder.getNodeRef(), ruleDefinition);
 | 
			
		||||
 | 
			
		||||
        assertStatusCode(CREATED);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void declareVersionAsRecordRuleAsNonRMUser()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        STEP("Create a collaboration folder");
 | 
			
		||||
        testFolder = dataContent.usingSite(testSite)
 | 
			
		||||
            .usingUser(nonRMuser)
 | 
			
		||||
            .createFolder();
 | 
			
		||||
 | 
			
		||||
        STEP("Create a rule with Declare as Record action and check that user can select a record folder.");
 | 
			
		||||
        RecordCategory recordCategory = new RecordCategory().builder()
 | 
			
		||||
            .id(category_manager.getId()).build();
 | 
			
		||||
 | 
			
		||||
        RuleDefinition ruleDefinition = RuleDefinition.createNewRule().title("name").description("description")
 | 
			
		||||
            .applyToChildren(true)
 | 
			
		||||
            .actions(Collections.singletonList(ActionsOnRule.DECLARE_AS_RECORD.getActionValue()));
 | 
			
		||||
        rulesAPI.createRule(nonRMuser.getUsername(), nonRMuser.getPassword(), NODE_PREFIX + testFolder.getNodeRef(), ruleDefinition);
 | 
			
		||||
 | 
			
		||||
        assertStatusCode(CREATED);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void triggerDeclareToUnfiledRuleAsNonRMUser() throws Exception {
 | 
			
		||||
 | 
			
		||||
        STEP("Create a collaboration folder with a rule set to declare and file as record without a record folder location");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        FileModel inplaceRecord = dataContent.usingSite(testSite).usingUser(nonRMuser)
 | 
			
		||||
            .createContent(new FileModel("declareAndFileToIntoUnfiledRecordFolder",
 | 
			
		||||
                FileType.TEXT_PLAIN));
 | 
			
		||||
 | 
			
		||||
        RecordCategory recordCategory = new RecordCategory().builder()
 | 
			
		||||
            .id(category_manager.getId()).build();
 | 
			
		||||
 | 
			
		||||
        RuleDefinition ruleDefinition = RuleDefinition.createNewRule().title("name").description("description")
 | 
			
		||||
            .applyToChildren(true)
 | 
			
		||||
            .actions(Collections.singletonList(ActionsOnRule.DECLARE_AS_RECORD.getActionValue()));
 | 
			
		||||
        rulesAPI.createRule(nonRMuser.getUsername(), nonRMuser.getPassword(), NODE_PREFIX + inplaceRecord.getNodeRef(), ruleDefinition);
 | 
			
		||||
 | 
			
		||||
        assertStatusCode(CREATED);
 | 
			
		||||
 | 
			
		||||
       STEP("Create as nonRMuser a new file into the previous folder in order to trigger the rule");
 | 
			
		||||
        inPlaceRecord = dataContent.usingUser(nonRMuser).usingResource(testFolder).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
 | 
			
		||||
 | 
			
		||||
        // verify the declared record is in Unfilled Records folder
 | 
			
		||||
        UnfiledContainerAPI unfiledContainersAPI = getRestAPIFactory().getUnfiledContainersAPI();
 | 
			
		||||
        List<UnfiledContainerChildEntry> matchingRecords = unfiledContainersAPI.getUnfiledContainerChildren(UNFILED_RECORDS_CONTAINER_ALIAS)
 | 
			
		||||
            .getEntries()
 | 
			
		||||
            .stream()
 | 
			
		||||
            .filter(e -> e.getEntry().getId().equals(inplaceRecord.getNodeRefWithoutVersion()))
 | 
			
		||||
            .collect(Collectors.toList());
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @AfterClass(alwaysRun = true)
 | 
			
		||||
    public void cleanupDeclareVersionAsRecordRuleTests()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        STEP("Delete the collaboration site");
 | 
			
		||||
        dataSite.usingUser(nonRMuser).deleteSite(testSite);
 | 
			
		||||
 | 
			
		||||
        STEP("Delete Users");
 | 
			
		||||
        dataUser.deleteUser(nonRMuser);
 | 
			
		||||
        dataUser.deleteUser(rmManager);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        STEP("Delete categories");
 | 
			
		||||
        getRestAPIFactory().getFilePlansAPI().getRootRecordCategories(FILE_PLAN_ALIAS).getEntries().forEach(recordCategoryEntry ->
 | 
			
		||||
            deleteRecordCategory(recordCategoryEntry.getEntry().getId()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,237 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%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.rules;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.rest.model.RestNodeModel;
 | 
			
		||||
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.rules.ActionsOnRule;
 | 
			
		||||
import org.alfresco.rest.rm.community.model.rules.ConditionsOnRule;
 | 
			
		||||
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.UnfiledContainerChildEntry;
 | 
			
		||||
import org.alfresco.rest.rm.community.model.user.UserRoles;
 | 
			
		||||
import org.alfresco.rest.rm.community.requests.gscore.api.RecordFolderAPI;
 | 
			
		||||
import org.alfresco.rest.rm.community.requests.gscore.api.UnfiledContainerAPI;
 | 
			
		||||
import org.alfresco.rest.search.RestRequestQueryModel;
 | 
			
		||||
import org.alfresco.rest.v0.HoldsAPI;
 | 
			
		||||
import org.alfresco.rest.v0.RecordsAPI;
 | 
			
		||||
import org.alfresco.rest.v0.RulesAPI;
 | 
			
		||||
import org.alfresco.rest.v0.service.RoleService;
 | 
			
		||||
import org.alfresco.utility.model.UserModel;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.testng.annotations.AfterClass;
 | 
			
		||||
import org.testng.annotations.BeforeClass;
 | 
			
		||||
import org.testng.annotations.Test;
 | 
			
		||||
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Random;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
import static java.lang.Integer.MAX_VALUE;
 | 
			
		||||
import static java.util.Arrays.asList;
 | 
			
		||||
import static org.alfresco.rest.core.v0.BaseAPI.NODE_PREFIX;
 | 
			
		||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.FILE_PLAN_ALIAS;
 | 
			
		||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.UNFILED_RECORDS_CONTAINER_ALIAS;
 | 
			
		||||
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.rest.rm.community.utils.FilePlanComponentsUtil.*;
 | 
			
		||||
import static org.alfresco.utility.data.RandomData.getRandomAlphanumeric;
 | 
			
		||||
import static org.alfresco.utility.data.RandomData.getRandomName;
 | 
			
		||||
import static org.alfresco.utility.report.log.Step.STEP;
 | 
			
		||||
import static org.springframework.http.HttpStatus.*;
 | 
			
		||||
import static org.testng.Assert.assertNotNull;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
public class MoveToRuleOnFoldersTest extends BaseRMRestTest{
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private RecordCategoryChild recordFolder2;
 | 
			
		||||
    private RecordCategoryChild recordFolder1;
 | 
			
		||||
    private String nonElectronicId;
 | 
			
		||||
 | 
			
		||||
    public Record electronicRecord;
 | 
			
		||||
 | 
			
		||||
    private String ruleType = ConditionsOnRule.UPDATE.getWhenConditionValue();
 | 
			
		||||
    private UserModel rmAdmin;
 | 
			
		||||
    public RecordCategory RecordCategoryOne;
 | 
			
		||||
    private RecordCategoryChild recordFolder;
 | 
			
		||||
    public static final String RECORD_FOLDER_ONE = "record-folder-one";
 | 
			
		||||
    private final String TEST_PREFIX = generateTestPrefix(MoveToRuleOnFoldersTest.class);
 | 
			
		||||
 | 
			
		||||
    private final String RECORD_CATEGORY_ONE = TEST_PREFIX + "category";
 | 
			
		||||
 | 
			
		||||
    private final String recordName = "Test record";
 | 
			
		||||
    private final String recordTitle = recordName + " title";
 | 
			
		||||
    private final String recordDescription = recordName + " description";
 | 
			
		||||
    private Record nonElectrinicRecordModel;
 | 
			
		||||
    private RecordFolderAPI recordFolderAPI;
 | 
			
		||||
    public String title,description,box,file,shelf,storageLocation,name;
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private RulesAPI rulesAPI;
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private HoldsAPI holdsAPI;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private RoleService roleService;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    public RecordsAPI recordsAPI;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @BeforeClass(alwaysRun = true)
 | 
			
		||||
    public void precondition()
 | 
			
		||||
    {
 | 
			
		||||
        //create RM site
 | 
			
		||||
        createRMSiteIfNotExists();
 | 
			
		||||
        rmAdmin = roleService.createUserWithRMRole(UserRoles.ROLE_RM_ADMIN.roleId);
 | 
			
		||||
        //create root category, create folders , add electronic and non electronic records
 | 
			
		||||
        RecordCategoryOne = createRootCategory(RECORD_CATEGORY_ONE);
 | 
			
		||||
        recordFolder1=createRecordFolder(RecordCategoryOne.getId(), getRandomName("recFolder"));
 | 
			
		||||
       // recordFolder1_id = createRecordFolder(RecordCategoryOne.getId(), getRandomName("recFolder")).getId();
 | 
			
		||||
        recordFolder2 = createFolder(getAdminUser(),RecordCategoryOne.getId(),getRandomName("recFolder"));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        STEP("CREATE ELECTRONIC RECORD");
 | 
			
		||||
        recordFolderAPI = getRestAPIFactory().getRecordFolderAPI();
 | 
			
		||||
        electronicRecord = recordFolderAPI.createRecord(createElectronicRecordModel(), recordFolder1.getId(), getFile(IMAGE_FILE));
 | 
			
		||||
        STEP("Check the electronic record has been created");
 | 
			
		||||
        assertStatusCode(CREATED);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        STEP("Create a non-electronic record by completing some of the fields");
 | 
			
		||||
        // Use these properties for non-electronic record to be created
 | 
			
		||||
        title = "Title " + getRandomAlphanumeric();
 | 
			
		||||
        description = "Description " + getRandomAlphanumeric();
 | 
			
		||||
        box = "Box "+ getRandomAlphanumeric();
 | 
			
		||||
        file = "File " + getRandomAlphanumeric();
 | 
			
		||||
        shelf = "Shelf " + getRandomAlphanumeric();
 | 
			
		||||
        storageLocation = "Storage Location " + getRandomAlphanumeric();
 | 
			
		||||
        name = "Record " + getRandomAlphanumeric();
 | 
			
		||||
        Random random = new Random();
 | 
			
		||||
        Integer numberOfCopies = random.nextInt(MAX_VALUE);
 | 
			
		||||
        Integer physicalSize = random.nextInt(MAX_VALUE);
 | 
			
		||||
 | 
			
		||||
        // Set values of all available properties for the non electronic records
 | 
			
		||||
        nonElectrinicRecordModel = createFullNonElectronicRecordModel(name, title, description, box, file, shelf, storageLocation, numberOfCopies, physicalSize);
 | 
			
		||||
        // Create non-electronic record
 | 
			
		||||
        nonElectronicId = recordFolderAPI.createRecord(nonElectrinicRecordModel, recordFolder1.getId()).getId();
 | 
			
		||||
        STEP("Check the non-electronic record has been created");
 | 
			
		||||
        assertStatusCode(CREATED);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void MoveToRuleFoldersTest()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        String CatName=RecordCategoryOne.getName();
 | 
			
		||||
        String folder2name=recordFolder2.getName();
 | 
			
		||||
        String recfolder2_path="/"+CatName+"/"+folder2name;
 | 
			
		||||
 | 
			
		||||
        STEP("create a rule MOVE_TO for folder 1");
 | 
			
		||||
        RuleDefinition ruleDefinition = RuleDefinition.createNewRule().title("name").description("description1")
 | 
			
		||||
            .runInBackground(true).title(title)
 | 
			
		||||
            .actions(Collections.singletonList(ActionsOnRule.MOVE_TO.getActionValue())).ruleType(ruleType).path(recfolder2_path);
 | 
			
		||||
        rulesAPI.createRule(getAdminUser().getUsername(), getAdminUser().getPassword(), NODE_PREFIX +recordFolder1.getId() , ruleDefinition);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        STEP("Update metadata for Non-Electronic Record");
 | 
			
		||||
        updateRecordMetadata();
 | 
			
		||||
 | 
			
		||||
        STEP("Delete ELECTRONIC AND NON-ELECTRONIC RECORDS IN FOLDER 2");
 | 
			
		||||
        org.alfresco.rest.rm.community.requests.gscore.api.RecordsAPI recordsAPI = getRestAPIFactory().getRecordsAPI();
 | 
			
		||||
        recordsAPI.deleteRecord(electronicRecord.getId());
 | 
			
		||||
        assertStatusCode(NO_CONTENT);
 | 
			
		||||
        recordsAPI.deleteRecord(nonElectronicId);
 | 
			
		||||
        assertStatusCode(NO_CONTENT);
 | 
			
		||||
 | 
			
		||||
        STEP("RULE CREATION FOR FOLDER 1 WITHOUT RUNNING IN BACKGROUND");
 | 
			
		||||
 | 
			
		||||
        RuleDefinition ruleDefinition_notinbackground = RuleDefinition.createNewRule().title("name").description("description1")
 | 
			
		||||
            .runInBackground(false).title(title)
 | 
			
		||||
            .actions(Collections.singletonList(ActionsOnRule.MOVE_TO.getActionValue())).ruleType(ruleType).path(recfolder2_path);
 | 
			
		||||
        rulesAPI.createRule(getAdminUser().getUsername(), getAdminUser().getPassword(), NODE_PREFIX +recordFolder1.getId() , ruleDefinition);
 | 
			
		||||
 | 
			
		||||
        STEP("CREATE ELECTRONIC AND NON-ELECTRONIC RECORDS");
 | 
			
		||||
        electronicRecord = recordFolderAPI.createRecord(createElectronicRecordModel(), recordFolder1.getId(), getFile(IMAGE_FILE));
 | 
			
		||||
        STEP("Check the electronic record has been created");
 | 
			
		||||
        assertStatusCode(CREATED);
 | 
			
		||||
        nonElectronicId = recordFolderAPI.createRecord(nonElectrinicRecordModel, recordFolder1.getId()).getId();
 | 
			
		||||
        STEP("Check the non-electronic record has been created");
 | 
			
		||||
        assertStatusCode(CREATED);
 | 
			
		||||
 | 
			
		||||
        STEP("UPDATE METADATA");
 | 
			
		||||
        updateRecordMetadata();
 | 
			
		||||
 | 
			
		||||
        STEP("CHECK IF ELECTRONIC AND NON-ELECTRONIC RECORDS MOVED  TO FOLDER2");
 | 
			
		||||
        updateRecordMetadata();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @AfterClass(alwaysRun = true)
 | 
			
		||||
    public void cleanMoveToRuleOnFoldersTest()
 | 
			
		||||
    {
 | 
			
		||||
        deleteRecordCategory(RecordCategoryOne.getId());
 | 
			
		||||
 | 
			
		||||
        getDataUser().deleteUser(rmAdmin);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String getModifiedPropertyValue(String originalValue) {
 | 
			
		||||
        /* to be used to append to modifications */
 | 
			
		||||
        String MODIFIED_PREFIX = "modified_";
 | 
			
		||||
        return MODIFIED_PREFIX + originalValue;
 | 
			
		||||
    }
 | 
			
		||||
    private void updateRecordMetadata(){
 | 
			
		||||
        STEP("Update metadata for Non-Electronic Record");
 | 
			
		||||
        org.alfresco.rest.rm.community.requests.gscore.api.RecordsAPI recordsAPI = getRestAPIFactory().getRecordsAPI();
 | 
			
		||||
        Record nonelecrecord = recordsAPI.getRecord(nonElectronicId);
 | 
			
		||||
        String nonelecnewName = getModifiedPropertyValue(nonElectrinicRecordModel.getName());
 | 
			
		||||
        String nonelecnewTitle = getModifiedPropertyValue(nonElectrinicRecordModel.getProperties().getTitle());
 | 
			
		||||
        String nonelecnewDescription = getModifiedPropertyValue(nonElectrinicRecordModel.getProperties().getDescription());
 | 
			
		||||
        recordsAPI.updateRecord(createRecordModel(nonelecnewName, nonelecnewDescription, nonelecnewTitle),nonelecrecord.getId());
 | 
			
		||||
        assertStatusCode(OK);
 | 
			
		||||
 | 
			
		||||
        STEP("Update metadata for Electronic Record");
 | 
			
		||||
        Record elecrecord = recordsAPI.getRecord(electronicRecord.getId());
 | 
			
		||||
        String elecnewName = getModifiedPropertyValue(electronicRecord.getName());
 | 
			
		||||
        String elecnewTitle = getModifiedPropertyValue(electronicRecord.getProperties().getTitle());
 | 
			
		||||
        String elecnewDescription = getModifiedPropertyValue(electronicRecord.getProperties().getDescription());
 | 
			
		||||
        recordsAPI.updateRecord(createRecordModel(elecnewName, elecnewDescription, elecnewTitle),elecrecord.getId());
 | 
			
		||||
        assertStatusCode(OK);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
   <parent>
 | 
			
		||||
      <groupId>org.alfresco</groupId>
 | 
			
		||||
      <artifactId>alfresco-governance-services-community-parent</artifactId>
 | 
			
		||||
      <version>20.19</version>
 | 
			
		||||
      <version>20.28-SNAPSHOT</version>
 | 
			
		||||
   </parent>
 | 
			
		||||
 | 
			
		||||
   <modules>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,3 @@
 | 
			
		||||
SOLR6_TAG=2.0.5
 | 
			
		||||
SOLR6_TAG=2.0.5.1
 | 
			
		||||
POSTGRES_TAG=14.4
 | 
			
		||||
ACTIVEMQ_TAG=5.17.1-jre11-rockylinux8
 | 
			
		||||
 
 | 
			
		||||
@@ -175,6 +175,10 @@
 | 
			
		||||
       <property name="nodesModelFactory" ref="nodesModelFactory" />
 | 
			
		||||
    </bean>
 | 
			
		||||
 | 
			
		||||
    <bean class="org.alfresco.rm.rest.api.events.EventEntityResource">
 | 
			
		||||
        <property name="recordsManagementEventService" ref="RecordsManagementEventService" />
 | 
			
		||||
    </bean>
 | 
			
		||||
 | 
			
		||||
   <!-- extended sites bean definition -->
 | 
			
		||||
   <bean id="rm.sites" class="org.alfresco.rm.rest.api.impl.RMSitesImpl" parent="sites">
 | 
			
		||||
        <property name="siteSurfConfig" ref="rm.siteSurfConfig" />
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@
 | 
			
		||||
   <parent>
 | 
			
		||||
      <groupId>org.alfresco</groupId>
 | 
			
		||||
      <artifactId>alfresco-governance-services-community-repo-parent</artifactId>
 | 
			
		||||
      <version>20.19</version>
 | 
			
		||||
      <version>20.28-SNAPSHOT</version>
 | 
			
		||||
   </parent>
 | 
			
		||||
 | 
			
		||||
   <properties>
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,76 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%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.rm.rest.api.events;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.module.org_alfresco_module_rm.event.RecordsManagementEventService;
 | 
			
		||||
import org.alfresco.rest.framework.WebApiDescription;
 | 
			
		||||
import org.alfresco.rest.framework.resource.EntityResource;
 | 
			
		||||
import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction;
 | 
			
		||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
 | 
			
		||||
import org.alfresco.rest.framework.resource.parameters.Paging;
 | 
			
		||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
 | 
			
		||||
import org.alfresco.rm.rest.api.model.EventInfo;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Event entity resource
 | 
			
		||||
 */
 | 
			
		||||
@EntityResource(name = "events", title = "Events")
 | 
			
		||||
public class EventEntityResource implements EntityResourceAction.Read<EventInfo> {
 | 
			
		||||
    private RecordsManagementEventService recordsManagementEventService;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set the records management event service
 | 
			
		||||
     *
 | 
			
		||||
     * @param rmEventService Records management event service
 | 
			
		||||
     */
 | 
			
		||||
    public void setRecordsManagementEventService(RecordsManagementEventService rmEventService)
 | 
			
		||||
    {
 | 
			
		||||
        this.recordsManagementEventService = rmEventService;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    @WebApiDescription(title = "Return a list of events")
 | 
			
		||||
    public CollectionWithPagingInfo<EventInfo> readAll(Parameters params)
 | 
			
		||||
    {
 | 
			
		||||
        Paging paging = params.getPaging();
 | 
			
		||||
 | 
			
		||||
        List<EventInfo> eventInfoList = recordsManagementEventService.getEvents().stream()
 | 
			
		||||
                .map(EventInfo::fromRecordsManagementEvent)
 | 
			
		||||
                .collect(Collectors.toList());
 | 
			
		||||
 | 
			
		||||
        int totalCount = eventInfoList.size();
 | 
			
		||||
        boolean hasMoreItems = paging.getSkipCount() + paging.getMaxItems() < totalCount;
 | 
			
		||||
        return CollectionWithPagingInfo.asPaged(paging, eventInfoList.stream()
 | 
			
		||||
                .skip(paging.getSkipCount())
 | 
			
		||||
                .limit(paging.getMaxItems())
 | 
			
		||||
                .collect(Collectors.toList()), hasMoreItems, totalCount);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,34 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%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 info that defines the Information Governance Events REST API
 | 
			
		||||
 */
 | 
			
		||||
@WebApi(name="gs", scope=Api.SCOPE.PUBLIC, version=1)
 | 
			
		||||
package org.alfresco.rm.rest.api.events;
 | 
			
		||||
import org.alfresco.rest.framework.Api;
 | 
			
		||||
import org.alfresco.rest.framework.WebApi;
 | 
			
		||||
@@ -0,0 +1,82 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%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.rm.rest.api.model;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.module.org_alfresco_module_rm.event.RecordsManagementEvent;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The EventInfo model to be exposed through REST API.
 | 
			
		||||
 */
 | 
			
		||||
public class EventInfo {
 | 
			
		||||
    private String id;
 | 
			
		||||
    private String name;
 | 
			
		||||
    private String type;
 | 
			
		||||
 | 
			
		||||
    public static EventInfo fromRecordsManagementEvent(RecordsManagementEvent event)
 | 
			
		||||
    {
 | 
			
		||||
        EventInfo eventInfo = new EventInfo();
 | 
			
		||||
        if (event != null) {
 | 
			
		||||
            eventInfo.setName(event.getDisplayLabel());
 | 
			
		||||
            eventInfo.setId(event.getName());
 | 
			
		||||
            eventInfo.setType(event.getType());
 | 
			
		||||
        }
 | 
			
		||||
        return eventInfo;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public EventInfo() {}
 | 
			
		||||
 | 
			
		||||
    public String getId()
 | 
			
		||||
    {
 | 
			
		||||
        return id;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setId(String id)
 | 
			
		||||
    {
 | 
			
		||||
        this.id = id;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String getName()
 | 
			
		||||
    {
 | 
			
		||||
        return name;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setName(String name)
 | 
			
		||||
    {
 | 
			
		||||
        this.name = name;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String getType()
 | 
			
		||||
    {
 | 
			
		||||
        return type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setType(String type)
 | 
			
		||||
    {
 | 
			
		||||
        this.type = type;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-governance-services-community-repo-parent</artifactId>
 | 
			
		||||
        <version>20.19</version>
 | 
			
		||||
        <version>20.28-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <build>
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,9 @@ tags:
 | 
			
		||||
    description: Retrieve and manage unfiled records containers
 | 
			
		||||
  - name: unfiled-record-folders
 | 
			
		||||
    description: Retrieve and manage unfiled record folders
 | 
			
		||||
  - name: events
 | 
			
		||||
    description: Retrieve and manage retention events
 | 
			
		||||
    
 | 
			
		||||
paths:
 | 
			
		||||
  ## GS sites
 | 
			
		||||
  '/gs-sites':
 | 
			
		||||
@@ -2091,7 +2094,172 @@ paths:
 | 
			
		||||
          description: Unexpected error
 | 
			
		||||
          schema:
 | 
			
		||||
            $ref: '#/definitions/Error'
 | 
			
		||||
  '/events':
 | 
			
		||||
    get:
 | 
			
		||||
      tags:
 | 
			
		||||
        - events
 | 
			
		||||
      summary: List all available retention events
 | 
			
		||||
      description: |
 | 
			
		||||
        Gets the list of events that can be used by retention steps
 | 
			
		||||
      operationId: getAllEvents
 | 
			
		||||
      produces:
 | 
			
		||||
        - application/json
 | 
			
		||||
      parameters:
 | 
			
		||||
        - $ref: '#/parameters/skipCountParam'
 | 
			
		||||
        - $ref: '#/parameters/maxItemsParam'
 | 
			
		||||
      responses:
 | 
			
		||||
        '200':
 | 
			
		||||
          description: Successful response
 | 
			
		||||
          schema:
 | 
			
		||||
            $ref: '#/definitions/EventPaging'
 | 
			
		||||
        '400':
 | 
			
		||||
          description: |
 | 
			
		||||
            Invalid parameter: value of **maxItems** or **skipCount** is invalid
 | 
			
		||||
        '401':
 | 
			
		||||
          description: Authentication failed
 | 
			
		||||
        default:
 | 
			
		||||
          description: Unexpected error
 | 
			
		||||
          schema:
 | 
			
		||||
            $ref: '#/definitions/Error'
 | 
			
		||||
 | 
			
		||||
    post:
 | 
			
		||||
      tags:
 | 
			
		||||
        - events
 | 
			
		||||
      summary: Create a new retention event
 | 
			
		||||
      description: |
 | 
			
		||||
        Creates a new event that can be used by retention schedules.
 | 
			
		||||
      operationId: createEvent
 | 
			
		||||
      parameters:
 | 
			
		||||
        - in: body
 | 
			
		||||
          name: eventBodyCreate
 | 
			
		||||
          description: The new event.
 | 
			
		||||
          required: true
 | 
			
		||||
          schema:
 | 
			
		||||
            $ref: '#/definitions/EventBody'
 | 
			
		||||
      consumes:
 | 
			
		||||
        - application/json
 | 
			
		||||
      produces:
 | 
			
		||||
        - application/json
 | 
			
		||||
      responses:
 | 
			
		||||
        '201':
 | 
			
		||||
          description: Successful response
 | 
			
		||||
          schema:
 | 
			
		||||
            $ref: '#/definitions/EventEntry'
 | 
			
		||||
        '400':
 | 
			
		||||
          description: |
 | 
			
		||||
            Invalid parameter: **name** or **type** is invalid
 | 
			
		||||
        '401':
 | 
			
		||||
          description: Authentication failed
 | 
			
		||||
        '403':
 | 
			
		||||
          description: Current user does not have permission to create event
 | 
			
		||||
        '409':
 | 
			
		||||
          description: Cannot create event. An event with the name **name** already exists
 | 
			
		||||
        default:
 | 
			
		||||
          description: Unexpected error
 | 
			
		||||
          schema:
 | 
			
		||||
            $ref: '#/definitions/Error'
 | 
			
		||||
  
 | 
			
		||||
  '/events/{eventId}':
 | 
			
		||||
    get:
 | 
			
		||||
      tags:
 | 
			
		||||
        - events
 | 
			
		||||
      summary: Return event for given eventId
 | 
			
		||||
      description: |
 | 
			
		||||
        Gets information about the retention event with id **eventId**.
 | 
			
		||||
      operationId: getEvent
 | 
			
		||||
      produces:
 | 
			
		||||
        - application/json
 | 
			
		||||
      parameters:
 | 
			
		||||
        - $ref: '#/parameters/eventIdParam'
 | 
			
		||||
      responses:
 | 
			
		||||
        '200':
 | 
			
		||||
          description: Successful response
 | 
			
		||||
          schema:
 | 
			
		||||
            $ref: '#/definitions/EventEntry'
 | 
			
		||||
        '400':
 | 
			
		||||
          description: |
 | 
			
		||||
            Invalid parameter: **eventId** is invalid    
 | 
			
		||||
        '401':
 | 
			
		||||
          description: Authentication failed
 | 
			
		||||
        '404':
 | 
			
		||||
          description: "**eventId** does not exist"
 | 
			
		||||
        default:
 | 
			
		||||
          description: Unexpected error
 | 
			
		||||
          schema:
 | 
			
		||||
            $ref: '#/definitions/Error'
 | 
			
		||||
    put:
 | 
			
		||||
      tags:
 | 
			
		||||
        - events
 | 
			
		||||
      summary: Update event for given eventId
 | 
			
		||||
      operationId: updateEvent
 | 
			
		||||
      description: |
 | 
			
		||||
        Updates retention event with id **eventId**.
 | 
			
		||||
      produces:
 | 
			
		||||
        - application/json
 | 
			
		||||
      parameters:
 | 
			
		||||
        - $ref: '#/parameters/eventIdParam'
 | 
			
		||||
        - in: body
 | 
			
		||||
          name: eventBodyUpdate
 | 
			
		||||
          description: The event information to update.
 | 
			
		||||
          required: true
 | 
			
		||||
          schema:
 | 
			
		||||
            $ref: '#/definitions/EventBody'
 | 
			
		||||
      responses:
 | 
			
		||||
        '200':
 | 
			
		||||
          description: Successful response
 | 
			
		||||
          schema:
 | 
			
		||||
            $ref: '#/definitions/EventEntry'
 | 
			
		||||
        '400':
 | 
			
		||||
          description: |
 | 
			
		||||
            Invalid parameter: The update request is invalid or **eventId** is not a valid format or **eventBodyUpdate** is invalid
 | 
			
		||||
        '401':
 | 
			
		||||
          description: Authentication failed
 | 
			
		||||
        '403':
 | 
			
		||||
          description: Current user does not have permission to update events
 | 
			
		||||
        '404':
 | 
			
		||||
          description: "**eventId** does not exist"
 | 
			
		||||
        '409':
 | 
			
		||||
          description: Cannot update event. An event with the name **name** already exists
 | 
			
		||||
        default:
 | 
			
		||||
          description: Unexpected error
 | 
			
		||||
          schema:
 | 
			
		||||
            $ref: '#/definitions/Error'
 | 
			
		||||
  
 | 
			
		||||
  '/event-types':
 | 
			
		||||
    get:
 | 
			
		||||
      tags:
 | 
			
		||||
        - events
 | 
			
		||||
      summary: List all the retention event types
 | 
			
		||||
      description: |
 | 
			
		||||
        Gets a list of all the retention event types.
 | 
			
		||||
      operationId: getAllEventTypes
 | 
			
		||||
      produces:
 | 
			
		||||
        - application/json
 | 
			
		||||
      parameters:
 | 
			
		||||
        - $ref: '#/parameters/skipCountParam'
 | 
			
		||||
        - $ref: '#/parameters/maxItemsParam'
 | 
			
		||||
      responses:
 | 
			
		||||
        '200':
 | 
			
		||||
          description: Successful response
 | 
			
		||||
          schema:
 | 
			
		||||
            $ref: '#/definitions/EventTypePaging'
 | 
			
		||||
        '400':
 | 
			
		||||
          description: |
 | 
			
		||||
            Invalid parameter: value of **maxItems** or **skipCount** is invalid
 | 
			
		||||
        '401':
 | 
			
		||||
          description: Authentication failed
 | 
			
		||||
        default:
 | 
			
		||||
          description: Unexpected error
 | 
			
		||||
          schema:
 | 
			
		||||
            $ref: '#/definitions/Error'          
 | 
			
		||||
parameters:
 | 
			
		||||
  ## event
 | 
			
		||||
  eventIdParam:
 | 
			
		||||
    name: eventId
 | 
			
		||||
    in: path
 | 
			
		||||
    description: The identifier of an event.
 | 
			
		||||
    required: true
 | 
			
		||||
    type: string
 | 
			
		||||
  ## File plans
 | 
			
		||||
  filePlanEntryIncludeParam:
 | 
			
		||||
    name: include
 | 
			
		||||
@@ -3760,3 +3928,91 @@ definitions:
 | 
			
		||||
          - SiteCollaborator
 | 
			
		||||
          - SiteContributor
 | 
			
		||||
          - SiteManager
 | 
			
		||||
  EventPaging:
 | 
			
		||||
    type: object
 | 
			
		||||
    properties:
 | 
			
		||||
      list:
 | 
			
		||||
        type: object
 | 
			
		||||
        properties:
 | 
			
		||||
          pagination:
 | 
			
		||||
            $ref: '#/definitions/Pagination'
 | 
			
		||||
          entries:
 | 
			
		||||
            type: array
 | 
			
		||||
            items:
 | 
			
		||||
              $ref: '#/definitions/EventEntry'
 | 
			
		||||
  EventEntry:
 | 
			
		||||
    type: object
 | 
			
		||||
    required:
 | 
			
		||||
      - entry
 | 
			
		||||
    properties:
 | 
			
		||||
      entry:
 | 
			
		||||
        $ref: '#/definitions/Event'
 | 
			
		||||
  Event:
 | 
			
		||||
    type: object
 | 
			
		||||
    required:
 | 
			
		||||
      - id
 | 
			
		||||
      - name
 | 
			
		||||
      - type
 | 
			
		||||
    properties:
 | 
			
		||||
      id:
 | 
			
		||||
        type: string
 | 
			
		||||
        description: this is the id of the event
 | 
			
		||||
      name:
 | 
			
		||||
        type: string
 | 
			
		||||
        description: This is the unique display label of the event
 | 
			
		||||
      type:
 | 
			
		||||
        type: string
 | 
			
		||||
        description: this is event type
 | 
			
		||||
  EventBody:
 | 
			
		||||
    type: object
 | 
			
		||||
    required:
 | 
			
		||||
      - name
 | 
			
		||||
    properties:
 | 
			
		||||
      name:
 | 
			
		||||
        type: string
 | 
			
		||||
        description: This is the unique display label of the event
 | 
			
		||||
      type:
 | 
			
		||||
        type: string
 | 
			
		||||
        description: this is event type
 | 
			
		||||
        default: Simple
 | 
			
		||||
  EventTypePaging:
 | 
			
		||||
    type: object
 | 
			
		||||
    properties:
 | 
			
		||||
      list:
 | 
			
		||||
        type: object
 | 
			
		||||
        properties:
 | 
			
		||||
          pagination:
 | 
			
		||||
            $ref: '#/definitions/Pagination'
 | 
			
		||||
          entries:
 | 
			
		||||
            type: array
 | 
			
		||||
            items:
 | 
			
		||||
              $ref: '#/definitions/EventTypeEntry'
 | 
			
		||||
  EventTypeEntry:
 | 
			
		||||
    type: object
 | 
			
		||||
    required:
 | 
			
		||||
      - entry
 | 
			
		||||
    properties:
 | 
			
		||||
      entry:
 | 
			
		||||
        $ref: '#/definitions/EventType'
 | 
			
		||||
  EventType:
 | 
			
		||||
    type: object
 | 
			
		||||
    required:
 | 
			
		||||
      - id
 | 
			
		||||
      - name
 | 
			
		||||
    properties:
 | 
			
		||||
      id:
 | 
			
		||||
        type: string
 | 
			
		||||
        description: this is the event type id
 | 
			
		||||
      name:
 | 
			
		||||
        type: string
 | 
			
		||||
        description: this is event type name
 | 
			
		||||
      isAutomatic:
 | 
			
		||||
        type: boolean
 | 
			
		||||
        description: Whether events of this type need completing manually or can be completed automatically
 | 
			
		||||
        default: true
 | 
			
		||||
      associationName:
 | 
			
		||||
        type: string
 | 
			
		||||
        description: The association used to determine whether automatic events of this type are complete
 | 
			
		||||
      actionOnAssociatedNode:
 | 
			
		||||
        type: string
 | 
			
		||||
        description: If an association name is set for this event type then it is possible to require an action to be completed on the associated node
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo</artifactId>
 | 
			
		||||
        <version>20.19</version>
 | 
			
		||||
        <version>20.28-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <modules>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo-amps</artifactId>
 | 
			
		||||
        <version>20.19</version>
 | 
			
		||||
        <version>20.28-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <properties>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
   <parent>
 | 
			
		||||
      <groupId>org.alfresco</groupId>
 | 
			
		||||
      <artifactId>alfresco-community-repo</artifactId>
 | 
			
		||||
      <version>20.19</version>
 | 
			
		||||
      <version>20.28-SNAPSHOT</version>
 | 
			
		||||
   </parent>
 | 
			
		||||
 | 
			
		||||
   <dependencies>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo</artifactId>
 | 
			
		||||
        <version>20.19</version>
 | 
			
		||||
        <version>20.28-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <properties>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo</artifactId>
 | 
			
		||||
        <version>20.19</version>
 | 
			
		||||
        <version>20.28-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <dependencies>
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,6 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo-packaging</artifactId>
 | 
			
		||||
        <version>20.19</version>
 | 
			
		||||
        <version>20.28-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
</project>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo-packaging</artifactId>
 | 
			
		||||
        <version>20.19</version>
 | 
			
		||||
        <version>20.28-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <properties>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo</artifactId>
 | 
			
		||||
        <version>20.19</version>
 | 
			
		||||
        <version>20.28-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <modules>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,3 @@
 | 
			
		||||
SOLR6_TAG=2.0.5
 | 
			
		||||
SOLR6_TAG=2.0.5.1
 | 
			
		||||
POSTGRES_TAG=14.4
 | 
			
		||||
ACTIVEMQ_TAG=5.17.1-jre11-rockylinux8
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo-packaging</artifactId>
 | 
			
		||||
        <version>20.19</version>
 | 
			
		||||
        <version>20.28-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <modules>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo-tests</artifactId>
 | 
			
		||||
        <version>20.19</version>
 | 
			
		||||
        <version>20.28-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <organization>
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo-tests</artifactId>
 | 
			
		||||
        <version>20.19</version>
 | 
			
		||||
        <version>20.28-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <developers>
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo-tests</artifactId>
 | 
			
		||||
        <version>20.19</version>
 | 
			
		||||
        <version>20.28-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <developers>
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo-tests</artifactId>
 | 
			
		||||
        <version>20.19</version>
 | 
			
		||||
        <version>20.28-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <developers>
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,103 @@
 | 
			
		||||
package org.alfresco.rest.actions.email;
 | 
			
		||||
 | 
			
		||||
import static java.util.Objects.requireNonNull;
 | 
			
		||||
 | 
			
		||||
import static org.hamcrest.Matchers.notNullValue;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import javax.json.JsonObject;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.rest.RestTest;
 | 
			
		||||
import org.alfresco.rest.core.JsonBodyGenerator;
 | 
			
		||||
import org.alfresco.utility.model.FileModel;
 | 
			
		||||
import org.alfresco.utility.model.FileType;
 | 
			
		||||
import org.alfresco.utility.model.FolderModel;
 | 
			
		||||
import org.alfresco.utility.model.UserModel;
 | 
			
		||||
 | 
			
		||||
import org.springframework.http.HttpStatus;
 | 
			
		||||
import org.testng.annotations.BeforeClass;
 | 
			
		||||
import org.testng.annotations.Test;
 | 
			
		||||
 | 
			
		||||
public class EmailTemplateTest extends RestTest {
 | 
			
		||||
 | 
			
		||||
    public static final String MAIL_ACTION = "mail";
 | 
			
		||||
 | 
			
		||||
    private UserModel adminUser;
 | 
			
		||||
    private UserModel testUser;
 | 
			
		||||
    private FolderModel testFolder;
 | 
			
		||||
 | 
			
		||||
    @BeforeClass(alwaysRun = true)
 | 
			
		||||
    public void dataPreparation() throws Exception {
 | 
			
		||||
        adminUser = dataUser.getAdminUser();
 | 
			
		||||
 | 
			
		||||
        testUser = dataUser.createRandomTestUser();
 | 
			
		||||
        testSite = dataSite.usingUser(testUser)
 | 
			
		||||
                           .createPublicRandomSite();
 | 
			
		||||
        testFolder = dataContent.usingUser(testUser)
 | 
			
		||||
                                .usingSite(testSite)
 | 
			
		||||
                                .createFolder();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void adminCanSendEmailUsingTemplateWithModelAsString() throws Exception
 | 
			
		||||
    {
 | 
			
		||||
        String templateId = uploadEmailTemplate("simpleEmailTemplate.ftl");
 | 
			
		||||
 | 
			
		||||
        // Create the model for use with email template
 | 
			
		||||
        JsonObject args = JsonBodyGenerator.defineJSON()
 | 
			
		||||
                                           .add("args", JsonBodyGenerator.defineJSON()
 | 
			
		||||
                                                                         .add("name", "testname")
 | 
			
		||||
                                                                         .build())
 | 
			
		||||
                                           .build();
 | 
			
		||||
        String emailModel = args.toString();
 | 
			
		||||
 | 
			
		||||
        // Send an email using the template
 | 
			
		||||
        restClient.authenticateUser(adminUser)
 | 
			
		||||
                  .withCoreAPI()
 | 
			
		||||
                  .usingActions()
 | 
			
		||||
                  .executeAction(MAIL_ACTION, testFolder, createMailWithTemplateParameters(adminUser, testUser, templateId, emailModel));
 | 
			
		||||
 | 
			
		||||
        restClient.onResponse()
 | 
			
		||||
                  .assertThat().statusCode(HttpStatus.ACCEPTED.value())
 | 
			
		||||
                  .assertThat().body("entry.id", notNullValue());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String uploadEmailTemplate(String templateName) throws IOException
 | 
			
		||||
    {
 | 
			
		||||
        final String templateContent = getTemplateContent(templateName);
 | 
			
		||||
        final FileModel templateToCreate = new FileModel(templateName, FileType.TEXT_PLAIN, templateContent);
 | 
			
		||||
 | 
			
		||||
        final FileModel createdTemplate = dataContent.usingAdmin()
 | 
			
		||||
                                                     .usingResource(testFolder)
 | 
			
		||||
                                                     .createContent(templateToCreate);
 | 
			
		||||
 | 
			
		||||
        return createdTemplate.getNodeRef();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String getTemplateContent(String templateName) throws IOException
 | 
			
		||||
    {
 | 
			
		||||
        final String templateClasspathLocation = "/shared-resources/testdata/" + templateName;
 | 
			
		||||
        try (InputStream templateStream = getClass().getResourceAsStream(templateClasspathLocation))
 | 
			
		||||
        {
 | 
			
		||||
            requireNonNull(templateStream, "Couldn't locate `" + templateClasspathLocation + "`");
 | 
			
		||||
            return new String(templateStream.readAllBytes());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static Map<String, Serializable> createMailWithTemplateParameters(UserModel sender, UserModel recipient, String templateId, Serializable model)
 | 
			
		||||
    {
 | 
			
		||||
        Map<String, Serializable> parameterValues = new HashMap<>();
 | 
			
		||||
 | 
			
		||||
        parameterValues.put("from", sender.getEmailAddress());
 | 
			
		||||
        parameterValues.put("to", recipient.getEmailAddress());
 | 
			
		||||
        parameterValues.put("subject", "Test");
 | 
			
		||||
        parameterValues.put("template", "workspace://SpacesStore/" + templateId);
 | 
			
		||||
        parameterValues.put("template_model", model);
 | 
			
		||||
 | 
			
		||||
        return parameterValues;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -25,6 +25,7 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.alfresco.rest.rules;
 | 
			
		||||
 | 
			
		||||
import static org.alfresco.rest.requests.RuleSettings.IS_INHERITANCE_ENABLED;
 | 
			
		||||
import static org.alfresco.utility.report.log.Step.STEP;
 | 
			
		||||
import static org.testng.Assert.assertEquals;
 | 
			
		||||
 | 
			
		||||
@@ -38,10 +39,12 @@ 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.rest.model.RestRuleSettingsModel;
 | 
			
		||||
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.springframework.http.HttpStatus;
 | 
			
		||||
import org.testng.annotations.BeforeClass;
 | 
			
		||||
import org.testng.annotations.Test;
 | 
			
		||||
 | 
			
		||||
@@ -71,26 +74,96 @@ public class GetInheritedRulesTests extends RestTest
 | 
			
		||||
        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 = rulesUtils.createRuleModelWithDefaultValues();
 | 
			
		||||
        RestRuleModel parentRule = rulesUtils.createInheritableRuleModel();
 | 
			
		||||
        parentRule = restClient.authenticateUser(user).withPrivateAPI().usingNode(parent).usingDefaultRuleSet().createSingleRule(parentRule);
 | 
			
		||||
        restClient.assertStatusCodeIs(HttpStatus.CREATED);
 | 
			
		||||
 | 
			
		||||
        RestRuleSettingsModel enabled = new RestRuleSettingsModel();
 | 
			
		||||
        enabled.setValue(true);
 | 
			
		||||
        restClient.authenticateUser(user).withPrivateAPI().usingNode(child).usingRuleSetting(IS_INHERITANCE_ENABLED).updateSetting(enabled);
 | 
			
		||||
        restClient.assertStatusCodeIs(HttpStatus.OK);
 | 
			
		||||
 | 
			
		||||
        RestRuleModel childRule = rulesUtils.createRuleModelWithDefaultValues();
 | 
			
		||||
        childRule = restClient.authenticateUser(user).withPrivateAPI().usingNode(child).usingDefaultRuleSet().createSingleRule(childRule);
 | 
			
		||||
        restClient.assertStatusCodeIs(HttpStatus.CREATED);
 | 
			
		||||
 | 
			
		||||
        STEP("Get the rules in the default rule set for the child folder");
 | 
			
		||||
        RestRuleModelsCollection rules = restClient.authenticateUser(user).withPrivateAPI().usingNode(child).usingDefaultRuleSet().getListOfRules();
 | 
			
		||||
        restClient.assertStatusCodeIs(HttpStatus.OK);
 | 
			
		||||
        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).withPrivateAPI().usingNode(child).include("inclusionType").getListOfRuleSets();
 | 
			
		||||
        restClient.assertStatusCodeIs(HttpStatus.OK);
 | 
			
		||||
        String inheritedRuleSetId = ruleSets.getEntries().stream()
 | 
			
		||||
                                            .filter(ruleSet -> ruleSet.onModel().getInclusionType().equals("inherited"))
 | 
			
		||||
                                            .findFirst().get().onModel().getId();
 | 
			
		||||
 | 
			
		||||
        RestRuleModelsCollection inheritedRules = restClient.authenticateUser(user).withPrivateAPI().usingNode(child).usingRuleSet(inheritedRuleSetId).getListOfRules();
 | 
			
		||||
        restClient.assertStatusCodeIs(HttpStatus.OK);
 | 
			
		||||
        inheritedRules.assertThat().entriesListContains("id", parentRule.getId())
 | 
			
		||||
                      .and().entriesListCountIs(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check we get no (inherited) rules when inheritance is disabled in the child folder.
 | 
			
		||||
     */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
 | 
			
		||||
    public void getInheritedRules_childFolderInheritanceDisabled()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Create a parent and child folder, with inheritable parent rule");
 | 
			
		||||
        FolderModel parent = dataContent.usingUser(user).usingSite(site).createFolder();
 | 
			
		||||
        FolderModel child = dataContent.usingUser(user).usingResource(parent).createFolder();
 | 
			
		||||
        RestRuleModel parentRule = rulesUtils.createInheritableRuleModel();
 | 
			
		||||
        restClient.authenticateUser(user).withPrivateAPI().usingNode(parent).usingDefaultRuleSet().createSingleRule(parentRule);
 | 
			
		||||
        restClient.assertStatusCodeIs(HttpStatus.CREATED);
 | 
			
		||||
 | 
			
		||||
        STEP("Disable inheritance in the child folder");
 | 
			
		||||
        RestRuleSettingsModel enabledInheritance = new RestRuleSettingsModel();
 | 
			
		||||
        enabledInheritance.setValue(false);
 | 
			
		||||
        restClient.authenticateUser(user).withPrivateAPI().usingNode(child).usingRuleSetting(IS_INHERITANCE_ENABLED).updateSetting(enabledInheritance);
 | 
			
		||||
        restClient.assertStatusCodeIs(HttpStatus.OK);
 | 
			
		||||
 | 
			
		||||
        STEP("The child folder should have no rule sets");
 | 
			
		||||
        RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withPrivateAPI().usingNode(child).getListOfRuleSets();
 | 
			
		||||
        restClient.assertStatusCodeIs(HttpStatus.OK);
 | 
			
		||||
        ruleSets.assertThat().entriesListIsEmpty();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check that non-inheritable rules owned by the parent folder are not found inside the child folder.
 | 
			
		||||
     */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
 | 
			
		||||
    public void inheritance_test()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Create a parent and child folder, with an inheritable and a non-inheritable parent rule");
 | 
			
		||||
        FolderModel parent = dataContent.usingUser(user).usingSite(site).createFolder();
 | 
			
		||||
        FolderModel child = dataContent.usingUser(user).usingResource(parent).createFolder();
 | 
			
		||||
 | 
			
		||||
        RestRuleModel inheritableRule = rulesUtils.createInheritableRuleModel();
 | 
			
		||||
        inheritableRule = restClient.authenticateUser(user).withPrivateAPI().usingNode(parent).usingDefaultRuleSet().createSingleRule(inheritableRule);
 | 
			
		||||
        restClient.assertStatusCodeIs(HttpStatus.CREATED);
 | 
			
		||||
 | 
			
		||||
        RestRuleModel nonInheritableRule = rulesUtils.createRuleModelWithDefaultValues();
 | 
			
		||||
        nonInheritableRule = restClient.authenticateUser(user).withPrivateAPI().usingNode(parent).usingDefaultRuleSet().createSingleRule(nonInheritableRule);
 | 
			
		||||
        restClient.assertStatusCodeIs(HttpStatus.CREATED);
 | 
			
		||||
 | 
			
		||||
        STEP("The inherited rule set for the child folder should only return the inheritable rule");
 | 
			
		||||
        RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withPrivateAPI().usingNode(child).include("inclusionType").getListOfRuleSets();
 | 
			
		||||
        restClient.assertStatusCodeIs(HttpStatus.OK);
 | 
			
		||||
 | 
			
		||||
        String inheritedRuleSetId = ruleSets.getEntries().stream()
 | 
			
		||||
                .filter(ruleSet -> ruleSet.onModel().getInclusionType().equals("inherited"))
 | 
			
		||||
                .findFirst().get().onModel().getId();
 | 
			
		||||
 | 
			
		||||
        RestRuleModelsCollection inheritedRules = restClient.authenticateUser(user).withPrivateAPI().usingNode(child).usingRuleSet(inheritedRuleSetId).getListOfRules();
 | 
			
		||||
        restClient.assertStatusCodeIs(HttpStatus.OK);
 | 
			
		||||
        inheritedRules.assertThat().entriesListContains("id", inheritableRule.getId())
 | 
			
		||||
                             .and().entriesListDoesNotContain("id",nonInheritableRule.getId())
 | 
			
		||||
                             .and().entriesListCountIs(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check that we only get each rule once with linking and inheritance, and the order is correct.
 | 
			
		||||
     * <p>
 | 
			
		||||
@@ -110,9 +183,14 @@ public class GetInheritedRulesTests extends RestTest
 | 
			
		||||
        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).withPrivateAPI().usingNode(folderB).usingDefaultRuleSet().createSingleRule(rulesUtils.createRuleModelWithDefaultValues());
 | 
			
		||||
        RestRuleModel ruleC = restClient.authenticateUser(user).withPrivateAPI().usingNode(folderC).usingDefaultRuleSet().createSingleRule(rulesUtils.createRuleModelWithDefaultValues());
 | 
			
		||||
        RestRuleModel ruleB = restClient.authenticateUser(user).withPrivateAPI().usingNode(folderB).usingDefaultRuleSet().createSingleRule(rulesUtils.createInheritableRuleModel());
 | 
			
		||||
        RestRuleModel ruleC = restClient.authenticateUser(user).withPrivateAPI().usingNode(folderC).usingDefaultRuleSet().createSingleRule(rulesUtils.createInheritableRuleModel());
 | 
			
		||||
        RestRuleModel ruleD = restClient.authenticateUser(user).withPrivateAPI().usingNode(folderD).usingDefaultRuleSet().createSingleRule(rulesUtils.createRuleModelWithDefaultValues());
 | 
			
		||||
        RestRuleSettingsModel enabled = new RestRuleSettingsModel();
 | 
			
		||||
        enabled.setValue(true);
 | 
			
		||||
        restClient.authenticateUser(user).withPrivateAPI().usingNode(folderC).usingRuleSetting(IS_INHERITANCE_ENABLED).updateSetting(enabled);
 | 
			
		||||
        restClient.authenticateUser(user).withPrivateAPI().usingNode(folderD).usingRuleSetting(IS_INHERITANCE_ENABLED).updateSetting(enabled);
 | 
			
		||||
 | 
			
		||||
        STEP("Link folderA to ruleSetD");
 | 
			
		||||
        RestRuleSetLinkModel linkModel = new RestRuleSetLinkModel();
 | 
			
		||||
        linkModel.setId(folderD.getNodeRef());
 | 
			
		||||
 
 | 
			
		||||
@@ -46,6 +46,7 @@ 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.springframework.http.HttpStatus;
 | 
			
		||||
import org.testng.annotations.BeforeClass;
 | 
			
		||||
import org.testng.annotations.Test;
 | 
			
		||||
 | 
			
		||||
@@ -172,6 +173,56 @@ public class RuleSetLinksTests extends RestTest
 | 
			
		||||
                .get(0).onModel().assertThat().isEqualTo(expectedRuleSet);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check we can link to a rule set when linking from a folder which has inherited rules.
 | 
			
		||||
     */
 | 
			
		||||
    @Test(groups = {TestGroup.REST_API, TestGroup.RULES})
 | 
			
		||||
    public void linkFromFolderWithInheritedRules()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Create folders");
 | 
			
		||||
        final FolderModel parentFolder = dataContent.usingUser(user).usingSite(site).createFolder();
 | 
			
		||||
        final FolderModel childFolder = dataContent.usingUser(user).usingResource(parentFolder).createFolder();
 | 
			
		||||
        final FolderModel linkedToFolder = dataContent.usingUser(user).usingSite(site).createFolder();
 | 
			
		||||
 | 
			
		||||
        STEP("Create rules in the parent folder and the linking folder");
 | 
			
		||||
        RestRuleModel parentRule = rulesUtils.createInheritableRuleModel();
 | 
			
		||||
        parentRule = restClient.authenticateUser(user).withPrivateAPI().usingNode(parentFolder).usingDefaultRuleSet().createSingleRule(parentRule);
 | 
			
		||||
        restClient.assertStatusCodeIs(CREATED);
 | 
			
		||||
 | 
			
		||||
        RestRuleModel linkingFolderRule = rulesUtils.createRuleModelWithDefaultValues();
 | 
			
		||||
        restClient.authenticateUser(user).withPrivateAPI().usingNode(linkedToFolder).usingDefaultRuleSet().createSingleRule(linkingFolderRule);
 | 
			
		||||
        restClient.assertStatusCodeIs(CREATED);
 | 
			
		||||
 | 
			
		||||
        STEP("Get the rule sets for the linking folder and find the rule set id");
 | 
			
		||||
        final RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withPrivateAPI().usingNode(linkedToFolder).getListOfRuleSets();
 | 
			
		||||
        restClient.assertStatusCodeIs(OK);
 | 
			
		||||
        ruleSets.assertThat().entriesListCountIs(1);
 | 
			
		||||
        final String ruleSetId = ruleSets.getEntries().get(0).onModel().getId();
 | 
			
		||||
 | 
			
		||||
        STEP("Link the child folder to the target folder");
 | 
			
		||||
        final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
 | 
			
		||||
        request.setId(linkedToFolder.getNodeRef());
 | 
			
		||||
        final RestRuleSetLinkModel ruleLink = restClient.authenticateUser(user).withPrivateAPI().usingNode(childFolder).createRuleLink(request);
 | 
			
		||||
        restClient.assertStatusCodeIs(CREATED);
 | 
			
		||||
 | 
			
		||||
        STEP("Assert link result");
 | 
			
		||||
        final RestRuleSetLinkModel expectedLink = new RestRuleSetLinkModel();
 | 
			
		||||
        expectedLink.setId(ruleSetId);
 | 
			
		||||
        ruleLink.assertThat().isEqualTo(expectedLink);
 | 
			
		||||
 | 
			
		||||
        STEP("Assert that the child folder has also inherited the parent rule");
 | 
			
		||||
        RestRuleSetModelsCollection ruleSetsInh = restClient.authenticateUser(user).withPrivateAPI().usingNode(childFolder).include("inclusionType").getListOfRuleSets();
 | 
			
		||||
        restClient.assertStatusCodeIs(OK);
 | 
			
		||||
        String inheritedRuleSetId = ruleSetsInh.getEntries().stream()
 | 
			
		||||
                .filter(ruleSet -> ruleSet.onModel().getInclusionType().equals("inherited"))
 | 
			
		||||
                .findFirst().get().onModel().getId();
 | 
			
		||||
 | 
			
		||||
        RestRuleModelsCollection inheritedRules = restClient.authenticateUser(user).withPrivateAPI().usingNode(childFolder).usingRuleSet(inheritedRuleSetId).getListOfRules();
 | 
			
		||||
        restClient.assertStatusCodeIs(OK);
 | 
			
		||||
        inheritedRules.assertThat().entriesListContains("id", parentRule.getId())
 | 
			
		||||
                .and().entriesListCountIs(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check we get 404 when linking to a non-existing rule set/folder.
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -213,6 +213,13 @@ public class RulesTestsUtils
 | 
			
		||||
        return createRuleModel(RULE_NAME_DEFAULT);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public RestRuleModel createInheritableRuleModel()
 | 
			
		||||
    {
 | 
			
		||||
        RestRuleModel ruleModel = createRuleModel(RULE_NAME_DEFAULT);
 | 
			
		||||
        ruleModel.setIsInheritable(true);
 | 
			
		||||
        return ruleModel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public RestRuleModel createRuleModel(String name)
 | 
			
		||||
    {
 | 
			
		||||
        return createRuleModel(name, List.of(createAddAudioAspectAction()));
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
<html>
 | 
			
		||||
<head></head>
 | 
			
		||||
<body>
 | 
			
		||||
Hello ${args.name}!
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo-tests</artifactId>
 | 
			
		||||
        <version>20.19</version>
 | 
			
		||||
        <version>20.28-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <developers>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo-packaging</artifactId>
 | 
			
		||||
        <version>20.19</version>
 | 
			
		||||
        <version>20.28-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <properties>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								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>20.19</version>
 | 
			
		||||
    <version>20.28-SNAPSHOT</version>
 | 
			
		||||
    <packaging>pom</packaging>
 | 
			
		||||
    <name>Alfresco Community Repo Parent</name>
 | 
			
		||||
 | 
			
		||||
@@ -109,7 +109,7 @@
 | 
			
		||||
        <dependency.jakarta-json-path.version>2.7.0</dependency.jakarta-json-path.version>
 | 
			
		||||
        <dependency.jakarta-rpc-api.version>1.1.4</dependency.jakarta-rpc-api.version>
 | 
			
		||||
 | 
			
		||||
        <alfresco.googledrive.version>3.3.1-A2</alfresco.googledrive.version>
 | 
			
		||||
        <alfresco.googledrive.version>3.3.1-A3</alfresco.googledrive.version>
 | 
			
		||||
        <alfresco.aos-module.version>1.5.0</alfresco.aos-module.version>
 | 
			
		||||
        <alfresco.api-explorer.version>7.3.0</alfresco.api-explorer.version> <!-- Also in alfresco-enterprise-share -->
 | 
			
		||||
 | 
			
		||||
@@ -149,7 +149,7 @@
 | 
			
		||||
        <connection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</connection>
 | 
			
		||||
        <developerConnection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</developerConnection>
 | 
			
		||||
        <url>https://github.com/Alfresco/alfresco-community-repo</url>
 | 
			
		||||
        <tag>20.19</tag>
 | 
			
		||||
        <tag>HEAD</tag>
 | 
			
		||||
    </scm>
 | 
			
		||||
 | 
			
		||||
    <distributionManagement>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo</artifactId>
 | 
			
		||||
        <version>20.19</version>
 | 
			
		||||
        <version>20.28-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <dependencies>
 | 
			
		||||
 
 | 
			
		||||
@@ -363,13 +363,13 @@ public class ActionsImpl implements Actions
 | 
			
		||||
                        Map.Entry::getValue));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private Map<String, Serializable> extractActionParams(org.alfresco.service.cmr.action.ActionDefinition actionDefinition, Map<String, String> params)
 | 
			
		||||
    private Map<String, Serializable> extractActionParams(org.alfresco.service.cmr.action.ActionDefinition actionDefinition, Map<String, ?> params)
 | 
			
		||||
    {
 | 
			
		||||
        Map<String, Serializable> parameterValues = new HashMap<>();
 | 
			
		||||
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            for (Map.Entry<String, String> entry : params.entrySet())
 | 
			
		||||
            for (Map.Entry<String, ?> entry : params.entrySet())
 | 
			
		||||
            {
 | 
			
		||||
                String propertyName = entry.getKey();
 | 
			
		||||
                Object propertyValue = entry.getValue();
 | 
			
		||||
 
 | 
			
		||||
@@ -170,7 +170,7 @@ public class RuleSetsImpl implements RuleSets
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //The folder shouldn't have any pre-existing rules
 | 
			
		||||
        if (ruleService.hasRules(folderNodeRef)) {
 | 
			
		||||
        if (ruleService.hasNonInheritedRules(folderNodeRef)) {
 | 
			
		||||
            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.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -26,17 +26,12 @@
 | 
			
		||||
 | 
			
		||||
package org.alfresco.rest.api.impl.rules;
 | 
			
		||||
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.repo.action.ActionImpl;
 | 
			
		||||
import org.alfresco.repo.action.access.ActionAccessRestriction;
 | 
			
		||||
import org.alfresco.repo.action.executer.ExecuteAllRulesActionExecuter;
 | 
			
		||||
import org.alfresco.rest.api.Rules;
 | 
			
		||||
import org.alfresco.rest.api.model.mapper.RestModelMapper;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.InclusionType;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.Rule;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.RuleExecution;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.RuleSet;
 | 
			
		||||
@@ -53,6 +48,14 @@ import org.apache.commons.collections.CollectionUtils;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
import static org.alfresco.rest.api.impl.rules.RuleSetLoader.INCLUSION_TYPE;
 | 
			
		||||
 | 
			
		||||
@Experimental
 | 
			
		||||
public class RulesImpl implements Rules
 | 
			
		||||
{
 | 
			
		||||
@@ -63,6 +66,7 @@ public class RulesImpl implements Rules
 | 
			
		||||
    private RuleService ruleService;
 | 
			
		||||
    private NodeValidator validator;
 | 
			
		||||
    private RuleLoader ruleLoader;
 | 
			
		||||
    private RuleSetLoader ruleSetLoader;
 | 
			
		||||
    private ActionPermissionValidator actionPermissionValidator;
 | 
			
		||||
    private RestModelMapper<Rule, org.alfresco.service.cmr.rule.Rule> ruleMapper;
 | 
			
		||||
 | 
			
		||||
@@ -75,8 +79,10 @@ public class RulesImpl implements Rules
 | 
			
		||||
        final NodeRef folderNodeRef = validator.validateFolderNode(folderNodeId, false);
 | 
			
		||||
        NodeRef ruleSetNode = validator.validateRuleSetNode(ruleSetId, folderNodeRef);
 | 
			
		||||
        NodeRef owningFolder = ruleService.getOwningNodeRef(ruleSetNode);
 | 
			
		||||
        RuleSet ruleSet = ruleSetLoader.loadRuleSet(ruleSetNode, folderNodeRef, List.of(INCLUSION_TYPE));
 | 
			
		||||
 | 
			
		||||
        final List<Rule> rules = ruleService.getRules(owningFolder, false).stream()
 | 
			
		||||
                .filter(ruleModel -> ruleSet.getInclusionType() != InclusionType.INHERITED || ruleModel.isAppliedToChildren())
 | 
			
		||||
                .map(ruleModel -> ruleLoader.loadRule(ruleModel, includes))
 | 
			
		||||
                .collect(Collectors.toList());
 | 
			
		||||
 | 
			
		||||
@@ -182,6 +188,11 @@ public class RulesImpl implements Rules
 | 
			
		||||
        this.ruleLoader = ruleLoader;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setRuleSetLoader(RuleSetLoader ruleSetLoader)
 | 
			
		||||
    {
 | 
			
		||||
        this.ruleSetLoader = ruleSetLoader;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setActionPermissionValidator(ActionPermissionValidator actionPermissionValidator)
 | 
			
		||||
    {
 | 
			
		||||
        this.actionPermissionValidator = actionPermissionValidator;
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@ public class Action
 | 
			
		||||
    private String id;
 | 
			
		||||
    private String actionDefinitionId;
 | 
			
		||||
    private String targetId;
 | 
			
		||||
    Map<String, String> params;
 | 
			
		||||
    private Map<String, ?> params;
 | 
			
		||||
 | 
			
		||||
    public String getId()
 | 
			
		||||
    {
 | 
			
		||||
@@ -64,12 +64,12 @@ public class Action
 | 
			
		||||
        this.targetId = targetId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Map<String, String> getParams()
 | 
			
		||||
    public Map<String, ?> getParams()
 | 
			
		||||
    {
 | 
			
		||||
        return params;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setParams(Map<String, String> params)
 | 
			
		||||
    public void setParams(Map<String, ? extends Object> params)
 | 
			
		||||
    {
 | 
			
		||||
        this.params = params;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -929,6 +929,7 @@
 | 
			
		||||
        <property name="validator" ref="nodeValidator"/>
 | 
			
		||||
        <property name="ruleService" ref="RuleService" />
 | 
			
		||||
        <property name="ruleLoader" ref="ruleLoader"/>
 | 
			
		||||
        <property name="ruleSetLoader" ref="ruleSetLoader"/>
 | 
			
		||||
        <property name="actionPermissionValidator" ref="actionPermissionValidator"/>
 | 
			
		||||
        <property name="ruleMapper" ref="ruleMapper"/>
 | 
			
		||||
    </bean>
 | 
			
		||||
 
 | 
			
		||||
@@ -257,7 +257,7 @@ public class RuleSetsImplTest extends TestCase
 | 
			
		||||
        String actual = ruleSets.linkToRuleSet(FOLDER_ID,LINK_TO_NODE_ID).getId();
 | 
			
		||||
 | 
			
		||||
        then(ruleServiceMock).should().hasRules(LINK_TO_NODE);
 | 
			
		||||
        then(ruleServiceMock).should().hasRules(FOLDER_NODE);
 | 
			
		||||
        then(ruleServiceMock).should().hasNonInheritedRules(FOLDER_NODE);
 | 
			
		||||
        then(runtimeRuleServiceMock).should().getSavedRuleFolderAssoc(LINK_TO_NODE);
 | 
			
		||||
        then(runtimeRuleServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(nodeServiceMock).should().addChild(FOLDER_NODE, childNodeRef, RuleModel.ASSOC_RULE_FOLDER, RuleModel.ASSOC_RULE_FOLDER);
 | 
			
		||||
@@ -284,7 +284,7 @@ public class RuleSetsImplTest extends TestCase
 | 
			
		||||
        then(nodeValidatorMock).should().validateRuleSetNode(LINK_TO_NODE_ID,false);
 | 
			
		||||
        then(nodeValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(ruleServiceMock).should().hasRules(LINK_TO_NODE);
 | 
			
		||||
        then(ruleServiceMock).should().hasRules(FOLDER_NODE);
 | 
			
		||||
        then(ruleServiceMock).should().hasNonInheritedRules(FOLDER_NODE);
 | 
			
		||||
        then(runtimeRuleServiceMock).should().getSavedRuleFolderAssoc(LINK_TO_NODE);
 | 
			
		||||
        then(runtimeRuleServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(nodeServiceMock).should().addChild(FOLDER_NODE, childNodeRef, RuleModel.ASSOC_RULE_FOLDER, RuleModel.ASSOC_RULE_FOLDER);
 | 
			
		||||
@@ -312,7 +312,8 @@ public class RuleSetsImplTest extends TestCase
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testLinkToRuleSet_folderShouldntHavePreExistingRules()
 | 
			
		||||
    {
 | 
			
		||||
        given(ruleServiceMock.hasRules(any(NodeRef.class))).willReturn(true, true);
 | 
			
		||||
        given(ruleServiceMock.hasRules(any(NodeRef.class))).willReturn(true);
 | 
			
		||||
        given(ruleServiceMock.hasNonInheritedRules(any(NodeRef.class))).willReturn(true);
 | 
			
		||||
 | 
			
		||||
        //when
 | 
			
		||||
        assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(
 | 
			
		||||
@@ -320,7 +321,7 @@ public class RuleSetsImplTest extends TestCase
 | 
			
		||||
 | 
			
		||||
        then(nodeServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(ruleServiceMock).should().hasRules(LINK_TO_NODE);
 | 
			
		||||
        then(ruleServiceMock).should().hasRules(FOLDER_NODE);
 | 
			
		||||
        then(ruleServiceMock).should().hasNonInheritedRules(FOLDER_NODE);
 | 
			
		||||
        then(ruleServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(runtimeRuleServiceMock).shouldHaveNoInteractions();
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -28,6 +28,7 @@ package org.alfresco.rest.api.impl.rules;
 | 
			
		||||
 | 
			
		||||
import static java.util.Collections.emptyList;
 | 
			
		||||
 | 
			
		||||
import static org.alfresco.rest.api.impl.rules.RuleSetLoader.INCLUSION_TYPE;
 | 
			
		||||
import static org.alfresco.rest.api.model.rules.RuleSet.DEFAULT_ID;
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
 | 
			
		||||
@@ -51,8 +52,10 @@ import org.alfresco.repo.action.executer.ExecuteAllRulesActionExecuter;
 | 
			
		||||
import org.alfresco.rest.api.Nodes;
 | 
			
		||||
import org.alfresco.rest.api.model.mapper.RestModelMapper;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.Action;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.InclusionType;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.Rule;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.RuleExecution;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.RuleSet;
 | 
			
		||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
 | 
			
		||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
 | 
			
		||||
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
 | 
			
		||||
@@ -80,6 +83,7 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
    private static final String FOLDER_NODE_ID = "dummy-folder-node-id";
 | 
			
		||||
    private static final String RULE_SET_ID = "dummy-rule-set-id";
 | 
			
		||||
    private static final String RULE_ID = "dummy-rule-id";
 | 
			
		||||
    private static final String RULE_ID_INHERITED = "dummy-rule-id-inherited";
 | 
			
		||||
    private static final NodeRef FOLDER_NODE_REF = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, FOLDER_NODE_ID);
 | 
			
		||||
    private static final NodeRef RULE_SET_NODE_REF = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, RULE_SET_ID);
 | 
			
		||||
    private static final NodeRef RULE_NODE_REF = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, RULE_ID);
 | 
			
		||||
@@ -101,15 +105,20 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
    @Mock
 | 
			
		||||
    private RuleLoader ruleLoaderMock;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private RuleSetLoader ruleSetLoaderMock;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private ActionPermissionValidator actionPermissionValidatorMock;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private org.alfresco.service.cmr.rule.Rule serviceRuleMock;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private Rule ruleMock;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private RuleSet ruleSetMock;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private Action actionMock;
 | 
			
		||||
 | 
			
		||||
    private org.alfresco.service.cmr.rule.Rule ruleModel = createRule(RULE_ID);
 | 
			
		||||
    private org.alfresco.service.cmr.rule.Rule ruleModelInherited = createRule(RULE_ID_INHERITED);
 | 
			
		||||
 | 
			
		||||
    @InjectMocks
 | 
			
		||||
    private RulesImpl rules;
 | 
			
		||||
@@ -118,6 +127,9 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
    @Override
 | 
			
		||||
    public void setUp() throws Exception
 | 
			
		||||
    {
 | 
			
		||||
        ruleModel.applyToChildren(true);
 | 
			
		||||
        ruleModelInherited.applyToChildren(true);
 | 
			
		||||
 | 
			
		||||
        given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(FOLDER_NODE_REF);
 | 
			
		||||
        given(nodeValidatorMock.validateRuleSetNode(any(), any())).willReturn(RULE_SET_NODE_REF);
 | 
			
		||||
        given(nodeValidatorMock.validateRuleNode(any(), any())).willReturn(RULE_NODE_REF);
 | 
			
		||||
@@ -126,13 +138,15 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
        given(ruleServiceMock.getRules(FOLDER_NODE_REF, false)).willReturn(List.of(ruleModel));
 | 
			
		||||
        given(ruleServiceMock.getOwningNodeRef(RULE_SET_NODE_REF)).willReturn(FOLDER_NODE_REF);
 | 
			
		||||
 | 
			
		||||
        given(ruleSetMock.getInclusionType()).willReturn(InclusionType.INHERITED);
 | 
			
		||||
 | 
			
		||||
        given(ruleLoaderMock.loadRule(ruleModel, INCLUDE)).willReturn(ruleMock);
 | 
			
		||||
        given(ruleSetLoaderMock.loadRuleSet(RULE_SET_NODE_REF, FOLDER_NODE_REF, List.of(INCLUSION_TYPE))).willReturn(ruleSetMock);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    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);
 | 
			
		||||
@@ -141,6 +155,66 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
        then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
 | 
			
		||||
        then(nodeValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(ruleServiceMock).should().getOwningNodeRef(RULE_SET_NODE_REF);
 | 
			
		||||
        then(ruleSetLoaderMock).should().loadRuleSet(RULE_SET_NODE_REF, FOLDER_NODE_REF, List.of(INCLUSION_TYPE));
 | 
			
		||||
        then(ruleSetLoaderMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(ruleServiceMock).should().getRules(FOLDER_NODE_REF, false);
 | 
			
		||||
        then(ruleServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(ruleLoaderMock).should().loadRule(ruleModel, emptyList());
 | 
			
		||||
        then(ruleLoaderMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        assertThat(rulesPage)
 | 
			
		||||
                .isNotNull()
 | 
			
		||||
                .extracting(CollectionWithPagingInfo::getCollection)
 | 
			
		||||
                .isNotNull()
 | 
			
		||||
                .extracting(Collection::size)
 | 
			
		||||
                .isEqualTo(1);
 | 
			
		||||
        assertThat(rulesPage.getCollection().stream().findFirst().get()).isEqualTo(ruleMock);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testGetRules_ruleNotAppliedToChildren()
 | 
			
		||||
    {
 | 
			
		||||
        given(ruleSetMock.getInclusionType()).willReturn(InclusionType.INHERITED);
 | 
			
		||||
        given(ruleServiceMock.getRules(FOLDER_NODE_REF, false)).willReturn(List.of(ruleModel, ruleModelInherited));
 | 
			
		||||
        ruleModelInherited.applyToChildren(false);
 | 
			
		||||
 | 
			
		||||
        // 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().getOwningNodeRef(RULE_SET_NODE_REF);
 | 
			
		||||
        then(ruleSetLoaderMock).should().loadRuleSet(RULE_SET_NODE_REF, FOLDER_NODE_REF, List.of(INCLUSION_TYPE));
 | 
			
		||||
        then(ruleSetLoaderMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(ruleServiceMock).should().getRules(FOLDER_NODE_REF, false);
 | 
			
		||||
        then(ruleServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(ruleLoaderMock).should().loadRule(ruleModel, emptyList());
 | 
			
		||||
        then(ruleLoaderMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        assertThat(rulesPage)
 | 
			
		||||
                .isNotNull()
 | 
			
		||||
                .extracting(CollectionWithPagingInfo::getCollection)
 | 
			
		||||
                .isNotNull()
 | 
			
		||||
                .extracting(Collection::size)
 | 
			
		||||
                .isEqualTo(1);
 | 
			
		||||
        assertThat(rulesPage.getCollection().stream().findFirst().get()).isEqualTo(ruleMock);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testGetRules_inheritedRuleSet()
 | 
			
		||||
    {
 | 
			
		||||
        given(ruleSetMock.getInclusionType()).willReturn(InclusionType.INHERITED);
 | 
			
		||||
        ruleModelInherited.applyToChildren(false);
 | 
			
		||||
        given(ruleServiceMock.getRules(FOLDER_NODE_REF, false)).willReturn(List.of(ruleModel, ruleModelInherited));
 | 
			
		||||
 | 
			
		||||
        // 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().getOwningNodeRef(RULE_SET_NODE_REF);
 | 
			
		||||
        then(ruleSetLoaderMock).should().loadRuleSet(RULE_SET_NODE_REF, FOLDER_NODE_REF, List.of(INCLUSION_TYPE));
 | 
			
		||||
        then(ruleSetLoaderMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(ruleServiceMock).should().getRules(FOLDER_NODE_REF, false);
 | 
			
		||||
        then(ruleServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(ruleLoaderMock).should().loadRule(ruleModel, emptyList());
 | 
			
		||||
@@ -163,6 +237,8 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
        final CollectionWithPagingInfo<Rule> rulesPage = rules.getRules(FOLDER_NODE_ID, RULE_SET_ID, INCLUDE, PAGING);
 | 
			
		||||
 | 
			
		||||
        then(ruleServiceMock).should().getOwningNodeRef(RULE_SET_NODE_REF);
 | 
			
		||||
        then(ruleSetLoaderMock).should().loadRuleSet(RULE_SET_NODE_REF, FOLDER_NODE_REF, List.of(INCLUSION_TYPE));
 | 
			
		||||
        then(ruleSetLoaderMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(ruleServiceMock).should().getRules(FOLDER_NODE_REF, false);
 | 
			
		||||
        then(ruleServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        assertThat(rulesPage)
 | 
			
		||||
 
 | 
			
		||||
@@ -78,7 +78,7 @@ public class Action extends org.alfresco.rest.api.model.Action implements Serial
 | 
			
		||||
        String id = (String) jsonObject.get("id");
 | 
			
		||||
        String actionDefinitionId = (String) jsonObject.get("actionDefinitionId");
 | 
			
		||||
        String targetId = (String) jsonObject.get("targetId");
 | 
			
		||||
        Map<String, String> params = (Map<String, String>) jsonObject.get("params");
 | 
			
		||||
        Map<String, Object> params = (Map<String, Object>) jsonObject.get("params");
 | 
			
		||||
 | 
			
		||||
        Action action = new Action();
 | 
			
		||||
        action.setId(id);
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo</artifactId>
 | 
			
		||||
        <version>20.19</version>
 | 
			
		||||
        <version>20.28-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <dependencies>
 | 
			
		||||
 
 | 
			
		||||
@@ -459,7 +459,13 @@ public class RuleServiceImpl
 | 
			
		||||
    public boolean hasRules(NodeRef nodeRef)
 | 
			
		||||
    {
 | 
			
		||||
        return getRules(nodeRef).size() != 0;
 | 
			
		||||
    } 
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean hasNonInheritedRules(NodeRef nodeRef)
 | 
			
		||||
    {
 | 
			
		||||
        return getRules(nodeRef, false).size() != 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<Rule> getRules(NodeRef nodeRef)
 | 
			
		||||
 
 | 
			
		||||
@@ -165,6 +165,15 @@ public interface RuleService
 | 
			
		||||
    @Auditable(parameters = {"nodeRef"})
 | 
			
		||||
    public boolean hasRules(NodeRef nodeRef);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Indicates whether the node in question has any non-inherited rules associated with it.
 | 
			
		||||
     *
 | 
			
		||||
     * @param nodeRef   the node reference
 | 
			
		||||
     * @return          true if the node has rules associated, false otherwise
 | 
			
		||||
     */
 | 
			
		||||
    @Auditable(parameters = {"nodeRef"})
 | 
			
		||||
    public boolean hasNonInheritedRules(NodeRef nodeRef);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get all the rules associated with an actionable node, including those
 | 
			
		||||
     * inherited from parents.
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user