[ACS-9697] Backport to 23.N (#3375)

This commit is contained in:
SatyamSah5
2025-06-05 16:23:23 +05:30
committed by GitHub
parent dcf9f65f6b
commit 9bfd274127
2 changed files with 109 additions and 118 deletions

View File

@@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited * Copyright (C) 2005 - 2025 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
@@ -26,6 +26,13 @@
package org.alfresco.rest.rules; package org.alfresco.rest.rules;
import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toList;
import static org.junit.Assert.assertEquals;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.CREATED;
import static org.springframework.http.HttpStatus.FORBIDDEN;
import static org.springframework.http.HttpStatus.NOT_FOUND;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.ERROR_MESSAGE_ACCESS_RESTRICTED; import static org.alfresco.rest.actions.access.AccessRestrictionUtil.ERROR_MESSAGE_ACCESS_RESTRICTED;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.MAIL_ACTION; import static org.alfresco.rest.actions.access.AccessRestrictionUtil.MAIL_ACTION;
import static org.alfresco.rest.rules.RulesTestsUtils.CHECKIN_ACTION; import static org.alfresco.rest.rules.RulesTestsUtils.CHECKIN_ACTION;
@@ -45,11 +52,6 @@ import static org.alfresco.utility.model.FileModel.getRandomFileModel;
import static org.alfresco.utility.model.FileType.TEXT_PLAIN; import static org.alfresco.utility.model.FileType.TEXT_PLAIN;
import static org.alfresco.utility.model.UserModel.getRandomUserModel; import static org.alfresco.utility.model.UserModel.getRandomUserModel;
import static org.alfresco.utility.report.log.Step.STEP; import static org.alfresco.utility.report.log.Step.STEP;
import static org.junit.Assert.assertEquals;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.CREATED;
import static org.springframework.http.HttpStatus.FORBIDDEN;
import static org.springframework.http.HttpStatus.NOT_FOUND;
import java.io.Serializable; import java.io.Serializable;
import java.util.Collections; import java.util.Collections;
@@ -61,10 +63,13 @@ import java.util.stream.IntStream;
import jakarta.json.Json; import jakarta.json.Json;
import jakarta.json.JsonObject; import jakarta.json.JsonObject;
import org.apache.chemistry.opencmis.client.api.CmisObject;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.alfresco.rest.model.RestActionBodyExecTemplateModel; import org.alfresco.rest.model.RestActionBodyExecTemplateModel;
import org.alfresco.rest.model.RestActionConstraintModel; import org.alfresco.rest.model.RestActionConstraintModel;
import org.alfresco.rest.model.RestCompositeConditionDefinitionModel; import org.alfresco.rest.model.RestCompositeConditionDefinitionModel;
import org.alfresco.rest.model.RestPaginationModel;
import org.alfresco.rest.model.RestRuleModel; import org.alfresco.rest.model.RestRuleModel;
import org.alfresco.rest.model.RestRuleModelsCollection; import org.alfresco.rest.model.RestRuleModelsCollection;
import org.alfresco.utility.constants.UserRole; import org.alfresco.utility.constants.UserRole;
@@ -74,9 +79,6 @@ import org.alfresco.utility.model.FolderModel;
import org.alfresco.utility.model.SiteModel; import org.alfresco.utility.model.SiteModel;
import org.alfresco.utility.model.TestGroup; import org.alfresco.utility.model.TestGroup;
import org.alfresco.utility.model.UserModel; import org.alfresco.utility.model.UserModel;
import org.apache.chemistry.opencmis.client.api.CmisObject;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/** /**
* Tests for POST /nodes/{nodeId}/rule-sets/{ruleSetId}/rules. * Tests for POST /nodes/{nodeId}/rule-sets/{ruleSetId}/rules.
@@ -263,8 +265,7 @@ public class CreateRulesTests extends RulesRestTest
restClient.assertStatusCodeIs(CREATED); restClient.assertStatusCodeIs(CREATED);
assertEquals("Unexpected number of rules received in response.", ruleNames.size(), rules.getEntries().size()); assertEquals("Unexpected number of rules received in response.", ruleNames.size(), rules.getEntries().size());
IntStream.range(0, ruleModels.size()).forEach(i -> IntStream.range(0, ruleModels.size()).forEach(i -> rules.getEntries().get(i).onModel()
rules.getEntries().get(i).onModel()
.assertThat().field("id").isNotNull() .assertThat().field("id").isNotNull()
.assertThat().field("name").is(ruleNames.get(i))); .assertThat().field("name").is(ruleNames.get(i)));
} }
@@ -287,8 +288,7 @@ public class CreateRulesTests extends RulesRestTest
restClient.assertStatusCodeIs(CREATED); restClient.assertStatusCodeIs(CREATED);
assertEquals("Unexpected number of rules received in response.", ruleCount, rules.getEntries().size()); assertEquals("Unexpected number of rules received in response.", ruleCount, rules.getEntries().size());
IntStream.range(0, ruleModels.size()).forEach(i -> IntStream.range(0, ruleModels.size()).forEach(i -> rules.getEntries().get(i).onModel()
rules.getEntries().get(i).onModel()
.assertThat().field("id").isNotNull() .assertThat().field("id").isNotNull()
.assertThat().field("name").is(ruleNamePrefix + (i + 1))); .assertThat().field("name").is(ruleNamePrefix + (i + 1)));
@@ -454,11 +454,7 @@ public class CreateRulesTests extends RulesRestTest
STEP("Create another user as a coordinator for this folder."); STEP("Create another user as a coordinator for this folder.");
UserModel coordinator = dataUser.createRandomTestUser("Rules"); UserModel coordinator = dataUser.createRandomTestUser("Rules");
/* /* Update folder node properties to add a coordinator { "permissions": { "isInheritanceEnabled": true, "locallySet": { "authorityId": "coordinator.getUsername()", "name": "Coordinator", "accessStatus":"ALLOWED" } } } */
Update folder node properties to add a coordinator
{ "permissions": { "isInheritanceEnabled": true, "locallySet": { "authorityId": "coordinator.getUsername()",
"name": "Coordinator", "accessStatus":"ALLOWED" } } }
*/
String putBody = getAddPermissionsBody(coordinator.getUsername(), "Coordinator"); String putBody = getAddPermissionsBody(coordinator.getUsername(), "Coordinator");
restClient.authenticateUser(user).withCoreAPI().usingNode(folder).updateNode(putBody); restClient.authenticateUser(user).withCoreAPI().usingNode(folder).updateNode(putBody);
@@ -478,11 +474,7 @@ public class CreateRulesTests extends RulesRestTest
STEP("Create another user as a editor for this folder."); STEP("Create another user as a editor for this folder.");
UserModel editor = dataUser.createRandomTestUser(); UserModel editor = dataUser.createRandomTestUser();
/* /* Update folder node properties to add an editor { "permissions": { "isInheritanceEnabled": true, "locallySet": { "authorityId": "editor.getUsername()", "name": "Coordinator", "accessStatus":"ALLOWED" } } } */
Update folder node properties to add an editor
{ "permissions": { "isInheritanceEnabled": true, "locallySet": { "authorityId": "editor.getUsername()",
"name": "Coordinator", "accessStatus":"ALLOWED" } } }
*/
String putBody = getAddPermissionsBody(editor.getUsername(), "Editor"); String putBody = getAddPermissionsBody(editor.getUsername(), "Editor");
restClient.authenticateUser(user).withCoreAPI().usingNode(folder).updateNode(putBody); restClient.authenticateUser(user).withCoreAPI().usingNode(folder).updateNode(putBody);
@@ -502,11 +494,7 @@ public class CreateRulesTests extends RulesRestTest
STEP("Create another user as a collaborator for this folder."); STEP("Create another user as a collaborator for this folder.");
UserModel collaborator = dataUser.createRandomTestUser(); UserModel collaborator = dataUser.createRandomTestUser();
/* /* Update folder node properties to add a collaborator { "permissions": { "isInheritanceEnabled": true, "locallySet": { "authorityId": "collaborator.getUsername()", "name": "Coordinator", "accessStatus":"ALLOWED" } } } */
Update folder node properties to add a collaborator
{ "permissions": { "isInheritanceEnabled": true, "locallySet": { "authorityId": "collaborator.getUsername()",
"name": "Coordinator", "accessStatus":"ALLOWED" } } }
*/
String putBody = getAddPermissionsBody(collaborator.getUsername(), "Collaborator"); String putBody = getAddPermissionsBody(collaborator.getUsername(), "Collaborator");
restClient.authenticateUser(user).withCoreAPI().usingNode(folder).updateNode(putBody); restClient.authenticateUser(user).withCoreAPI().usingNode(folder).updateNode(putBody);
@@ -656,8 +644,7 @@ public class CreateRulesTests extends RulesRestTest
public void createRuleWithNotApplicableActionShouldFail() public void createRuleWithNotApplicableActionShouldFail()
{ {
final RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues(); final RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
final RestActionBodyExecTemplateModel invalidAction = final RestActionBodyExecTemplateModel invalidAction = rulesUtils.createCustomActionModel(RulesTestsUtils.DELETE_RENDITION_ACTION, Map.of("dummy-key", "dummy-value"));
rulesUtils.createCustomActionModel(RulesTestsUtils.DELETE_RENDITION_ACTION, Map.of("dummy-key", "dummy-value"));
ruleModel.setActions(List.of(invalidAction)); ruleModel.setActions(List.of(invalidAction));
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel); restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
@@ -673,8 +660,7 @@ public class CreateRulesTests extends RulesRestTest
public void createRuleWithMissingActionParametersShouldFail() public void createRuleWithMissingActionParametersShouldFail()
{ {
final RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues(); final RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
final RestActionBodyExecTemplateModel invalidAction = final RestActionBodyExecTemplateModel invalidAction = rulesUtils.createCustomActionModel(RulesTestsUtils.COPY_ACTION, Collections.emptyMap());
rulesUtils.createCustomActionModel(RulesTestsUtils.COPY_ACTION, Collections.emptyMap());
ruleModel.setActions(List.of(invalidAction)); ruleModel.setActions(List.of(invalidAction));
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet() restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
@@ -761,7 +747,7 @@ public class CreateRulesTests extends RulesRestTest
.createSingleRule(ruleModel); .createSingleRule(ruleModel);
restClient.assertStatusCodeIs(NOT_FOUND); restClient.assertStatusCodeIs(NOT_FOUND);
restClient.assertLastError().containsSummary("The entity with id: non-existent-node was not found"); restClient.assertLastError().containsSummary("Destination folder having Id: non-existent-node no longer exists. Please update your rule definition.");
} }
/** /**
@@ -828,7 +814,6 @@ public class CreateRulesTests extends RulesRestTest
restClient.assertLastError().containsSummary("Node is not a folder " + fileModel.getNodeRef()); restClient.assertLastError().containsSummary("Node is not a folder " + fileModel.getNodeRef());
} }
/** /**
* Check we get error when attempting to create a rule with mail action defined with non-existing mail template. * Check we get error when attempting to create a rule with mail action defined with non-existing mail template.
*/ */
@@ -970,9 +955,7 @@ public class CreateRulesTests extends RulesRestTest
String fakeCategoryId = "bdba5f9f-fake-id22-803b-349bcfd06fd1"; String fakeCategoryId = "bdba5f9f-fake-id22-803b-349bcfd06fd1";
RestCompositeConditionDefinitionModel conditions = rulesUtils.createCompositeCondition(List.of( RestCompositeConditionDefinitionModel conditions = rulesUtils.createCompositeCondition(List.of(
rulesUtils.createCompositeCondition(!INVERTED, List.of( rulesUtils.createCompositeCondition(!INVERTED, List.of(
rulesUtils.createSimpleCondition("category", "equals", fakeCategoryId) rulesUtils.createSimpleCondition("category", "equals", fakeCategoryId)))));
))
));
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues(); RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
ruleModel.setConditions(conditions); ruleModel.setConditions(conditions);
@@ -992,9 +975,7 @@ public class CreateRulesTests extends RulesRestTest
final String comparator = "greaterthan"; final String comparator = "greaterthan";
RestCompositeConditionDefinitionModel conditions = rulesUtils.createCompositeCondition(List.of( RestCompositeConditionDefinitionModel conditions = rulesUtils.createCompositeCondition(List.of(
rulesUtils.createCompositeCondition(!INVERTED, List.of( rulesUtils.createCompositeCondition(!INVERTED, List.of(
rulesUtils.createSimpleCondition("size", comparator, "500") rulesUtils.createSimpleCondition("size", comparator, "500")))));
))
));
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues(); RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
ruleModel.setConditions(conditions); ruleModel.setConditions(conditions);

View File

@@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Remote API * Alfresco Remote API
* %% * %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited * Copyright (C) 2005 - 2025 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
@@ -39,6 +39,9 @@ import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.apache.commons.collections.MapUtils;
import org.apache.logging.log4j.util.Strings;
import org.alfresco.repo.action.executer.CheckOutActionExecuter; import org.alfresco.repo.action.executer.CheckOutActionExecuter;
import org.alfresco.repo.action.executer.CopyActionExecuter; import org.alfresco.repo.action.executer.CopyActionExecuter;
import org.alfresco.repo.action.executer.ImageTransformActionExecuter; import org.alfresco.repo.action.executer.ImageTransformActionExecuter;
@@ -58,8 +61,6 @@ import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.NamespaceService;
import org.apache.commons.collections.MapUtils;
import org.apache.logging.log4j.util.Strings;
/** /**
* This class provides logic for validation of permissions for action parameters which reference node. * This class provides logic for validation of permissions for action parameters which reference node.
@@ -67,15 +68,14 @@ import org.apache.logging.log4j.util.Strings;
public class ActionNodeParameterValidator implements ActionValidator public class ActionNodeParameterValidator implements ActionValidator
{ {
/** /**
* This list holds action parameter names which require only READ permission on a referenced node * This list holds action parameter names which require only READ permission on a referenced node That means, all other parameters that reference nodes will require WRITE permission
* That means, all other parameters that reference nodes will require WRITE permission
*/ */
static final Map<String, List<String>> REQUIRE_READ_PERMISSION_PARAMS = static final Map<String, List<String>> REQUIRE_READ_PERMISSION_PARAMS = Map.of(LinkCategoryActionExecuter.NAME, List.of(LinkCategoryActionExecuter.PARAM_CATEGORY_VALUE));
Map.of(LinkCategoryActionExecuter.NAME, List.of(LinkCategoryActionExecuter.PARAM_CATEGORY_VALUE));
static final String NO_PROPER_PERMISSIONS_FOR_NODE = "No proper permissions for node: "; static final String NO_PROPER_PERMISSIONS_FOR_NODE = "No proper permissions for node: ";
static final String NOT_A_CATEGORY = "Node is not a category "; static final String NOT_A_CATEGORY = "Node is not a category ";
static final String NOT_A_FOLDER = "Node is not a folder "; static final String NOT_A_FOLDER = "Node is not a folder ";
static final String NO_LONGER_EXISTS = "%s having Id: %s no longer exists. Please update your rule definition.";
private final Actions actions; private final Actions actions;
private final NamespaceService namespaceService; private final NamespaceService namespaceService;
@@ -94,7 +94,8 @@ public class ActionNodeParameterValidator implements ActionValidator
/** /**
* Validates action parameters that reference nodes against access permissions for executing user. * Validates action parameters that reference nodes against access permissions for executing user.
* *
* @param action Action to be validated * @param action
* Action to be validated
*/ */
@Override @Override
public void validate(Action action) public void validate(Action action)
@@ -132,7 +133,15 @@ public class ActionNodeParameterValidator implements ActionValidator
.filter(pd -> action.getParams().containsKey(pd.getName())) .filter(pd -> action.getParams().containsKey(pd.getName()))
.forEach(p -> { .forEach(p -> {
final String nodeId = Objects.toString(action.getParams().get(p.getName()), Strings.EMPTY); final String nodeId = Objects.toString(action.getParams().get(p.getName()), Strings.EMPTY);
final NodeRef nodeRef = nodes.validateNode(nodeId); NodeRef nodeRef;
try
{
nodeRef = nodes.validateNode(nodeId);
}
catch (EntityNotFoundException e)
{
throw new EntityNotFoundException(String.format(NO_LONGER_EXISTS, p.getDisplayLabel(), nodeId), e);
}
validatePermission(action.getActionDefinitionId(), p.getName(), nodeRef); validatePermission(action.getActionDefinitionId(), p.getName(), nodeRef);
validateType(action.getActionDefinitionId(), nodeRef); validateType(action.getActionDefinitionId(), nodeRef);
}); });
@@ -163,7 +172,8 @@ public class ActionNodeParameterValidator implements ActionValidator
{ {
throw new InvalidArgumentException(NOT_A_FOLDER + nodeRef.getId()); throw new InvalidArgumentException(NOT_A_FOLDER + nodeRef.getId());
} }
} else if (!nodes.nodeMatches(nodeRef, Set.of(TYPE_CATEGORY), Collections.emptySet())) }
else if (!nodes.nodeMatches(nodeRef, Set.of(TYPE_CATEGORY), Collections.emptySet()))
{ {
throw new InvalidArgumentException(NOT_A_CATEGORY + nodeRef.getId()); throw new InvalidArgumentException(NOT_A_CATEGORY + nodeRef.getId());
} }