[ACS-3006] Revert changes made to implement a validation logic (#1139)

* Revert "ACS-2744 Private action validation logic (#1051)"

This reverts commit 64998b5c53.

* Revert "[ACS-2747] Prevent private action execution from the V1 HTTP API. Added end-to-end test method. (#1108)"

This reverts commit 8edfd4bdce.
This commit is contained in:
Kacper Magdziarz
2022-05-30 13:18:44 +02:00
committed by GitHub
parent e1b6203cdc
commit b7bd6aa215
11 changed files with 17 additions and 534 deletions

View File

@@ -11,7 +11,6 @@ import org.alfresco.rest.model.RestActionDefinitionModelsCollection;
import org.alfresco.rest.model.RestNodeModel; import org.alfresco.rest.model.RestNodeModel;
import org.alfresco.utility.Utility; import org.alfresco.utility.Utility;
import org.alfresco.utility.model.FileModel; import org.alfresco.utility.model.FileModel;
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;
@@ -22,14 +21,10 @@ import org.springframework.http.HttpStatus;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.util.Properties;
public class ActionsTests extends RestTest public class ActionsTests extends RestTest
{ {
private UserModel adminUser; private UserModel adminUser;
private FileModel document; private FileModel document;
private FolderModel folder;
private FileModel randomFile;
private SiteModel publicSite; private SiteModel publicSite;
@BeforeClass(alwaysRun = true) @BeforeClass(alwaysRun = true)
@@ -38,8 +33,6 @@ public class ActionsTests extends RestTest
adminUser = dataUser.getAdminUser(); adminUser = dataUser.getAdminUser();
publicSite = dataSite.createPublicRandomSite(); publicSite = dataSite.createPublicRandomSite();
document = dataContent.usingSite(publicSite).usingUser(adminUser).createContent(CMISUtil.DocumentType.TEXT_PLAIN); document = dataContent.usingSite(publicSite).usingUser(adminUser).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
folder = dataContent.usingUser(adminUser).createFolder();
randomFile = dataContent.usingUser(adminUser).usingResource(folder).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
} }
@TestRail(section = { TestGroup.REST_API,TestGroup.ACTIONS }, executionType = ExecutionType.SANITY, @TestRail(section = { TestGroup.REST_API,TestGroup.ACTIONS }, executionType = ExecutionType.SANITY,
@@ -113,22 +106,6 @@ public class ActionsTests extends RestTest
}); });
} }
@TestRail(section = { TestGroup.REST_API,TestGroup.ACTIONS }, executionType = ExecutionType.SANITY,
description = "Test for private action execution from POST api/-default-/public/alfresco/versions/1/action-executions, should not be possible to execute private action using V1 REST API")
@Test(groups = { TestGroup.REST_API, TestGroup.ACTIONS, TestGroup.SANITY})
public void executePrivateActionV1RESTAPI() throws Exception
{
// 'count-children' action is expected to be private (not exposed) by default
String actionDefinitionId = "count-children";
JSONObject response = restClient.authenticateUser(adminUser)
.withCoreAPI()
.usingActions()
.executeAction(actionDefinitionId, folder);
restClient.assertStatusCodeIs(HttpStatus.FORBIDDEN);
restClient.assertLastError().containsSummary("Action '" + actionDefinitionId + "' is not exposed within 'http-v1' execution source.");
}
@TestRail (section = { TestGroup.REST_API, TestGroup.ACTIONS }, executionType = ExecutionType.SANITY, @TestRail (section = { TestGroup.REST_API, TestGroup.ACTIONS }, executionType = ExecutionType.SANITY,
description = "Sanity test for POST /action-executions") description = "Sanity test for POST /action-executions")
@Test (groups = { TestGroup.REST_API, TestGroup.ACTIONS, TestGroup.SANITY }) @Test (groups = { TestGroup.REST_API, TestGroup.ACTIONS, TestGroup.SANITY })
@@ -164,7 +141,7 @@ public class ActionsTests extends RestTest
withCoreAPI(). withCoreAPI().
usingActions(). usingActions().
getActionDefinitionById("add-features"); getActionDefinitionById("add-features");
restClient.assertStatusCodeIs(HttpStatus.OK); restClient.assertStatusCodeIs(HttpStatus.OK);
assertFalse(restActionDefinition.getId().isEmpty()); assertFalse(restActionDefinition.getId().isEmpty());
restActionDefinition.getId().equals("add-features"); restActionDefinition.getId().equals("add-features");

