ACS-3353: POST support for "other fields" (#1287)

This commit is contained in:
krdabrowski
2022-08-18 15:19:39 +02:00
committed by GitHub
parent 2ab89f0d79
commit 12bc363bcd
7 changed files with 235 additions and 43 deletions

View File

@@ -27,9 +27,16 @@ package org.alfresco.rest.rules;
import static java.util.stream.Collectors.toList;
import static org.alfresco.rest.rules.RulesTestsUtils.createActionModel;
import static org.alfresco.rest.rules.RulesTestsUtils.RULE_NAME_DEFAULT;
import static org.alfresco.rest.rules.RulesTestsUtils.createDefaultActionModel;
import static org.alfresco.rest.rules.RulesTestsUtils.createEmptyConditionModel;
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModel;
import static org.alfresco.utility.constants.UserRole.*;
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModelWithDefaultName;
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModelWithDefaultValues;
import static org.alfresco.utility.constants.UserRole.SiteCollaborator;
import static org.alfresco.utility.constants.UserRole.SiteConsumer;
import static org.alfresco.utility.constants.UserRole.SiteContributor;
import static org.alfresco.utility.constants.UserRole.SiteManager;
import static org.alfresco.utility.model.FileModel.getRandomFileModel;
import static org.alfresco.utility.model.FileType.TEXT_PLAIN;
import static org.alfresco.utility.report.log.Step.STEP;
@@ -60,6 +67,8 @@ import org.testng.annotations.Test;
@Test(groups = {TestGroup.RULES})
public class CreateRulesTests extends RestTest
{
private static final String IGNORE_ID = "id";
private static final String IGNORE_IS_SHARED = "isShared";
private UserModel user;
private SiteModel site;
private FolderModel ruleFolder;
@@ -80,14 +89,19 @@ public class CreateRulesTests extends RestTest
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void createRule()
{
RestRuleModel ruleModel = createRuleModel("ruleName");
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
RestRuleModel expectedRuleModel = createRuleModelWithDefaultValues();
expectedRuleModel.setConditions(createEmptyConditionModel());
restClient.assertStatusCodeIs(CREATED);
rule.assertThat().field("id").isNotNull()
.assertThat().field("name").is("ruleName")
// TODO fix actions mapping and remove it from ignored fields, actual issue - difference:
// actual: actions=[RestActionBodyExecTemplateModel{actionDefinitionId='add-features', params={actionContext=rule, aspect-name={http://www.alfresco.org/model/audio/1.0}audio}}]
// expected: actions=[RestActionBodyExecTemplateModel{actionDefinitionId='set-property-value', params={aspect-name={http://www.alfresco.org/model/audio/1.0}audio, actionContext=rule}}]
rule.assertThat().isEqualTo(expectedRuleModel, IGNORE_ID, IGNORE_IS_SHARED, "actions")
.assertThat().field("id").isNotNull()
.assertThat().field("isShared").isNull();
}
@@ -257,6 +271,71 @@ public class CreateRulesTests extends RestTest
restClient.assertLastError().containsSummary("Rule name is a mandatory parameter");
}
/** Check we can create a rule without description. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void createRuleWithoutDescription()
{
RestRuleModel ruleModel = createRuleModelWithDefaultName();
UserModel admin = dataUser.getAdminUser();
RestRuleModel rule = restClient.authenticateUser(admin).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(CREATED);
rule.assertThat().field("id").isNotNull()
.assertThat().field("name").is(RULE_NAME_DEFAULT)
.assertThat().field("description").isNull();
}
/** Check we can create a rule without specifying triggers but with the default "inbound" value. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void createRuleWithoutTriggers()
{
RestRuleModel ruleModel = createRuleModelWithDefaultName();
UserModel admin = dataUser.getAdminUser();
RestRuleModel rule = restClient.authenticateUser(admin).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(CREATED);
rule.assertThat().field("id").isNotNull()
.assertThat().field("name").is(RULE_NAME_DEFAULT)
.assertThat().field("triggers").is(List.of("inbound"));
}
/** Check we can create a rule without error script. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void createRuleWithoutErrorScript()
{
RestRuleModel ruleModel = createRuleModelWithDefaultName();
UserModel admin = dataUser.getAdminUser();
RestRuleModel rule = restClient.authenticateUser(admin).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(CREATED);
rule.assertThat().field("id").isNotNull()
.assertThat().field("name").is(RULE_NAME_DEFAULT)
.assertThat().field("errorScript").isNull();
}
/** Check we can create a rule with irrelevant isShared flag, and it doesn't have impact to the process. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void createRuleWithSharedFlag()
{
RestRuleModel ruleModel = createRuleModelWithDefaultName();
ruleModel.setIsShared(true);
UserModel admin = dataUser.getAdminUser();
RestRuleModel rule = restClient.authenticateUser(admin).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(CREATED);
rule.assertThat().field("id").isNotNull()
.assertThat().field("name").is(RULE_NAME_DEFAULT)
.assertThat().field("isShared").isNull();
}
/** Check we can create a rule. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void createRuleAndIncludeFieldsInResponse()
@@ -280,7 +359,7 @@ public class CreateRulesTests extends RestTest
STEP(String.format("Add a user with '%s' role in the private site's folder", userRole.toString()));
UserModel userWithRole = dataUser.createRandomTestUser();
dataUser.addUserToSite(userWithRole, privateSite, userRole);
RestRuleModel ruleModel = createRuleModel("testRule", List.of(createActionModel()));
RestRuleModel ruleModel = createRuleModel("testRule", List.of(createDefaultActionModel()));
return restClient.authenticateUser(userWithRole).withCoreAPI().usingNode(privateFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
}

View File

@@ -29,13 +29,47 @@ import java.util.List;
import java.util.Map;
import org.alfresco.rest.model.RestActionBodyExecTemplateModel;
import org.alfresco.rest.model.RestCompositeConditionDefinitionModel;
import org.alfresco.rest.model.RestRuleModel;
public class RulesTestsUtils
{
static final String RULE_NAME_DEFAULT = "ruleName";
static final String RULE_DESCRIPTION_DEFAULT = "rule description";
static final boolean RULE_ENABLED_DEFAULT = true;
static final boolean RULE_CASCADE_DEFAULT = true;
static final boolean RULE_ASYNC_DEFAULT = true;
static final boolean RULE_SHARED_DEFAULT = false;
static final String RULE_ERROR_SCRIPT_DEFAULT = "error-script";
static final List<String> ruleTriggersDefault = List.of("inbound", "update", "outbound");
public static RestRuleModel createRuleModel(String name) {
return createRuleModel(name, List.of(createActionModel()));
/**
* Create a rule model filled with default values.
*
* @return The created rule model.
*/
public static RestRuleModel createRuleModelWithDefaultValues()
{
RestRuleModel ruleModel = createRuleModelWithDefaultName();
ruleModel.setDescription(RULE_DESCRIPTION_DEFAULT);
ruleModel.setEnabled(RULE_ENABLED_DEFAULT);
ruleModel.setCascade(RULE_CASCADE_DEFAULT);
ruleModel.setAsynchronous(RULE_ASYNC_DEFAULT);
ruleModel.setIsShared(RULE_SHARED_DEFAULT);
ruleModel.setTriggers(ruleTriggersDefault);
ruleModel.setErrorScript(RULE_ERROR_SCRIPT_DEFAULT);
return ruleModel;
}
public static RestRuleModel createRuleModelWithDefaultName()
{
return createRuleModel(RULE_NAME_DEFAULT, List.of(createDefaultActionModel()));
}
public static RestRuleModel createRuleModel(String name)
{
return createRuleModel(name, List.of(createDefaultActionModel()));
}
/**
@@ -58,11 +92,19 @@ public class RulesTestsUtils
*
* @return The created action model.
*/
public static RestActionBodyExecTemplateModel createActionModel()
public static RestActionBodyExecTemplateModel createDefaultActionModel()
{
RestActionBodyExecTemplateModel restActionModel = new RestActionBodyExecTemplateModel();
restActionModel.setActionDefinitionId("add-features");
restActionModel.setParams(Map.of("aspect-name", "{http://www.alfresco.org/model/audio/1.0}audio", "actionContext", "rule"));
return restActionModel;
}
public static RestCompositeConditionDefinitionModel createEmptyConditionModel()
{
RestCompositeConditionDefinitionModel conditions = new RestCompositeConditionDefinitionModel();
conditions.setInverted(false);
conditions.setBooleanMode("and");
return conditions;
}
}

