mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
ACS-3651 Validate node pameters.
This commit is contained in:
@@ -522,6 +522,49 @@ public class CreateRulesTests extends RestTest
|
|||||||
restClient.assertLastError().containsSummary("Missing action's mandatory parameter: destination-folder");
|
restClient.assertLastError().containsSummary("Missing action's mandatory parameter: destination-folder");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check we get error when attempting to create a rule that copies files to a non-existent folder.
|
||||||
|
*/
|
||||||
|
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||||
|
public void createRuleThatUsesNonExistentNode()
|
||||||
|
{
|
||||||
|
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||||
|
RestActionBodyExecTemplateModel invalidAction = new RestActionBodyExecTemplateModel();
|
||||||
|
String actionDefinitionId = "copy";
|
||||||
|
invalidAction.setActionDefinitionId(actionDefinitionId);
|
||||||
|
invalidAction.setParams(Map.of("destination-folder", "non-existent-node"));
|
||||||
|
ruleModel.setActions(List.of(invalidAction));
|
||||||
|
|
||||||
|
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||||
|
.createSingleRule(ruleModel);
|
||||||
|
|
||||||
|
restClient.assertStatusCodeIs(NOT_FOUND);
|
||||||
|
restClient.assertLastError().containsSummary("The entity with id: non-existent-node was not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check we get error when attempting to create a rule that references a folder that the user does not have read permission for.
|
||||||
|
*/
|
||||||
|
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||||
|
public void createRuleThatUsesNodeWithoutReadPermission()
|
||||||
|
{
|
||||||
|
SiteModel privateSite = dataSite.usingAdmin().createPrivateRandomSite();
|
||||||
|
FolderModel privateFolder = dataContent.usingAdmin().usingSite(privateSite).createFolder();
|
||||||
|
|
||||||
|
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||||
|
RestActionBodyExecTemplateModel invalidAction = new RestActionBodyExecTemplateModel();
|
||||||
|
String actionDefinitionId = "copy";
|
||||||
|
invalidAction.setActionDefinitionId(actionDefinitionId);
|
||||||
|
invalidAction.setParams(Map.of("destination-folder", privateFolder.getNodeRef()));
|
||||||
|
ruleModel.setActions(List.of(invalidAction));
|
||||||
|
|
||||||
|
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||||
|
.createSingleRule(ruleModel);
|
||||||
|
|
||||||
|
restClient.assertStatusCodeIs(NOT_FOUND);
|
||||||
|
restClient.assertLastError().containsSummary("The entity with id: " + privateFolder.getNodeRef() + " was not found");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check we can create a rule with multiple conditions
|
* Check we can create a rule with multiple conditions
|
||||||
*/
|
*/
|
||||||
|
@@ -93,6 +93,7 @@ public class RulesTestsUtils implements InitializingBean
|
|||||||
private FolderModel copyDestinationFolder;
|
private FolderModel copyDestinationFolder;
|
||||||
|
|
||||||
private FolderModel checkOutDestinationFolder;
|
private FolderModel checkOutDestinationFolder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialise the util class.
|
* Initialise the util class.
|
||||||
*/
|
*/
|
||||||
|
@@ -26,12 +26,17 @@
|
|||||||
|
|
||||||
package org.alfresco.rest.api.impl.rules;
|
package org.alfresco.rest.api.impl.rules;
|
||||||
|
|
||||||
|
import static org.alfresco.rest.framework.core.exceptions.NotFoundException.DEFAULT_MESSAGE_ID;
|
||||||
|
import static org.alfresco.service.cmr.security.AccessStatus.ALLOWED;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
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 org.alfresco.rest.api.Nodes;
|
||||||
|
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.NotFoundException;
|
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
|
||||||
import org.alfresco.service.Experimental;
|
import org.alfresco.service.Experimental;
|
||||||
@@ -42,8 +47,9 @@ import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
|||||||
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
||||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.cmr.repository.StoreRef;
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||||
|
import org.alfresco.service.cmr.security.PermissionService;
|
||||||
import org.alfresco.service.namespace.NamespaceService;
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
@@ -56,13 +62,19 @@ public class ActionParameterConverter
|
|||||||
private final DictionaryService dictionaryService;
|
private final DictionaryService dictionaryService;
|
||||||
private final ActionService actionService;
|
private final ActionService actionService;
|
||||||
private final NamespaceService namespaceService;
|
private final NamespaceService namespaceService;
|
||||||
|
private final NodeService nodeService;
|
||||||
|
private final PermissionService permissionService;
|
||||||
|
private final Nodes nodes;
|
||||||
|
|
||||||
public ActionParameterConverter(DictionaryService dictionaryService, ActionService actionService,
|
public ActionParameterConverter(DictionaryService dictionaryService, ActionService actionService, NamespaceService namespaceService,
|
||||||
NamespaceService namespaceService)
|
NodeService nodeService, PermissionService permissionService, Nodes nodes)
|
||||||
{
|
{
|
||||||
this.dictionaryService = dictionaryService;
|
this.dictionaryService = dictionaryService;
|
||||||
this.actionService = actionService;
|
this.actionService = actionService;
|
||||||
this.namespaceService = namespaceService;
|
this.namespaceService = namespaceService;
|
||||||
|
this.nodeService = nodeService;
|
||||||
|
this.permissionService = permissionService;
|
||||||
|
this.nodes = nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Serializable> getConvertedParams(Map<String, Serializable> params, String name)
|
public Map<String, Serializable> getConvertedParams(Map<String, Serializable> params, String name)
|
||||||
@@ -74,10 +86,12 @@ public class ActionParameterConverter
|
|||||||
definition = actionService.getActionDefinition(name);
|
definition = actionService.getActionDefinition(name);
|
||||||
if (definition == null)
|
if (definition == null)
|
||||||
{
|
{
|
||||||
throw new NotFoundException(NotFoundException.DEFAULT_MESSAGE_ID, new String[]{name});
|
throw new NotFoundException(DEFAULT_MESSAGE_ID, new String[]{name});
|
||||||
}
|
}
|
||||||
} catch (NoSuchBeanDefinitionException e) {
|
}
|
||||||
throw new NotFoundException(NotFoundException.DEFAULT_MESSAGE_ID, new String[]{name});
|
catch (NoSuchBeanDefinitionException e)
|
||||||
|
{
|
||||||
|
throw new NotFoundException(DEFAULT_MESSAGE_ID, new String[]{name});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Map.Entry<String, Serializable> param : params.entrySet())
|
for (Map.Entry<String, Serializable> param : params.entrySet())
|
||||||
@@ -91,7 +105,8 @@ public class ActionParameterConverter
|
|||||||
{
|
{
|
||||||
final QName typeQName = paramDef.getType();
|
final QName typeQName = paramDef.getType();
|
||||||
parameters.put(param.getKey(), convertValue(typeQName, param.getValue()));
|
parameters.put(param.getKey(), convertValue(typeQName, param.getValue()));
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
parameters.put(param.getKey(), param.getValue().toString());
|
parameters.put(param.getKey(), param.getValue().toString());
|
||||||
}
|
}
|
||||||
@@ -105,7 +120,8 @@ public class ActionParameterConverter
|
|||||||
{
|
{
|
||||||
return ((QName) param).toPrefixString(namespaceService);
|
return ((QName) param).toPrefixString(namespaceService);
|
||||||
}
|
}
|
||||||
else if (param instanceof NodeRef) {
|
else if (param instanceof NodeRef)
|
||||||
|
{
|
||||||
return ((NodeRef) param).getId();
|
return ((NodeRef) param).getId();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -121,7 +137,7 @@ public class ActionParameterConverter
|
|||||||
final DataTypeDefinition typeDef = dictionaryService.getDataType(typeQName);
|
final DataTypeDefinition typeDef = dictionaryService.getDataType(typeQName);
|
||||||
if (typeDef == null)
|
if (typeDef == null)
|
||||||
{
|
{
|
||||||
throw new NotFoundException(NotFoundException.DEFAULT_MESSAGE_ID, new String[]{typeQName.toPrefixString()});
|
throw new NotFoundException(DEFAULT_MESSAGE_ID, new String[]{typeQName.toPrefixString()});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (propertyValue instanceof JSONArray)
|
if (propertyValue instanceof JSONArray)
|
||||||
@@ -130,7 +146,8 @@ public class ActionParameterConverter
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Class.forName(javaClassName);
|
Class.forName(javaClassName);
|
||||||
} catch (ClassNotFoundException e)
|
}
|
||||||
|
catch (ClassNotFoundException e)
|
||||||
{
|
{
|
||||||
throw new DictionaryException("Java class " + javaClassName + " of property type " + typeDef.getName() + " is invalid", e);
|
throw new DictionaryException("Java class " + javaClassName + " of property type " + typeDef.getName() + " is invalid", e);
|
||||||
}
|
}
|
||||||
@@ -151,7 +168,12 @@ public class ActionParameterConverter
|
|||||||
}
|
}
|
||||||
else if (typeQName.isMatch(DataTypeDefinition.NODE_REF))
|
else if (typeQName.isMatch(DataTypeDefinition.NODE_REF))
|
||||||
{
|
{
|
||||||
value = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, propertyValue.toString());
|
NodeRef nodeRef = nodes.validateOrLookupNode(propertyValue.toString(), null);
|
||||||
|
if (permissionService.hasReadPermission(nodeRef) != ALLOWED)
|
||||||
|
{
|
||||||
|
throw new EntityNotFoundException(propertyValue.toString());
|
||||||
|
}
|
||||||
|
value = nodeRef;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@@ -44,6 +44,17 @@ public class EntityNotFoundException extends NotFoundException
|
|||||||
super(DEFAULT_MESSAGE_ID, new String[] {entityId});
|
super(DEFAULT_MESSAGE_ID, new String[] {entityId});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The entity id param will be shown in the default error message.
|
||||||
|
*
|
||||||
|
* @param msgId The message template.
|
||||||
|
* @param parameters The message template parameters.
|
||||||
|
*/
|
||||||
|
public EntityNotFoundException(String msgId, String[] parameters)
|
||||||
|
{
|
||||||
|
super(msgId, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
public EntityNotFoundException(String msgId, Throwable cause)
|
public EntityNotFoundException(String msgId, Throwable cause)
|
||||||
{
|
{
|
||||||
super(msgId, cause);
|
super(msgId, cause);
|
||||||
|
@@ -910,6 +910,9 @@
|
|||||||
<constructor-arg name="actionService" ref="ActionService"/>
|
<constructor-arg name="actionService" ref="ActionService"/>
|
||||||
<constructor-arg name="dictionaryService" ref="DictionaryService"/>
|
<constructor-arg name="dictionaryService" ref="DictionaryService"/>
|
||||||
<constructor-arg name="namespaceService" ref="NamespaceService"/>
|
<constructor-arg name="namespaceService" ref="NamespaceService"/>
|
||||||
|
<constructor-arg name="nodeService" ref="NodeService"/>
|
||||||
|
<constructor-arg name="permissionService" ref="PermissionService" />
|
||||||
|
<constructor-arg name="nodes" ref="Nodes"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="actionPermissionValidator" class="org.alfresco.rest.api.impl.rules.ActionPermissionValidator">
|
<bean id="actionPermissionValidator" class="org.alfresco.rest.api.impl.rules.ActionPermissionValidator">
|
||||||
|
Reference in New Issue
Block a user