View File

@@ -26,14 +26,11 @@
package org.alfresco.rest.api.impl; package org.alfresco.rest.api.impl;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.action.ActionExecutionContext;
import org.alfresco.repo.action.RuntimeActionService;
import org.alfresco.rest.api.Actions; import org.alfresco.rest.api.Actions;
import org.alfresco.rest.api.model.Action; import org.alfresco.rest.api.model.Action;
import org.alfresco.rest.api.model.ActionDefinition; import org.alfresco.rest.api.model.ActionDefinition;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Parameters; import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.rest.framework.resource.parameters.SortColumn; import org.alfresco.rest.framework.resource.parameters.SortColumn;
@@ -75,9 +72,6 @@ public class ActionsImpl implements Actions
private NamespaceService namespaceService; private NamespaceService namespaceService;
private NodeService nodeService; private NodeService nodeService;
private NamespacePrefixResolver prefixResolver; private NamespacePrefixResolver prefixResolver;
private RuntimeActionService runtimeActionService;
private final String HTTP_V1_EXECUTION_SOURCE = "http-v1";
public void setActionService(ActionService actionService) public void setActionService(ActionService actionService)
{ {
@@ -104,11 +98,6 @@ public class ActionsImpl implements Actions
this.prefixResolver = prefixResolver; this.prefixResolver = prefixResolver;
} }
public void setRuntimeActionService(RuntimeActionService runtimeActionService)
{
this.runtimeActionService = runtimeActionService;
}
@Override @Override
public ActionDefinition getActionDefinitionById(String actionDefinitionId) public ActionDefinition getActionDefinitionById(String actionDefinitionId)
{ {
@@ -274,16 +263,6 @@ public class ActionsImpl implements Actions
throw new EntityNotFoundException(action.getActionDefinitionId()); throw new EntityNotFoundException(action.getActionDefinitionId());
} }
final ActionExecutionContext actionExecutionContext = ActionExecutionContext
.builder(actionDef.getName())
.withExecutionSource(HTTP_V1_EXECUTION_SOURCE)
.build();
if (!runtimeActionService.isExposed(actionExecutionContext))
{
throw new PermissionDeniedException("Action '" + actionDef.getName() + "' is not exposed within '" + HTTP_V1_EXECUTION_SOURCE + "' execution source.");
}
// targetId is optional, however, currently targetId must be a valid node ID. // targetId is optional, however, currently targetId must be a valid node ID.
NodeRef actionedUponNodeRef = null; NodeRef actionedUponNodeRef = null;
if (action.getTargetId() != null && !action.getTargetId().isEmpty()) if (action.getTargetId() != null && !action.getTargetId().isEmpty())

View File

@@ -566,7 +566,6 @@
<property name="namespaceService" ref="NamespaceService"/> <property name="namespaceService" ref="NamespaceService"/>
<property name="nodeService" ref="NodeService"/> <property name="nodeService" ref="NodeService"/>
<property name="prefixResolver" ref="namespaceService"/> <property name="prefixResolver" ref="namespaceService"/>
<property name="runtimeActionService" ref="actionService"/>
</bean> </bean>
<bean id="Actions" class="org.springframework.aop.framework.ProxyFactoryBean"> <bean id="Actions" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="org.alfresco.rest.api.Actions"/> <property name="proxyInterfaces" value="org.alfresco.rest.api.Actions"/>

View File

@@ -1,93 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.action;
import java.util.Objects;
/**
* Instances of this class are responsible for holding an action id with additional data used to identify the action's
* execution context like:
* <ul>
* <li>REST API</li>
* <li>rules execution</li>
* <li>...</li>
* </ul>
*/
public class ActionExecutionContext
{
private final String actionId;
private final String executionSource;
private ActionExecutionContext(String actionId, String executionSource)
{
this.actionId = actionId;
this.executionSource = executionSource;
}
String getActionId()
{
return actionId;
}
String getExecutionSource()
{
return executionSource;
}
boolean isExecutionSourceKnown()
{
return Objects.nonNull(executionSource);
}
public static Builder builder(final String actionId)
{
Objects.requireNonNull(actionId);
return new Builder(actionId);
}
public static class Builder
{
private final String actionId;
private String executionSource;
private Builder(String actionId)
{
this.actionId = actionId;
}
public ActionExecutionContext build()
{
return new ActionExecutionContext(actionId, executionSource);
}
public Builder withExecutionSource(final String executionSource)
{
Objects.requireNonNull(executionSource);
this.executionSource = executionSource;
return this;
}
}
}