View File

@@ -25,7 +25,7 @@
*/
package org.alfresco.rest.rules;
import static org.alfresco.rest.rules.RulesTestsUtils.createActionModel;
import static org.alfresco.rest.rules.RulesTestsUtils.createDefaultActionModel;
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModel;
import static org.alfresco.utility.constants.UserRole.SiteCollaborator;
import static org.alfresco.utility.report.log.Step.STEP;
@@ -201,7 +201,7 @@ public class UpdateRulesTests extends RestTest
private RestRuleModel createAndSaveRule(String name)
{
return createAndSaveRule(name, List.of(createActionModel()));
return createAndSaveRule(name, List.of(createDefaultActionModel()));
}
/**

View File

@@ -30,12 +30,14 @@ import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.alfresco.repo.action.ActionImpl;
import org.alfresco.repo.action.executer.ScriptActionExecuter;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.framework.resource.UniqueId;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.action.CompositeAction;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.util.GUID;
@Experimental
public class Rule
@@ -48,7 +50,7 @@ public class Rule
private boolean asynchronous;
private Boolean isShared;
private String errorScript;
private List<RuleTrigger> triggers;
private List<RuleTrigger> triggers = List.of(RuleTrigger.INBOUND);
private CompositeCondition conditions;
private List<Action> actions;
@@ -107,8 +109,21 @@ public class Rule
final NodeRef nodeRef = (id != null) ? nodes.validateOrLookupNode(id, null) : null;
ruleModel.setNodeRef(nodeRef);
ruleModel.setTitle(name);
ruleModel.setDescription(description);
ruleModel.setRuleDisabled(!enabled);
ruleModel.applyToChildren(cascade);
ruleModel.setExecuteAsynchronously(asynchronous);
if (triggers != null)
{
ruleModel.setRuleTypes(triggers.stream().map(RuleTrigger::getValue).collect(Collectors.toList()));
}
ruleModel.setAction(Action.toCompositeAction(actions));
if (errorScript != null)
{
final org.alfresco.service.cmr.action.Action compensatingAction = new ActionImpl(null, GUID.generate(), ScriptActionExecuter.NAME);
compensatingAction.setParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF, errorScript);
ruleModel.getAction().setCompensatingAction(compensatingAction);
}
return ruleModel;
}
@@ -203,7 +218,15 @@ public class Rule
return triggers.stream().map(RuleTrigger::getValue).collect(Collectors.toList());
}
public void setTriggers(List<RuleTrigger> triggers)
public void setTriggers(List<String> triggers)
{
if (triggers != null)
{
this.triggers = triggers.stream().map(RuleTrigger::of).collect(Collectors.toList());
}
}
public void setRuleTriggers(List<RuleTrigger> triggers)
{
this.triggers = triggers;
}
@@ -279,7 +302,7 @@ public class Rule
private boolean asynchronous;
private Boolean isShared;
private String errorScript;
private List<RuleTrigger> triggers;
private List<RuleTrigger> triggers = List.of(RuleTrigger.INBOUND);
private CompositeCondition conditions;
private List<Action> actions;
@@ -360,7 +383,7 @@ public class Rule
rule.setAsynchronous(asynchronous);
rule.setIsShared(isShared);
rule.setErrorScript(errorScript);
rule.setTriggers(triggers);
rule.setRuleTriggers(triggers);
rule.setConditions(conditions);
rule.setActions(actions);
return rule;

View File

@@ -31,31 +31,15 @@ import org.alfresco.service.Experimental;
@Experimental
public enum RuleTrigger
{
INBOUND("inbound"),
UPDATE("update"),
OUTBOUND("outbound");
RuleTrigger(String value)
{
this.value = value;
}
private final String value;
INBOUND, UPDATE, OUTBOUND;
public String getValue()
{
return value;
return this.name().toLowerCase();
}
public static RuleTrigger of(final String value)
{
for (RuleTrigger ruleTrigger : values())
{
if (ruleTrigger.value.equals(value)) {
return ruleTrigger;
}
}
return null;
return RuleTrigger.valueOf(value.toUpperCase());
}
}

View File

@@ -27,6 +27,7 @@
package org.alfresco.rest.api;
import org.alfresco.rest.api.impl.rules.NodeValidatorTest;
import org.alfresco.rest.api.impl.rules.RuleSetsImplTest;
import org.alfresco.rest.api.model.rules.ActionTest;
import org.alfresco.rest.api.model.rules.CompositeConditionTest;
import org.alfresco.rest.api.impl.rules.RulesImplTest;
@@ -42,6 +43,7 @@ import org.junit.runners.Suite;
@Suite.SuiteClasses({
NodeRulesRelationTest.class,
RulesImplTest.class,
RuleSetsImplTest.class,
NodeValidatorTest.class,
RuleTest.class,
ActionTest.class,

View File

@@ -27,6 +27,8 @@
package org.alfresco.rest.api.model.rules;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.mock;
import java.util.Collections;
import java.util.List;
@@ -34,15 +36,18 @@ import java.util.List;
import org.alfresco.repo.action.ActionConditionImpl;
import org.alfresco.repo.action.ActionImpl;
import org.alfresco.repo.action.executer.ScriptActionExecuter;
import org.alfresco.rest.api.Nodes;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ActionCondition;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.rule.RuleType;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
@Experimental
@RunWith(MockitoJUnitRunner.class)
public class RuleTest
{
private static final String RULE_ID = "fake-rule-id";
@@ -51,6 +56,8 @@ public class RuleTest
private static final boolean RULE_ENABLED = true;
private static final boolean RULE_CASCADE = true;
private static final boolean RULE_ASYNC = true;
private static final boolean RULE_SHARED = true;
private static final String ACTION_DEFINITION_NAME = "action-def-name";
private static final String ERROR_SCRIPT = "error-script-ref";
@Test
@@ -79,6 +86,51 @@ public class RuleTest
}
@Test
public void testToServiceModel()
{
final Nodes nodesMock = mock(Nodes.class);
final Rule rule = createRuleWithDefaultValues();
rule.setActions(List.of(Action.builder().actionDefinitionId(ACTION_DEFINITION_NAME).create()));
final org.alfresco.service.cmr.rule.Rule expectedRuleModel = createRuleModel();
final org.alfresco.service.cmr.action.Action expectedCompensatingActionModel = createCompensatingActionModel();
// when
final org.alfresco.service.cmr.rule.Rule actualRuleModel = rule.toServiceModel(nodesMock);
then(nodesMock).should().validateOrLookupNode(RULE_ID, null);
then(nodesMock).shouldHaveNoMoreInteractions();
assertThat(actualRuleModel)
.isNotNull()
.usingRecursiveComparison().ignoringFields("nodeRef", "action")
.isEqualTo(expectedRuleModel);
assertThat(actualRuleModel.getAction())
.isNotNull();
assertThat(actualRuleModel.getAction().getCompensatingAction())
.isNotNull()
.usingRecursiveComparison().ignoringFields("id")
.isEqualTo(expectedCompensatingActionModel);
}
@Test
public void testToServiceModel_withNullValues()
{
final Nodes nodesMock = mock(Nodes.class);
final Rule rule = new Rule();
final org.alfresco.service.cmr.rule.Rule expectedRuleModel = new org.alfresco.service.cmr.rule.Rule();
expectedRuleModel.setRuleDisabled(true);
// when
final org.alfresco.service.cmr.rule.Rule actualRuleModel = rule.toServiceModel(nodesMock);
then(nodesMock).shouldHaveNoInteractions();
assertThat(actualRuleModel)
.isNotNull()
.usingRecursiveComparison()
.ignoringFields("ruleTypes")
.isEqualTo(expectedRuleModel);
}
private static org.alfresco.service.cmr.rule.Rule createRuleModel() {
final NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, RULE_ID);
final org.alfresco.service.cmr.rule.Rule ruleModel = new org.alfresco.service.cmr.rule.Rule(nodeRef);
@@ -88,17 +140,27 @@ public class RuleTest
ruleModel.applyToChildren(RULE_CASCADE);
ruleModel.setExecuteAsynchronously(RULE_ASYNC);
ruleModel.setRuleTypes(List.of(RuleType.INBOUND, RuleType.UPDATE));
final Action compensatingAction = new ActionImpl(nodeRef, "compensatingActionId", "compensatingActionDefName");
compensatingAction.setParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF, ERROR_SCRIPT);
final ActionCondition actionCondition = new ActionConditionImpl("actionConditionId", "actionConditionDefName");
final Action action = new ActionImpl(nodeRef, "actionId", "actionDefName");
action.setCompensatingAction(compensatingAction);
action.addActionCondition(actionCondition);
ruleModel.setAction(action);
ruleModel.setAction(createActionModel());
return ruleModel;
}
private static org.alfresco.service.cmr.action.Action createActionModel() {
final ActionCondition actionCondition = new ActionConditionImpl("action-condition-id", "action-condition-def-name");
final org.alfresco.service.cmr.action.Action actionModel = new ActionImpl(null, "action-id", ACTION_DEFINITION_NAME);
actionModel.setCompensatingAction(createCompensatingActionModel());
actionModel.addActionCondition(actionCondition);
return actionModel;
}
private static org.alfresco.service.cmr.action.Action createCompensatingActionModel() {
final org.alfresco.service.cmr.action.Action compensatingActionModel = new ActionImpl(null, "compensating-action-id", ScriptActionExecuter.NAME);
compensatingActionModel.setParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF, ERROR_SCRIPT);
return compensatingActionModel;
}
private static Rule createRuleWithDefaultValues() {
return Rule.builder()
.id(RULE_ID)