mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
[ACS-2747] Prevent private action execution from the V1 HTTP API. Added end-to-end test method. (#1108)
This commit is contained in:
@@ -11,6 +11,7 @@ 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;
|
||||||
@@ -21,10 +22,14 @@ 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)
|
||||||
@@ -33,6 +38,8 @@ 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,
|
||||||
@@ -106,6 +113,22 @@ 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 })
|
||||||
|
@@ -26,11 +26,14 @@
|
|||||||
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;
|
||||||
@@ -72,6 +75,9 @@ 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)
|
||||||
{
|
{
|
||||||
@@ -98,6 +104,11 @@ 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)
|
||||||
{
|
{
|
||||||
@@ -263,6 +274,16 @@ 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())
|
||||||
|
@@ -566,6 +566,7 @@
|
|||||||
<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"/>
|
||||||
|
Reference in New Issue
Block a user