View File

@@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited * Copyright (C) 2005 - 2020 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
@@ -33,14 +33,7 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Properties;
import java.util.Set; import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.evaluator.ActionConditionEvaluator; import org.alfresco.repo.action.evaluator.ActionConditionEvaluator;
@@ -127,8 +120,6 @@ public class ActionServiceImpl implements ActionService, RuntimeActionService, A
private ActionTrackingService actionTrackingService; private ActionTrackingService actionTrackingService;
private PolicyComponent policyComponent; private PolicyComponent policyComponent;
private ActionServiceMonitor monitor; private ActionServiceMonitor monitor;
private Properties configProperties;
private ActionExecutionValidator actionExecutionValidator;
/** /**
* The asynchronous action execution queues map of name, queue * The asynchronous action execution queues map of name, queue
@@ -245,17 +236,7 @@ public class ActionServiceImpl implements ActionService, RuntimeActionService, A
{ {
this.asynchronousActionExecutionQueues = asynchronousActionExecutionQueues; this.asynchronousActionExecutionQueues = asynchronousActionExecutionQueues;
} }
public void setConfigurationProperties(Properties properties)
{
this.configProperties = properties;
}
protected Properties getConfigurationProperties()
{
return configProperties;
}
/** /**
* This method registers an {@link AsynchronousActionExecutionQueue} with the {@link ActionService}. * This method registers an {@link AsynchronousActionExecutionQueue} with the {@link ActionService}.
* @param key String * @param key String
@@ -275,11 +256,6 @@ public class ActionServiceImpl implements ActionService, RuntimeActionService, A
ActionModel.TYPE_ACTION_PARAMETER, new JavaBehaviour(this, "getCopyCallback")); ActionModel.TYPE_ACTION_PARAMETER, new JavaBehaviour(this, "getCopyCallback"));
this.policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onCopyComplete"), this.policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onCopyComplete"),
ActionModel.TYPE_ACTION_PARAMETER, new JavaBehaviour(this, "onCopyComplete")); ActionModel.TYPE_ACTION_PARAMETER, new JavaBehaviour(this, "onCopyComplete"));
if (configProperties == null)
{
configProperties = applicationContext.getBean("global-properties", Properties.class);
}
actionExecutionValidator = new ActionExecutionValidator(configProperties::getProperty, actionDefinitions::containsKey);
} }
/** /**
@@ -1894,58 +1870,5 @@ public class ActionServiceImpl implements ActionService, RuntimeActionService, A
LoggingAwareExecuter executer = (LoggingAwareExecuter) this.applicationContext.getBean(action.getActionDefinitionName()); LoggingAwareExecuter executer = (LoggingAwareExecuter) this.applicationContext.getBean(action.getActionDefinitionName());
return executer.onLogException(logger,t, message); return executer.onLogException(logger,t, message);
} }
@Override
public boolean isExposed(ActionExecutionContext actionExecutionContext)
{
return actionExecutionValidator.isExposed(actionExecutionContext);
}
static class ActionExecutionValidator
{
private final Function<String, String> config;
private final Predicate<String> isPublic;
ActionExecutionValidator(Function<String, String> config, Predicate<String> isPublic)
{
this.config = Objects.requireNonNull(config);
this.isPublic = Objects.requireNonNull(isPublic);
}
boolean isExposed(ActionExecutionContext actionExecutionContext)
{
Objects.requireNonNull(actionExecutionContext);
return isExposedInConfig(actionExecutionContext).orElseGet(() -> isPublic(actionExecutionContext));
}
private Optional<Boolean> isExposedInConfig(ActionExecutionContext actionExecutionContext)
{
return getConfigKeys(actionExecutionContext).
map(config).
filter(Objects::nonNull).
map(Boolean::parseBoolean).
findFirst();
}
private Boolean isPublic(ActionExecutionContext actionExecutionContext)
{
return isPublic.test(actionExecutionContext.getActionId());
}
private static Stream<String> getConfigKeys(ActionExecutionContext actionExecutionContext)
{
if (actionExecutionContext.isExecutionSourceKnown())
{
return Stream.of(
getConfigKey(actionExecutionContext.getExecutionSource(), actionExecutionContext.getActionId()),
getConfigKey(actionExecutionContext.getActionId()));
}
return Stream.of(getConfigKey(actionExecutionContext.getActionId()));
}
static String getConfigKey(String... parts)
{
return Stream.of(parts).collect(Collectors.joining(".", "org.alfresco.repo.action.", ".exposed"));
}
}
} }

View File

@@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited * Copyright (C) 2005 - 2016 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
@@ -125,14 +125,4 @@ public interface RuntimeActionService
* @return true if it was handled, false for default handling * @return true if it was handled, false for default handling
*/ */
public boolean onLogException(Action action, Log logger, Throwable t, String message); public boolean onLogException(Action action, Log logger, Throwable t, String message);
/**
* Allows you to check if an action can be executed/used in a given execution context
* @param actionExecutionContext describes action and its execution context
* @return true if action can be executed, false otherwise
*/
default boolean isExposed(ActionExecutionContext actionExecutionContext)
{
return true;
}
} }

View File

@@ -75,9 +75,6 @@
<property name="monitor"> <property name="monitor">
<ref bean="actionServiceMonitor"/> <ref bean="actionServiceMonitor"/>
</property> </property>
<property name="configurationProperties">
<ref bean="global-properties"/>
</property>
</bean> </bean>
<bean id="defaultAsynchronousActionExecutionQueue" class="org.alfresco.repo.action.AsynchronousActionExecutionQueueImpl" init-method="init"> <bean id="defaultAsynchronousActionExecutionQueue" class="org.alfresco.repo.action.AsynchronousActionExecutionQueueImpl" init-method="init">

View File

@@ -176,7 +176,6 @@ import org.junit.runners.Suite;
org.alfresco.repo.action.CompositeActionImplTest.class, org.alfresco.repo.action.CompositeActionImplTest.class,
org.alfresco.repo.action.CompositeActionConditionImplTest.class, org.alfresco.repo.action.CompositeActionConditionImplTest.class,
org.alfresco.repo.action.executer.TransformActionExecuterTest.class, org.alfresco.repo.action.executer.TransformActionExecuterTest.class,
org.alfresco.repo.action.PrivateActionValidationTest.class,
org.alfresco.repo.audit.AuditableAnnotationTest.class, org.alfresco.repo.audit.AuditableAnnotationTest.class,
org.alfresco.repo.audit.PropertyAuditFilterTest.class, org.alfresco.repo.audit.PropertyAuditFilterTest.class,
org.alfresco.repo.audit.access.NodeChangeTest.class, org.alfresco.repo.audit.access.NodeChangeTest.class,

View File

@@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited * Copyright (C) 2005 - 2016 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
@@ -25,27 +25,28 @@
*/ */
package org.alfresco.repo.action; package org.alfresco.repo.action;
import static org.alfresco.repo.action.ActionExecutionContext.builder;
import java.io.Serializable; import java.io.Serializable;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.evaluator.ComparePropertyValueEvaluator; import org.alfresco.repo.action.evaluator.ComparePropertyValueEvaluator;
import org.alfresco.repo.action.evaluator.InCategoryEvaluator; import org.alfresco.repo.action.evaluator.InCategoryEvaluator;
import org.alfresco.repo.action.evaluator.NoConditionEvaluator; import org.alfresco.repo.action.evaluator.NoConditionEvaluator;
import org.alfresco.repo.action.evaluator.compare.ComparePropertyValueOperation; import org.alfresco.repo.action.evaluator.compare.ComparePropertyValueOperation;
import org.alfresco.repo.action.executer.ActionExecuter;
import org.alfresco.repo.action.executer.ActionExecuterAbstractBase; import org.alfresco.repo.action.executer.ActionExecuterAbstractBase;
import org.alfresco.repo.action.executer.AddFeaturesActionExecuter; import org.alfresco.repo.action.executer.AddFeaturesActionExecuter;
import org.alfresco.repo.action.executer.CheckInActionExecuter; import org.alfresco.repo.action.executer.CheckInActionExecuter;
import org.alfresco.repo.action.executer.CheckOutActionExecuter; import org.alfresco.repo.action.executer.CheckOutActionExecuter;
import org.alfresco.repo.action.executer.CompositeActionExecuter; import org.alfresco.repo.action.executer.CompositeActionExecuter;
import org.alfresco.repo.action.executer.MoveActionExecuter; import org.alfresco.repo.action.executer.MoveActionExecuter;
import org.alfresco.repo.action.executer.ScriptActionExecuter;
import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper;
@@ -64,14 +65,19 @@ import org.alfresco.service.cmr.action.CompositeActionCondition;
import org.alfresco.service.cmr.action.ParameterDefinition; import org.alfresco.service.cmr.action.ParameterDefinition;
import org.alfresco.service.cmr.coci.CheckOutCheckInService; import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.repository.ContentData; import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService; import org.alfresco.service.transaction.TransactionService;
import org.alfresco.test_category.BaseSpringTestsCategory; import org.alfresco.test_category.BaseSpringTestsCategory;
import org.alfresco.util.ApplicationContextHelper;
import org.alfresco.util.BaseAlfrescoSpringTest; import org.alfresco.util.BaseAlfrescoSpringTest;
import org.alfresco.util.GUID; import org.alfresco.util.GUID;
import org.alfresco.util.PropertyMap;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.experimental.categories.Category; import org.junit.experimental.categories.Category;
@@ -97,18 +103,13 @@ public class ActionServiceImplTest extends BaseAlfrescoSpringTest
private NodeRef nodeRef; private NodeRef nodeRef;
private NodeRef folder; private NodeRef folder;
private RetryingTransactionHelper transactionHelper; private RetryingTransactionHelper transactionHelper;
private Properties globalConfig;
private RuntimeActionService runtimeActionService;
@Before @Before
public void before() throws Exception public void before() throws Exception
{ {
super.before(); super.before();
this.transactionHelper = applicationContext.getBean("retryingTransactionHelper", RetryingTransactionHelper.class); this.transactionHelper = (RetryingTransactionHelper)this.applicationContext.getBean("retryingTransactionHelper");
this.globalConfig = applicationContext.getBean("global-properties", Properties.class);
this.runtimeActionService = this.applicationContext.getBean("actionService", RuntimeActionService.class);
// Create the node used for tests // Create the node used for tests
this.nodeRef = this.nodeService.createNode( this.nodeRef = this.nodeService.createNode(
@@ -1294,89 +1295,6 @@ public class ActionServiceImplTest extends BaseAlfrescoSpringTest
assertEquals(123455, action.getExecutionEndDate().getTime()); assertEquals(123455, action.getExecutionEndDate().getTime());
assertEquals(null, action.getExecutionFailureMessage()); assertEquals(null, action.getExecutionFailureMessage());
} }
@Test
public void testActionExposureBasedOnConfiguration()
{
globalConfig.remove("org.alfresco.repo.action.public-test-action.exposed");
globalConfig.remove("org.alfresco.repo.action.source.public-test-action.exposed");
globalConfig.remove("org.alfresco.repo.action.unknown.public-test-action.exposed");
assertTrue(runtimeActionService.isExposed(builder("public-test-action").build()));
assertTrue(runtimeActionService.isExposed(builder("public-test-action").withExecutionSource("source").build()));
assertTrue(runtimeActionService.isExposed(builder("public-test-action").withExecutionSource("unknown").build()));
globalConfig.setProperty("org.alfresco.repo.action.public-test-action.exposed", "true");
globalConfig.remove("org.alfresco.repo.action.source.public-test-action.exposed");
globalConfig.remove("org.alfresco.repo.action.unknown.public-test-action.exposed");
assertTrue(runtimeActionService.isExposed(builder("public-test-action").build()));
assertTrue(runtimeActionService.isExposed(builder("public-test-action").withExecutionSource("source").build()));
assertTrue(runtimeActionService.isExposed(builder("public-test-action").withExecutionSource("unknown").build()));
globalConfig.setProperty("org.alfresco.repo.action.public-test-action.exposed", "false");
globalConfig.remove("org.alfresco.repo.action.source.public-test-action.exposed");
globalConfig.remove("org.alfresco.repo.action.unknown.public-test-action.exposed");
assertFalse(runtimeActionService.isExposed(builder("public-test-action").build()));
assertFalse(runtimeActionService.isExposed(builder("public-test-action").withExecutionSource("source").build()));
assertFalse(runtimeActionService.isExposed(builder("public-test-action").withExecutionSource("unknown").build()));
globalConfig.remove("org.alfresco.repo.action.public-test-action.exposed");
globalConfig.setProperty("org.alfresco.repo.action.source.public-test-action.exposed", "true");
globalConfig.remove("org.alfresco.repo.action.unknown.public-test-action.exposed");
assertTrue(runtimeActionService.isExposed(builder("public-test-action").build()));
assertTrue(runtimeActionService.isExposed(builder("public-test-action").withExecutionSource("source").build()));
assertTrue(runtimeActionService.isExposed(builder("public-test-action").withExecutionSource("unknown").build()));
globalConfig.remove("org.alfresco.repo.action.public-test-action.exposed");
globalConfig.setProperty("org.alfresco.repo.action.source.public-test-action.exposed", "false");
globalConfig.remove("org.alfresco.repo.action.unknown.public-test-action.exposed");
assertTrue(runtimeActionService.isExposed(builder("public-test-action").build()));
assertFalse(runtimeActionService.isExposed(builder("public-test-action").withExecutionSource("source").build()));
assertTrue(runtimeActionService.isExposed(builder("public-test-action").withExecutionSource("unknown").build()));
globalConfig.remove("org.alfresco.repo.action.private-test-action.exposed");
globalConfig.remove("org.alfresco.repo.action.source.private-test-action.exposed");
globalConfig.remove("org.alfresco.repo.action.unknown.private-test-action.exposed");
assertFalse(runtimeActionService.isExposed(builder("private-test-action").build()));
assertFalse(runtimeActionService.isExposed(builder("private-test-action").withExecutionSource("source").build()));
assertFalse(runtimeActionService.isExposed(builder("private-test-action").withExecutionSource("unknown").build()));
globalConfig.setProperty("org.alfresco.repo.action.private-test-action.exposed", "true");
globalConfig.remove("org.alfresco.repo.action.source.private-test-action.exposed");
globalConfig.remove("org.alfresco.repo.action.unknown.private-test-action.exposed");
assertTrue(runtimeActionService.isExposed(builder("private-test-action").build()));
assertTrue(runtimeActionService.isExposed(builder("private-test-action").withExecutionSource("source").build()));
assertTrue(runtimeActionService.isExposed(builder("private-test-action").withExecutionSource("unknown").build()));
globalConfig.setProperty("org.alfresco.repo.action.private-test-action.exposed", "false");
globalConfig.remove("org.alfresco.repo.action.source.private-test-action.exposed");
globalConfig.remove("org.alfresco.repo.action.unknown.private-test-action.exposed");
assertFalse(runtimeActionService.isExposed(builder("private-test-action").build()));
assertFalse(runtimeActionService.isExposed(builder("private-test-action").withExecutionSource("source").build()));
assertFalse(runtimeActionService.isExposed(builder("private-test-action").withExecutionSource("unknown").build()));
globalConfig.remove("org.alfresco.repo.action.private-test-action.exposed");
globalConfig.setProperty("org.alfresco.repo.action.source.private-test-action.exposed", "true");
globalConfig.remove("org.alfresco.repo.action.unknown.private-test-action.exposed");
assertFalse(runtimeActionService.isExposed(builder("private-test-action").build()));
assertTrue(runtimeActionService.isExposed(builder("private-test-action").withExecutionSource("source").build()));
assertFalse(runtimeActionService.isExposed(builder("private-test-action").withExecutionSource("unknown").build()));
globalConfig.remove("org.alfresco.repo.action.private-test-action.exposed");
globalConfig.setProperty("org.alfresco.repo.action.source.private-test-action.exposed", "false");
globalConfig.remove("org.alfresco.repo.action.unknown.private-test-action.exposed");
assertFalse(runtimeActionService.isExposed(builder("private-test-action").build()));
assertFalse(runtimeActionService.isExposed(builder("private-test-action").withExecutionSource("source").build()));
assertFalse(runtimeActionService.isExposed(builder("private-test-action").withExecutionSource("unknown").build()));
}
@Test
public void testIfGlobalConfigurationIsUsedEvenIfNotInjectedBySpring()
{
TestExtendedActionServiceImpl extended = applicationContext.getBean("extendedActionServiceWithoutConfigurationProperty", TestExtendedActionServiceImpl.class);
assertNotNull(extended.getConfigurationProperties());
assertSame(globalConfig, extended.getConfigurationProperties());
}
/** /**
* This method returns an {@link Action} which will fail when executed. * This method returns an {@link Action} which will fail when executed.
@@ -1591,26 +1509,8 @@ public class ActionServiceImplTest extends BaseAlfrescoSpringTest
throw new ActionServiceTransientException("action failed intentionally in " + TransientFailActionExecuter.class.getSimpleName()); throw new ActionServiceTransientException("action failed intentionally in " + TransientFailActionExecuter.class.getSimpleName());
} }
} }
public static class NoOpActionExecuter extends ActionExecuterAbstractBase
{
@Override
protected void addParameterDefinitions(List<ParameterDefinition> paramList)
{
//do nothing
}
@Override
protected void executeImpl(Action action, NodeRef actionedUponNodeRef)
{
//do nothing
}
}
public static class TestExtendedActionServiceImpl extends ActionServiceImpl
{
}
protected static class CancellableSleepAction extends ActionImpl implements CancellableAction protected static class CancellableSleepAction extends ActionImpl implements CancellableAction
{ {

View File

@@ -1,152 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* 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.repo.action;
import static org.alfresco.repo.action.ActionExecutionContext.builder;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import java.util.Map;
import java.util.Set;
import org.alfresco.repo.action.ActionServiceImpl.ActionExecutionValidator;
import org.junit.Assert;
import org.junit.Test;
public class PrivateActionValidationTest
{
@Test
public void shouldFailOnNullContext()
{
final ActionExecutionValidator validator = givenActionExecutionValidator(Map.of(), Set.of());
try
{
validator.isExposed(null);
}
catch (NullPointerException e)
{
assertNotNull(e);
return;
}
fail("Expected NPE.");
}
@Test
public void privateActionShouldNotBeExposedByDefault()
{
final ActionExecutionValidator validator = givenActionExecutionValidator(Map.of(), Set.of());
Assert.assertFalse(validator.isExposed(builder("privateA").build()));
Assert.assertFalse(validator.isExposed(builder("privateA").withExecutionSource("test").build()));
}
@Test
public void publicActionShouldBeExposedByDefault()
{
final ActionExecutionValidator validator = givenActionExecutionValidator(Map.of(), Set.of("publicA"));
Assert.assertTrue(validator.isExposed(builder("publicA").build()));
Assert.assertTrue(validator.isExposed(builder("publicA").withExecutionSource("test").build()));
}
@Test
public void privateActionShouldBeExposedByConfigurationBasedOnActionId()
{
final ActionExecutionValidator validator = givenActionExecutionValidator(Map.of(
"org.alfresco.repo.action.privateA.exposed", "true"), Set.of());
Assert.assertTrue(validator.isExposed(builder("privateA").build()));
Assert.assertTrue(validator.isExposed(builder("privateA").withExecutionSource("test").build()));
Assert.assertTrue(validator.isExposed(builder("privateA").withExecutionSource("test2").build()));
Assert.assertFalse(validator.isExposed(builder("privateB").build()));
Assert.assertFalse(validator.isExposed(builder("privateB").withExecutionSource("test").build()));
Assert.assertFalse(validator.isExposed(builder("privateB").withExecutionSource("test2").build()));
}
@Test
public void privateActionShouldBeExposedByConfigurationBasedOnActionIdAndExecutionSource()
{
final ActionExecutionValidator validator = givenActionExecutionValidator(Map.of(
"org.alfresco.repo.action.test.privateA.exposed", "true"), Set.of());
Assert.assertFalse(validator.isExposed(builder("privateA").build()));
Assert.assertTrue(validator.isExposed(builder("privateA").withExecutionSource("test").build()));
Assert.assertFalse(validator.isExposed(builder("privateA").withExecutionSource("test2").build()));
Assert.assertFalse(validator.isExposed(builder("privateB").build()));
Assert.assertFalse(validator.isExposed(builder("privateB").withExecutionSource("test").build()));
Assert.assertFalse(validator.isExposed(builder("privateB").withExecutionSource("test2").build()));
}
@Test
public void executionSourceConfigurationShouldTakePrecedenceOverGeneralConfigurationForPrivateAction()
{
final ActionExecutionValidator validator = givenActionExecutionValidator(Map.of(
"org.alfresco.repo.action.test.privateA.exposed", "true",
"org.alfresco.repo.action.privateA.exposed", "false"), Set.of());
Assert.assertFalse(validator.isExposed(builder("privateA").build()));
Assert.assertTrue(validator.isExposed(builder("privateA").withExecutionSource("test").build()));
}
@Test
public void publicActionShouldNotBeExposedByConfigurationBasedOnActionId()
{
final ActionExecutionValidator validator = givenActionExecutionValidator(Map.of(
"org.alfresco.repo.action.publicA.exposed", "false"), Set.of("publicA"));
Assert.assertFalse(validator.isExposed(builder("publicA").build()));
Assert.assertFalse(validator.isExposed(builder("publicA").withExecutionSource("test").build()));
}
@Test
public void publicActionShouldNotBeExposedByConfigurationBasedOnActionIdAndExecutionSource()
{
final ActionExecutionValidator validator = givenActionExecutionValidator(Map.of(
"org.alfresco.repo.action.test.publicA.exposed", "false"), Set.of("publicA"));
Assert.assertTrue(validator.isExposed(builder("publicA").build()));
Assert.assertFalse(validator.isExposed(builder("publicA").withExecutionSource("test").build()));
}
@Test
public void executionSourceConfigurationShouldTakePrecedenceOverGeneralConfigurationForPublicAction()
{
final ActionExecutionValidator validator = givenActionExecutionValidator(Map.of(
"org.alfresco.repo.action.test.publicA.exposed", "false",
"org.alfresco.repo.action.publicA.exposed", "true"), Set.of("publicA"));
Assert.assertTrue(validator.isExposed(builder("publicA").build()));
Assert.assertFalse(validator.isExposed(builder("publicA").withExecutionSource("test").build()));
}
private ActionExecutionValidator givenActionExecutionValidator(Map<String, String> configuration, Set<String> publicActions)
{
return new ActionExecutionValidator(configuration::get, publicActions::contains);
}
}

View File

@@ -11,18 +11,6 @@
<value>1000</value> <value>1000</value>
</property> </property>
</bean> </bean>
<bean id="public-test-action" class="org.alfresco.repo.action.ActionServiceImplTest$NoOpActionExecuter" parent="action-executer">
<property name="publicAction">
<value>true</value>
</property>
</bean>
<bean id="private-test-action" class="org.alfresco.repo.action.ActionServiceImplTest$NoOpActionExecuter" parent="action-executer">
<property name="publicAction">
<value>false</value>
</property>
</bean>
<bean id="sleepActionFilter" class="org.alfresco.repo.action.ActionServiceImplTest$SleepActionFilter" parent="baseActionFilter"> <bean id="sleepActionFilter" class="org.alfresco.repo.action.ActionServiceImplTest$SleepActionFilter" parent="baseActionFilter">
<property name="name"> <property name="name">
@@ -43,28 +31,4 @@
<bean id="transient-fail-action" <bean id="transient-fail-action"
class="org.alfresco.repo.action.ActionServiceImplTest$TransientFailActionExecuter" class="org.alfresco.repo.action.ActionServiceImplTest$TransientFailActionExecuter"
parent="action-executer" /> parent="action-executer" />
<bean id="extendedActionServiceWithoutConfigurationProperty" class="org.alfresco.repo.action.ActionServiceImplTest$TestExtendedActionServiceImpl" init-method="init">
<property name="policyComponent">
<ref bean="policyComponent" />
</property>
<property name="nodeService">
<ref bean="NodeService" />
</property>
<property name="searchService">
<ref bean="ADMSearchService" />
</property>
<property name="authenticationContext">
<ref bean="authenticationContext" />
</property>
<property name="actionTrackingService">
<ref bean="actionTrackingService" />
</property>
<property name="dictionaryService">
<ref bean="DictionaryService" />
</property>
<property name="monitor">
<ref bean="actionServiceMonitor"/>
</property>
</bean>
</beans> </beans>