Compare commits

..

34 Commits

Author SHA1 Message Date
Travis CI User
de14eb97cb [maven-release-plugin][skip ci] prepare release 17.162 2022-10-11 15:56:11 +00:00
krdabrowski
8ff074dfea ACS-3620: E2Es - API for manual triggering rules on a folder (#1482)
- adding "alwaysRun = true" to @BeforeMethod due to failing acs-packaging "REST API TAS tests with AIMS"
2022-10-11 17:14:43 +02:00
Travis CI User
a27a5571bc [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-11 14:31:41 +00:00
Travis CI User
3f9b18d110 [maven-release-plugin][skip ci] prepare release 17.161 2022-10-11 14:31:38 +00:00
Tom Page
623d166a76 Merge pull request #1487 from Alfresco/feature/ACS-3595_ActionParamMap
ACS-3651 Use Serializable for values in action parameters.
2022-10-11 14:53:02 +01:00
Travis CI User
6502924f8e [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-11 13:42:04 +00:00
Travis CI User
918e1cf183 [maven-release-plugin][skip ci] prepare release 17.160 2022-10-11 13:42:01 +00:00
Aleksandra Onych
59ab7e9458 ACS-3635 Alfresco WebDAV CSRF - allowInsecurePOSTMethod flag (#1488) 2022-10-11 15:05:48 +02:00
Tom Page
ccd421871c ACS-3651 Use Serializable for values in action parameters. 2022-10-11 12:00:17 +01:00
Travis CI User
fa1e616c72 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-11 10:40:52 +00:00
Travis CI User
5a34a2b01a [maven-release-plugin][skip ci] prepare release 17.159 2022-10-11 10:40:49 +00:00
Piotr Żurek
aae87ebffd PRODSEC-6550 Fix CSRF in the WebScript console Refresh Scripts form (#1483) 2022-10-11 12:05:35 +02:00
Travis CI User
44947e3d06 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-11 06:22:01 +00:00
Travis CI User
a94e660047 [maven-release-plugin][skip ci] prepare release 17.158 2022-10-11 06:21:59 +00:00
Marcin Strankowski
561d7d2f5a Update transform-core to 3.0.0-A4, transform-service to 2.0.0-A4, remove different version for jackson-databind. Update jackson version to 2.14.0-rc1 (#1484) 2022-10-11 08:44:52 +03:00
Travis CI User
78e69353d4 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-10 19:29:30 +00:00
Travis CI User
71a88870bd [maven-release-plugin][skip ci] prepare release 17.157 2022-10-10 19:29:27 +00:00
George Evangelopoulos
6bcf33d672 ACS-3616: fix exception type for missing node id (#1457)
* ACS-3616: fix exception type for missing node id

* ACS-3616: fix exception handling for missing node id

* ACS-3616: update javadoc, add a constructor for the exception
2022-10-10 21:52:19 +03:00
Travis CI User
81f2bd7018 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-10 16:08:17 +00:00
Travis CI User
b3968bcd9e [maven-release-plugin][skip ci] prepare release 17.156 2022-10-10 16:08:14 +00:00
Maciej Pichura
307eaff896 ACS-3649, ACS-3650 Action validation mechanism + validations against Action Definitions (#1481)
* ACS-3572: Action constraints endpoint + logic + unit tests.

* ACS-3572: Action constraints endpoint + logic + unit tests.

* ACS-3572: Action constraints endpoint fixes.

* ACS-3572: Cleanup after removal of GET all Action constraints.

* ACS-3572: Fixing formatting in tests.

* ACS-3572: Loosening V1 constraints restrictions for aspects, types and properties.

* ACS-3649: Action validators - constraints.

* ACS-3649: Action validators - constraints.

* ACS-3649: Action validators - constraints.

* ACS-3572: Adding validation for extra paramater.

* ACS-3649: Small refactors and fixes.

* ACS-3649: Validations against action definition.

* ACS-3649: Adding @Experimental annotation.

* ACS-3649: Fixes/refactoring after code review.

* ACS-3649: Removing ignored test
2022-10-10 17:13:51 +02:00
Travis CI User
0cfedbc979 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-10 09:13:35 +00:00
Travis CI User
89522ba09d [maven-release-plugin][skip ci] prepare release 17.155 2022-10-10 09:13:32 +00:00
Tom Page
86761bd408 Merge pull request #1478 from Alfresco/feature/ACS-3615_AllowNullParams
ACS-3615 Allow actions in rules without any params.
2022-10-10 09:29:29 +01:00
Maciej Pichura
4d6b4c2ecf ACS-3572 V1 API for action constraints (#1469)
* ACS-3572: Action constraints endpoint + logic + unit tests.

* ACS-3572: Action constraints endpoint + logic + unit tests.

* ACS-3572: Action constraints endpoint fixes.

* ACS-3572: Cleanup after removal of GET all Action constraints.

* ACS-3572: Fixing formatting in tests.

* ACS-3572: Loosening V1 constraints restrictions for aspects, types and properties.

* ACS-3572: Removing unnecessary code.

* ACS-3572: Removing unnecessary field.

* ACS-3572: Removing unnecessary field - fixing the tests.

* ACS-3572: Renaming the endpoint and fixing license headers.

* ACS-3572: Fixing license headers.

* ACS-3572: Fixing tas-restapi dependency version.

* ACS-3649: Bumping tes-restapi version.

* ACS-3649: Bumping tes-restapi version.
2022-10-10 10:14:47 +02:00
Travis CI User
98cb7762c4 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-09 09:44:47 +00:00
Travis CI User
ee01595f31 [maven-release-plugin][skip ci] prepare release 17.154 2022-10-09 09:44:44 +00:00
Elia Porciani
75acf5110e Fix/acs 2699 mandatory modifier (#1472)
[ACS-2699] managed + and - modifiers in fts query parser
2022-10-09 10:47:18 +02:00
Travis CI User
3a5971e267 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-09 00:11:41 +00:00
Travis CI User
99ef570054 [maven-release-plugin][skip ci] prepare release 17.153 2022-10-09 00:11:39 +00:00
Alfresco CI User
9649324d33 [force] Force release for 2022-10-09. 2022-10-09 00:04:36 +00:00
Tom Page
ad96f85251 ACS-3615 Allow actions in rules without any params. 2022-10-07 16:37:08 +01:00
krdabrowski
7ac48f8a99 ACS-3687: Execute rules API: Remove field "isEachInheritedRuleExecuted" (#1476)
* ACS-3620: E2Es - API for manual triggering rules on a folder
2022-10-07 17:01:08 +02:00
Travis CI User
aa38bcf9df [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-07 14:27:33 +00:00
72 changed files with 1767 additions and 328 deletions

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-amps</artifactId>
<version>17.152</version>
<version>17.162</version>
</parent>
<modules>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-parent</artifactId>
<version>17.152</version>
<version>17.162</version>
</parent>
<modules>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-automation-community-repo</artifactId>
<version>17.152</version>
<version>17.162</version>
</parent>
<build>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-parent</artifactId>
<version>17.152</version>
<version>17.162</version>
</parent>
<modules>

View File

@@ -8,7 +8,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
<version>17.152</version>
<version>17.162</version>
</parent>
<properties>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
<version>17.152</version>
<version>17.162</version>
</parent>
<build>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>17.152</version>
<version>17.162</version>
</parent>
<modules>

View File

@@ -8,7 +8,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-amps</artifactId>
<version>17.152</version>
<version>17.162</version>
</parent>
<properties>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>17.152</version>
<version>17.162</version>
</parent>
<dependencies>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>17.152</version>
<version>17.162</version>
</parent>
<properties>

View File

@@ -346,7 +346,7 @@ public class FTSQueryParser
}
constraints.add(constraint);
}
if (constraints.size() == 1 && Occur.EXCLUDE != constraints.get(0).getOccur())
if (constraints.size() == 1)
{
return constraints.get(0);
}

View File

@@ -69,21 +69,20 @@ public class LuceneDisjunction<Q, S, E extends Throwable> extends BaseDisjunctio
@SuppressWarnings("unchecked")
LuceneQueryBuilderComponent<Q, S, E> luceneQueryBuilderComponent = (LuceneQueryBuilderComponent<Q, S, E>) constraint;
Q constraintQuery = luceneQueryBuilderComponent.addComponent(selectors, functionArgs, luceneContext, functionContext);
queriestoDisjoin.add(new Pair<Constraint, Q>(constraint, constraintQuery));
queriestoDisjoin.add(new Pair<>(constraint, constraintQuery));
if (constraintQuery != null)
{
switch (constraint.getOccur())
{
case DEFAULT:
case MANDATORY:
case OPTIONAL:
expressionBuilder.addOptional(constraintQuery, constraint.getBoost());
break;
case MANDATORY:
expressionBuilder.addRequired(constraintQuery, constraint.getBoost());
break;
case EXCLUDE:
QueryParserExpressionAdaptor<Q, E> subExpressionBuilder = luceneContext.getLuceneQueryParserAdaptor().getExpressionAdaptor();
subExpressionBuilder.addRequired(luceneContext.getLuceneQueryParserAdaptor().getMatchAllNodesQuery());
subExpressionBuilder.addExcluded(constraintQuery);
expressionBuilder.addOptional(subExpressionBuilder.getQuery(), constraint.getBoost());
expressionBuilder.addExcluded(constraintQuery, constraint.getBoost());
break;
}
}

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>17.152</version>
<version>17.162</version>
</parent>
<dependencies>

View File

@@ -9,6 +9,6 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId>
<version>17.152</version>
<version>17.162</version>
</parent>
</project>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId>
<version>17.152</version>
<version>17.162</version>
</parent>
<properties>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>17.152</version>
<version>17.162</version>
</parent>
<modules>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId>
<version>17.152</version>
<version>17.162</version>
</parent>
<modules>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>17.152</version>
<version>17.162</version>
</parent>
<organization>

View File

@@ -9,7 +9,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>17.152</version>
<version>17.162</version>
</parent>
<developers>

View File

@@ -9,7 +9,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>17.152</version>
<version>17.162</version>
</parent>
<developers>

View File

@@ -9,7 +9,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>17.152</version>
<version>17.162</version>
</parent>
<developers>

View File

@@ -2,10 +2,13 @@ package org.alfresco.rest.actions;
import static org.testng.Assert.assertFalse;
import com.google.common.collect.ImmutableMap;
import java.util.List;
import com.google.common.collect.ImmutableMap;
import org.alfresco.dataprep.CMISUtil;
import org.alfresco.rest.RestTest;
import org.alfresco.rest.model.RestActionConstraintDataModel;
import org.alfresco.rest.model.RestActionConstraintModel;
import org.alfresco.rest.model.RestActionDefinitionModel;
import org.alfresco.rest.model.RestActionDefinitionModelsCollection;
import org.alfresco.rest.model.RestNodeModel;
@@ -148,4 +151,66 @@ public class ActionsTests extends RestTest
restActionDefinition.getDescription().equals("This will add an aspect to the matched item.");
restActionDefinition.getTitle().equals("Add aspect");
}
@TestRail(section = {TestGroup.REST_API, TestGroup.ACTIONS}, executionType = ExecutionType.SANITY,
description = "Sanity test for ACTIONS endpoint GET action-conditions/{actionConstraintName}")
@Test(groups = {TestGroup.REST_API, TestGroup.ACTIONS, TestGroup.SANITY})
public void testGetSingleActionConstraint()
{
final UserModel testUser = dataUser.createRandomTestUser();
restClient.authenticateUser(testUser);
final String compareOperationsName = "ac-compare-operations";
final RestActionConstraintModel actionConstraintCompareOperations =
restClient.withCoreAPI().usingActions().getActionConstraintByName(compareOperationsName);
restClient.assertStatusCodeIs(HttpStatus.OK);
final RestActionConstraintModel expectedComparatorConstraints = new RestActionConstraintModel();
expectedComparatorConstraints.setConstraintName(compareOperationsName);
expectedComparatorConstraints.setConstraintValues(getComparatorConstraints());
actionConstraintCompareOperations.assertThat().isEqualTo(expectedComparatorConstraints);
}
@TestRail(section = {TestGroup.REST_API, TestGroup.ACTIONS}, executionType = ExecutionType.SANITY,
description = "Sanity test for ACTIONS endpoint GET action-conditions/{actionConstraintName} - non existing constraint name")
@Test(groups = {TestGroup.REST_API, TestGroup.ACTIONS, TestGroup.SANITY})
public void testGetSingleNonExistingActionConstraint()
{
final UserModel testUser = dataUser.createRandomTestUser();
restClient.authenticateUser(testUser);
restClient.withCoreAPI().usingActions().getActionConstraintByName("dummy-name");
restClient.assertStatusCodeIs(HttpStatus.NOT_FOUND);
}
private List<RestActionConstraintDataModel> getComparatorConstraints()
{
final RestActionConstraintDataModel equalsConstraint = new RestActionConstraintDataModel();
equalsConstraint.setValue("EQUALS");
equalsConstraint.setLabel("Equals");
final RestActionConstraintDataModel containsConstraint = new RestActionConstraintDataModel();
containsConstraint.setValue("CONTAINS");
containsConstraint.setLabel("Contains");
final RestActionConstraintDataModel beginsConstraint = new RestActionConstraintDataModel();
beginsConstraint.setValue("BEGINS");
beginsConstraint.setLabel("Begins With");
final RestActionConstraintDataModel endsConstraint = new RestActionConstraintDataModel();
endsConstraint.setValue("ENDS");
endsConstraint.setLabel("Ends With");
final RestActionConstraintDataModel greaterThanConstraint = new RestActionConstraintDataModel();
greaterThanConstraint.setValue("GREATER_THAN");
greaterThanConstraint.setLabel("Greater Than");
final RestActionConstraintDataModel greaterThanEqualConstraint = new RestActionConstraintDataModel();
greaterThanEqualConstraint.setValue("GREATER_THAN_EQUAL");
greaterThanEqualConstraint.setLabel("Greater Than Or Equal To");
final RestActionConstraintDataModel lessThanConstraint = new RestActionConstraintDataModel();
lessThanConstraint.setValue("LESS_THAN");
lessThanConstraint.setLabel("Less Than");
final RestActionConstraintDataModel lessThanEqualConstraint = new RestActionConstraintDataModel();
lessThanEqualConstraint.setValue("LESS_THAN_EQUAL");
lessThanEqualConstraint.setLabel("Less Than Or Equal To");
return List.of(equalsConstraint, containsConstraint, beginsConstraint, endsConstraint, greaterThanConstraint,
greaterThanEqualConstraint, lessThanConstraint, lessThanEqualConstraint);
}
}

View File

@@ -1,15 +1,17 @@
package org.alfresco.rest.actions.access;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.gson.Gson;
import org.alfresco.rest.actions.access.pojo.Action;
import org.alfresco.rest.actions.access.pojo.ActionCondition;
import org.alfresco.rest.actions.access.pojo.Rule;
import org.alfresco.utility.model.UserModel;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class AccessRestrictionUtil {
public static final String MAIL_ACTION = "mail";
@@ -19,8 +21,8 @@ public class AccessRestrictionUtil {
"Only admin or system user is allowed to define uses of or directly execute this action";
private static final String ERROR_MESSAGE_FAILED_TO_SEND_EMAIL = "Failed to send email to:";
public static Map<String, String> createMailParameters(UserModel sender, UserModel recipient) {
Map<String, String> parameterValues = new HashMap<>();
public static Map<String, Serializable> createMailParameters(UserModel sender, UserModel recipient) {
Map<String, Serializable> parameterValues = new HashMap<>();
parameterValues.put("from", sender.getEmailAddress());
parameterValues.put("to", recipient.getEmailAddress());
parameterValues.put("subject", "Test");
@@ -29,7 +31,7 @@ public class AccessRestrictionUtil {
return parameterValues;
}
public static Rule createRuleWithAction(String actionName, Map<String, String> parameterValues) {
public static Rule createRuleWithAction(String actionName, Map<String, Serializable> parameterValues) {
Rule rule = new Rule();
rule.setId("");
rule.setTitle("Test rule title");
@@ -57,7 +59,7 @@ public class AccessRestrictionUtil {
return rule;
}
public static Action createActionWithParameters(String actionName, Map<String, String> parameterValues) {
public static Action createActionWithParameters(String actionName, Map<String, Serializable> parameterValues) {
Action compositeAction = new Action();
compositeAction.setActionDefinitionName("composite-action");
@@ -76,7 +78,7 @@ public class AccessRestrictionUtil {
}
public static Action createAction(String actionName, Map<String, String> parameterValues) {
public static Action createAction(String actionName, Map<String, Serializable> parameterValues) {
Action action = new Action();
action.setActionDefinitionName(actionName);
action.setParameterValues(parameterValues);

View File

@@ -1,5 +1,15 @@
package org.alfresco.rest.actions.access;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.ERROR_MESSAGE_ACCESS_RESTRICTED;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.ERROR_MESSAGE_FIELD;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.MAIL_ACTION;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.createMailParameters;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.getExpectedEmailSendFailureMessage;
import static org.hamcrest.Matchers.containsString;
import java.io.Serializable;
import java.util.Map;
import org.alfresco.rest.RestTest;
import org.alfresco.rest.core.RestRequest;
import org.alfresco.rest.core.RestResponse;
@@ -13,15 +23,6 @@ import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.util.Map;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.ERROR_MESSAGE_ACCESS_RESTRICTED;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.ERROR_MESSAGE_FIELD;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.MAIL_ACTION;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.createMailParameters;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.getExpectedEmailSendFailureMessage;
import static org.hamcrest.Matchers.containsString;
public class FormProcAdminAccessRestrictionTest extends RestTest {
private static final String ACTION_FORM_PROCESSOR_ENDPOINT = "alfresco/service/api/action/%s/formprocessor";
@@ -75,7 +76,7 @@ public class FormProcAdminAccessRestrictionTest extends RestTest {
.assertThat().body(ERROR_MESSAGE_FIELD, containsString(getExpectedEmailSendFailureMessage(testUser)));
}
private String generateBody(Map<String, String> mailParameters) {
private String generateBody(Map<String, Serializable> mailParameters) {
JSONObject json = new JSONObject();
mailParameters.forEach((key, value) -> json.put(PROPERTY_PREFIX + key, value));

View File

@@ -1,5 +1,6 @@
package org.alfresco.rest.actions.access.pojo;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
@@ -8,7 +9,7 @@ public class Action {
private String actionedUponNode;
private List<ActionCondition> conditions;
private List<Action> actions;
private Map<String, String> parameterValues;
private Map<String, Serializable> parameterValues;
private boolean executeAsynchronously;
@@ -47,11 +48,11 @@ public class Action {
this.actions = actions;
}
public Map<String, String> getParameterValues() {
public Map<String, Serializable> getParameterValues() {
return parameterValues;
}
public void setParameterValues(Map<String, String> parameterValues) {
public void setParameterValues(Map<String, Serializable> parameterValues) {
this.parameterValues = parameterValues;
}
}

View File

@@ -26,7 +26,6 @@
package org.alfresco.rest.rules;
import static java.util.stream.Collectors.toList;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.ERROR_MESSAGE_ACCESS_RESTRICTED;
import static org.alfresco.rest.rules.RulesTestsUtils.ID;
import static org.alfresco.rest.rules.RulesTestsUtils.INVERTED;
@@ -34,6 +33,7 @@ import static org.alfresco.rest.rules.RulesTestsUtils.IS_SHARED;
import static org.alfresco.rest.rules.RulesTestsUtils.RULE_NAME_DEFAULT;
import static org.alfresco.rest.rules.RulesTestsUtils.createAddAudioAspectAction;
import static org.alfresco.rest.rules.RulesTestsUtils.createCompositeCondition;
import static org.alfresco.rest.rules.RulesTestsUtils.createCustomActionModel;
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModel;
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModelWithDefaultValues;
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModelWithModifiedValues;
@@ -124,7 +124,7 @@ public class CreateRulesTests extends RestTest
restClient.authenticateUser(user).withCoreAPI().usingNode(nonExistentFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
restClient.assertStatusCodeIs(NOT_FOUND);
restClient.assertLastError().containsSummary("fake-id was not found");
restClient.assertLastError().containsSummary("Folder with id fake-id was not found");
}
/** Check creating a rule in a non-existent rule set returns an error. */
@@ -138,7 +138,7 @@ public class CreateRulesTests extends RestTest
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingRuleSet("fake-id").createSingleRule(ruleModel);
restClient.assertStatusCodeIs(NOT_FOUND);
restClient.assertLastError().containsSummary("fake-id was not found");
restClient.assertLastError().containsSummary("Rule set with id fake-id was not found");
}
/** Try to create a rule without a name and check the error. */
@@ -441,8 +441,94 @@ public class CreateRulesTests extends RestTest
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(NOT_FOUND);
restClient.assertLastError().containsSummary(actionDefinitionId);
restClient.assertStatusCodeIs(BAD_REQUEST);
restClient.assertLastError().containsSummary(String.format("Invalid action definition requested %s", actionDefinitionId));
}
/**
* Check we get error when attempt to create a rule with missing action parameters.
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void createRuleWithMissingActionParametersShouldFail()
{
final RestRuleModel ruleModel = createRuleModelWithDefaultValues();
final RestActionBodyExecTemplateModel invalidAction = new RestActionBodyExecTemplateModel();
final String actionDefinitionId = "copy";
invalidAction.setActionDefinitionId(actionDefinitionId);
ruleModel.setActions(List.of(invalidAction));
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(BAD_REQUEST);
restClient.assertLastError().containsSummary(
String.format("Action parameters should not be null or empty for this action. See Action Definition for action of: %s",
actionDefinitionId));
}
/**
* Check we get error when attempt to create a rule with parameter not fulfilling constraint.
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void createRuleWithActionParameterNotFulfillingConstraint()
{
final RestRuleModel ruleModel = createRuleModelWithDefaultValues();
final String actionDefinitionId = "script";
final String scriptRef = "script-ref";
final String scriptNodeId = "dummy-script-node-id";
final RestActionBodyExecTemplateModel scriptAction = createCustomActionModel(actionDefinitionId, Map.of(scriptRef, scriptNodeId));
ruleModel.setActions(List.of(scriptAction));
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(BAD_REQUEST);
final String acScriptsConstraint = "ac-scripts";
restClient.assertLastError().containsSummary(
String.format("Action parameter: %s has invalid value (%s). Look up possible values for constraint name %s",
scriptRef, scriptNodeId, acScriptsConstraint));
}
/**
* Check we get error when attempt to create a rule with action parameter that should not be passed.
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void createRuleWithoutInvalidActionParameterShouldFail()
{
final RestRuleModel ruleModel = createRuleModelWithDefaultValues();
final RestActionBodyExecTemplateModel invalidAction = new RestActionBodyExecTemplateModel();
final String actionDefinitionId = "add-features";
invalidAction.setActionDefinitionId(actionDefinitionId);
final String invalidParameterKey = "invalidParameterKey";
invalidAction.setParams(Map.of(invalidParameterKey,"dummyValue"));
ruleModel.setActions(List.of(invalidAction));
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(BAD_REQUEST);
restClient.assertLastError().containsSummary(
String.format("Action of definition id: %s must not contain parameter of name: %s", actionDefinitionId, invalidParameterKey));
}
/**
* Check we get error when attempt to create a rule with missing mandatory action parameter.
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void createRuleWithoutMandatoryActionParametersShouldFail()
{
final RestRuleModel ruleModel = createRuleModelWithDefaultValues();
final RestActionBodyExecTemplateModel invalidAction = new RestActionBodyExecTemplateModel();
final String actionDefinitionId = "copy";
invalidAction.setActionDefinitionId(actionDefinitionId);
invalidAction.setParams(Map.of("deep-copy",false));
ruleModel.setActions(List.of(invalidAction));
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(BAD_REQUEST);
restClient.assertLastError().containsSummary("Missing action's mandatory parameter: destination-folder");
}
/**

View File

@@ -43,7 +43,6 @@ import org.alfresco.dataprep.CMISUtil;
import org.alfresco.rest.RestTest;
import org.alfresco.rest.model.RestActionBodyExecTemplateModel;
import org.alfresco.rest.model.RestNodeModel;
import org.alfresco.rest.model.RestRuleExecutionBodyModel;
import org.alfresco.rest.model.RestRuleExecutionModel;
import org.alfresco.rest.model.RestRuleModel;
import org.alfresco.utility.constants.UserRole;
@@ -55,6 +54,7 @@ import org.alfresco.utility.model.UserModel;
import org.springframework.http.HttpStatus;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Ignore;
import org.testng.annotations.Test;
/**
@@ -81,7 +81,7 @@ public class ExecuteRulesTests extends RestTest
site = dataSite.usingUser(user).createPublicRandomSite();
}
@BeforeMethod
@BeforeMethod(alwaysRun = true)
public void setUp()
{
STEP("Create parent folder, rule folder and file in it");
@@ -112,7 +112,6 @@ public class ExecuteRulesTests extends RestTest
STEP("Execute rule");
RestRuleExecutionModel executionResult = restClient.authenticateUser(user).withCoreAPI().usingNode(childFolder).executeRules(createRuleExecutionRequest());
restClient.assertStatusCodeIs(HttpStatus.CREATED);
executionResult.assertThat().field("isEachInheritedRuleExecuted").is(false);
executionResult.assertThat().field("isEachSubFolderIncluded").is(false);
STEP("Check if only Audio aspect was added");
@@ -133,11 +132,9 @@ public class ExecuteRulesTests extends RestTest
assertThat(fileNode).notContainsAspects(AUDIO_ASPECT, LOCKABLE_ASPECT);
STEP("Execute rules including inherited rules");
RestRuleExecutionBodyModel ruleExecutionRequest = createRuleExecutionRequest();
ruleExecutionRequest.setIsEachInheritedRuleExecuted(true);
RestRuleExecutionModel ruleExecutionRequest = createRuleExecutionRequest();
RestRuleExecutionModel executionResult = restClient.authenticateUser(user).withCoreAPI().usingNode(childFolder).executeRules(ruleExecutionRequest);
restClient.assertStatusCodeIs(HttpStatus.CREATED);
executionResult.assertThat().field("isEachInheritedRuleExecuted").is(true);
executionResult.assertThat().field("isEachSubFolderIncluded").is(false);
STEP("Check if Audio and Lockable aspects were added");
@@ -163,11 +160,10 @@ public class ExecuteRulesTests extends RestTest
assertThat(fileNode).notContainsAspects(AUDIO_ASPECT, LOCKABLE_ASPECT);
STEP("Execute rules on parent folder including sub-folders");
RestRuleExecutionBodyModel ruleExecutionRequest = createRuleExecutionRequest();
RestRuleExecutionModel ruleExecutionRequest = createRuleExecutionRequest();
ruleExecutionRequest.setIsEachSubFolderIncluded(true);
RestRuleExecutionModel executionResult = restClient.authenticateUser(user).withCoreAPI().usingNode(parentFolder).executeRules(ruleExecutionRequest);
restClient.assertStatusCodeIs(HttpStatus.CREATED);
executionResult.assertThat().field("isEachInheritedRuleExecuted").is(false);
executionResult.assertThat().field("isEachSubFolderIncluded").is(true);
STEP("Check if Lockable aspects was added to parent folder's file");
@@ -182,7 +178,6 @@ public class ExecuteRulesTests extends RestTest
restClient.assertStatusCodeIs(HttpStatus.OK);
assertThat(fileNode)
.containsAspects(AUDIO_ASPECT, LOCKABLE_ASPECT);
// LOCKABLE_ASPECT shouldn't be present here, see ACS-3683
}
/**
@@ -205,7 +200,6 @@ public class ExecuteRulesTests extends RestTest
RestRuleExecutionModel executionResult = restClient.authenticateUser(user).withCoreAPI().usingNode(childFolder).executeRules(createRuleExecutionRequest());
restClient.assertStatusCodeIs(HttpStatus.CREATED);
executionResult.assertThat().field("isEachSubFolderIncluded").is(false);
executionResult.assertThat().field("isEachInheritedRuleExecuted").is(false);
STEP("Check if Audio aspect is still missing");
fileNode = restClient.authenticateUser(user).withCoreAPI().usingNode(childFolderFile).getNode();
@@ -231,10 +225,8 @@ public class ExecuteRulesTests extends RestTest
STEP("Execute child folder rules including inherited rules");
RestRuleExecutionModel executionResult = restClient.authenticateUser(user).withCoreAPI().usingNode(childFolder).executeRules(createRuleExecutionRequest());
executionResult.setIsEachInheritedRuleExecuted(true);
restClient.assertStatusCodeIs(HttpStatus.CREATED);
executionResult.assertThat().field("isEachSubFolderIncluded").is(false);
executionResult.assertThat().field("isEachInheritedRuleExecuted").is(true);
STEP("Check if Audio aspect is present and Lockable is still missing");
fileNode = restClient.authenticateUser(user).withCoreAPI().usingNode(childFolderFile).getNode();
@@ -248,7 +240,7 @@ public class ExecuteRulesTests extends RestTest
* Try to execute private folder's rules by user not added to site and receive 403.
*/
@Test(groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.ACTIONS })
public void executeRules_privateFolder()
public void executeRules_privateFolderResultsWith403()
{
STEP("Using admin create private site, folder and rule");
SiteModel privateSite = dataSite.usingAdmin().createPrivateRandomSite();
@@ -265,7 +257,7 @@ public class ExecuteRulesTests extends RestTest
* Try to execute private folder's rules as site contributor and receive 403.
*/
@Test(groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.ACTIONS })
public void executeRules_privateFolderAsContributor()
public void executeRules_privateFolderAsContributorResultsWith403()
{
STEP("Using admin create private site, folder, file in it, rule and add user to site as contributor");
UserModel contributor = dataUser.createRandomTestUser();
@@ -310,20 +302,5 @@ public class ExecuteRulesTests extends RestTest
assertThat(fileNode).containsAspects(AUDIO_ASPECT);
}
/**
* Try to execute rule with broken action and receive 500.
*/
@Test(groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.ACTIONS })
public void executeRules_brokenAction()
{
STEP("Update folder rule with broken action");
RestActionBodyExecTemplateModel brokenAction = createCustomActionModel("set-property-value", Map.of("aspect-name", AUDIO_ASPECT));
childFolderRule.setActions(List.of(brokenAction));
restClient.authenticateUser(user).withCoreAPI().usingNode(childFolder).usingDefaultRuleSet().updateRule(childFolderRule.getId(), childFolderRule);
restClient.assertStatusCodeIs(HttpStatus.OK);
STEP("Try to execute rule with broken action");
restClient.authenticateUser(user).withCoreAPI().usingNode(childFolder).executeRules(createRuleExecutionRequest());
restClient.assertStatusCodeIs(HttpStatus.INTERNAL_SERVER_ERROR);
}
//TODO: add test(s) that would cover handling executing broken rule and/or broken rule execution (ACS-3699)
}

View File

@@ -440,7 +440,7 @@ public class RuleSetLinksTests extends RestTest
STEP("Assert unlink result");
restClient.assertStatusCodeIs(NOT_FOUND)
.assertLastError().containsSummary("The entity with id:");
.assertLastError().containsSummary("Rule set with id non-existent-id was not found");
}
/**

View File

@@ -37,7 +37,7 @@ import java.util.Map;
import org.alfresco.rest.model.RestActionBodyExecTemplateModel;
import org.alfresco.rest.model.RestCompositeConditionDefinitionModel;
import org.alfresco.rest.model.RestNodeModel;
import org.alfresco.rest.model.RestRuleExecutionBodyModel;
import org.alfresco.rest.model.RestRuleExecutionModel;
import org.alfresco.rest.model.RestRuleModel;
import org.alfresco.rest.model.RestSimpleConditionDefinitionModel;
@@ -171,10 +171,10 @@ public class RulesTestsUtils
Map.of("destination-folder", "fake-folder-node", "assoc-name", "cm:checkout", "assoc-type",
"cm:contains");
final RestActionBodyExecTemplateModel checkOutAction = createCustomActionModel("check-out", checkOutParams);
final Map<String, Serializable> scriptParams = Map.of("script-ref", "dummy-script-node-id");
final RestActionBodyExecTemplateModel scriptAction = createCustomActionModel("script", scriptParams);
// The counter action takes no parameters, so check we can omit the "params" entry.
final RestActionBodyExecTemplateModel counterAction = createCustomActionModel("counter", null);
final RestRuleModel ruleModel = createRuleModelWithDefaultValues();
ruleModel.setActions(Arrays.asList(copyAction, checkOutAction, scriptAction));
ruleModel.setActions(Arrays.asList(copyAction, checkOutAction, counterAction));
return ruleModel;
}
@@ -209,16 +209,15 @@ public class RulesTestsUtils
return createCompositeCondition(AND, inverted, null, simpleConditions);
}
public static RestRuleExecutionBodyModel createRuleExecutionRequest()
public static RestRuleExecutionModel createRuleExecutionRequest()
{
return createRuleExecutionRequest(false, false);
return createRuleExecutionRequest(false);
}
public static RestRuleExecutionBodyModel createRuleExecutionRequest(boolean eachSubFolderIncluded, boolean eachInheritedRuleExecuted)
public static RestRuleExecutionModel createRuleExecutionRequest(boolean eachSubFolderIncluded)
{
RestRuleExecutionBodyModel ruleExecutionBody = new RestRuleExecutionBodyModel();
RestRuleExecutionModel ruleExecutionBody = new RestRuleExecutionModel();
ruleExecutionBody.setIsEachSubFolderIncluded(eachSubFolderIncluded);
ruleExecutionBody.setIsEachInheritedRuleExecuted(eachInheritedRuleExecuted);
return ruleExecutionBody;
}

View File

@@ -94,7 +94,7 @@ public class SetInheritanceTests extends RestTest
.retrieveSetting();
restClient.assertLastError().statusCodeIs(NOT_FOUND)
.containsSummary("The entity with id: fake-id was not found");
.containsSummary("Folder with id fake-id was not found");
}
/** Check we get an error when trying to retrieve a non-existent setting. */
@@ -188,7 +188,7 @@ public class SetInheritanceTests extends RestTest
.updateSetting(updateBody);
restClient.assertLastError().statusCodeIs(NOT_FOUND)
.containsSummary("The entity with id: fake-id was not found");
.containsSummary("Folder with id fake-id was not found");
}
/** Check we get an error when trying to set a non-existent setting. */

View File

@@ -122,7 +122,7 @@ public class UpdateRulesTests extends RestTest
.updateRule(rule.getId(), updatedRuleModel);
restClient.assertLastError().statusCodeIs(NOT_FOUND)
.containsSummary("fake-id was not found");
.containsSummary("Folder with id fake-id was not found");
}
/** Check we get a 404 if trying to update a rule in a rule set that doesn't exist. */
@@ -138,7 +138,7 @@ public class UpdateRulesTests extends RestTest
.updateRule(rule.getId(), updatedRuleModel);
restClient.assertLastError().statusCodeIs(NOT_FOUND)
.containsSummary("fake-id was not found");
.containsSummary("Rule set with id fake-id was not found");
}
/** Check we get a 404 if trying to update a rule that doesn't exist. */
@@ -255,8 +255,8 @@ public class UpdateRulesTests extends RestTest
.include(IS_SHARED)
.updateRule(rule.getId(), rule);
restClient.assertStatusCodeIs(NOT_FOUND);
restClient.assertLastError().containsSummary(actionDefinitionId);
restClient.assertStatusCodeIs(BAD_REQUEST);
restClient.assertLastError().containsSummary(String.format("Invalid action definition requested %s", actionDefinitionId));
}
/** Check we can use the POST response to create the new rule. */
@@ -472,9 +472,9 @@ public class UpdateRulesTests extends RestTest
final Map<String, Serializable> copyParams =
Map.of("destination-folder", "dummy-folder-node", "deep-copy", true);
final RestActionBodyExecTemplateModel copyAction = createCustomActionModel("copy", copyParams);
final Map<String, Serializable> scriptParams = Map.of("script-ref", "dummy-script-node-id");
final RestActionBodyExecTemplateModel scriptAction = createCustomActionModel("script", scriptParams);
rule.setActions(Arrays.asList(copyAction, scriptAction));
final Map<String, Serializable> addAspectParams = Map.of("aspect-name", "cm:taggable");
final RestActionBodyExecTemplateModel addAspectAction = createCustomActionModel("add-features", addAspectParams);
rule.setActions(Arrays.asList(copyAction, addAspectAction));
final RestRuleModel updatedRule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.updateRule(rule.getId(), rule);
@@ -519,14 +519,18 @@ public class UpdateRulesTests extends RestTest
STEP("Try to update the rule by adding action with invalid parameter (non-existing namespace in value)");
final RestActionBodyExecTemplateModel action = new RestActionBodyExecTemplateModel();
action.setActionDefinitionId("add-features");
action.setParams(Map.of("aspect-name", "dummy:dummy"));
final String aspectNameParam = "aspect-name";
final String paramValue = "dummy:dummy";
action.setParams(Map.of(aspectNameParam, paramValue));
rule.setActions(List.of(action));
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.updateRule(rule.getId(), rule);
restClient.assertStatusCodeIs(INTERNAL_SERVER_ERROR);
restClient.assertLastError().containsSummary("Namespace prefix dummy is not mapped to a namespace URI");
restClient.assertStatusCodeIs(BAD_REQUEST);
restClient.assertLastError().containsSummary(
String.format("Action parameter: %s has invalid value (%s). Look up possible values for constraint name %s",
aspectNameParam, paramValue, "ac-aspects"));
}
/** Check that a normal user cannot create rules that use private actions. */

View File

@@ -9,7 +9,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>17.152</version>
<version>17.162</version>
</parent>
<developers>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId>
<version>17.152</version>
<version>17.162</version>
</parent>
<properties>

View File

@@ -139,6 +139,33 @@
<param name="cookie">{token}</param>
</action>
</rule>
<rule>
<request>
<method>GET</method>
<path>/s/index|/s/</path>
</request>
<action name="generateToken">
<param name="session">{token}</param>
<param name="cookie">{token}</param>
</action>
</rule>
<rule>
<request>
<method>POST</method>
<path>/s/index|/s/</path>
</request>
<action name="assertToken">
<param name="session">{token}</param>
<param name="parameter">{token}</param>
</action>
<action name="assertReferer">
<param name="referer">{referer}</param>
</action>
<action name="assertOrigin">
<param name="origin">{origin}</param>
</action>
</rule>
<!--
Verify multipart requests contain the token as a parameter

View File

@@ -231,6 +231,12 @@
<url-pattern>/wcs/admin/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CSRF Token Filter</filter-name>
<url-pattern>/s/index</url-pattern>
<url-pattern>/s/</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>Security Headers Filter</filter-name>
<url-pattern>/*</url-pattern>

15
pom.xml
View File

@@ -2,7 +2,7 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>alfresco-community-repo</artifactId>
<version>17.152</version>
<version>17.162</version>
<packaging>pom</packaging>
<name>Alfresco Community Repo Parent</name>
@@ -51,15 +51,14 @@
<dependency.alfresco-log-sanitizer.version>0.2</dependency.alfresco-log-sanitizer.version>
<dependency.activiti-engine.version>5.23.0</dependency.activiti-engine.version>
<dependency.activiti.version>5.23.0</dependency.activiti.version>
<dependency.alfresco-transform-service.version>2.0.0-A3</dependency.alfresco-transform-service.version>
<dependency.alfresco-transform-core.version>3.0.0-A3</dependency.alfresco-transform-core.version>
<dependency.alfresco-transform-service.version>2.0.0-A4</dependency.alfresco-transform-service.version>
<dependency.alfresco-transform-core.version>3.0.0-A4</dependency.alfresco-transform-core.version>
<dependency.alfresco-greenmail.version>6.4</dependency.alfresco-greenmail.version>
<dependency.acs-event-model.version>0.0.16</dependency.acs-event-model.version>
<dependency.spring.version>5.3.23</dependency.spring.version>
<dependency.antlr.version>3.5.3</dependency.antlr.version>
<dependency.jackson.version>2.13.3</dependency.jackson.version>
<dependency.jackson-databind.version>2.13.3</dependency.jackson-databind.version>
<dependency.jackson.version>2.14.0-rc1</dependency.jackson.version>
<dependency.cxf.version>3.5.3</dependency.cxf.version>
<dependency.opencmis.version>1.0.0</dependency.opencmis.version>
<dependency.webscripts.version>8.32</dependency.webscripts.version>
@@ -123,7 +122,7 @@
<dependency.mariadb.version>2.7.4</dependency.mariadb.version>
<dependency.tas-utility.version>3.0.56</dependency.tas-utility.version>
<dependency.rest-assured.version>5.2.0</dependency.rest-assured.version>
<dependency.tas-restapi.version>1.128</dependency.tas-restapi.version>
<dependency.tas-restapi.version>1.134</dependency.tas-restapi.version>
<dependency.tas-email.version>1.9</dependency.tas-email.version>
<dependency.tas-webdav.version>1.7</dependency.tas-webdav.version>
<dependency.tas-ftp.version>1.7</dependency.tas-ftp.version>
@@ -150,7 +149,7 @@
<connection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</connection>
<developerConnection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</developerConnection>
<url>https://github.com/Alfresco/alfresco-community-repo</url>
<tag>17.152</tag>
<tag>17.162</tag>
</scm>
<distributionManagement>
@@ -503,7 +502,7 @@
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${dependency.jackson-databind.version}</version>
<version>${dependency.jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>17.152</version>
<version>17.162</version>
</parent>
<dependencies>

View File

@@ -121,6 +121,13 @@ public class WebDAVServlet extends HttpServlet
startTime = System.currentTimeMillis();
}
if (request.getMethod().equals(WebDAV.METHOD_POST) && !initParams.allowInsecurePOSTMethod())
{
logger.error("POST method is not allowed!");
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
return;
}
FileFilterMode.setClient(Client.webdav);
try
@@ -407,6 +414,7 @@ public class WebDAVServlet extends HttpServlet
private String storeName;
private String rootPath;
private String urlPathPrefix;
private boolean allowInsecurePOSTMethod = false;
public boolean getEnabled()
{
@@ -482,5 +490,15 @@ public class WebDAVServlet extends HttpServlet
{
this.urlPathPrefix = urlPathPrefix;
}
public boolean allowInsecurePOSTMethod()
{
return allowInsecurePOSTMethod;
}
public void setAllowInsecurePOSTMethod(boolean allowInsecurePOSTMethod)
{
this.allowInsecurePOSTMethod = allowInsecurePOSTMethod;
}
}
}

View File

@@ -2,7 +2,7 @@
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* 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
@@ -29,8 +29,10 @@ package org.alfresco.rest.api;
import org.alfresco.rest.api.model.Action;
import org.alfresco.rest.api.model.ActionDefinition;
import org.alfresco.rest.api.model.ActionParameterConstraint;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.repository.NodeRef;
public interface Actions
@@ -45,7 +47,10 @@ public interface Actions
{
NAME,
TITLE
};
}
Action executeAction(Action action, Parameters parameters);
@Experimental
ActionParameterConstraint getActionConstraint(String constraintName);
}

View File

@@ -104,7 +104,6 @@ public interface Rules
*
* @param folderNodeId - the ID of a folder
* @param eachSubFolderIncluded - indicates if rules should be executed also on sub-folders
* @param eachInheritedRuleExecuted - indicates if the inherited rules should be also executed
*/
RuleExecution executeRules(final String folderNodeId, final boolean eachSubFolderIncluded, final boolean eachInheritedRuleExecuted);
RuleExecution executeRules(final String folderNodeId, final boolean eachSubFolderIncluded);
}

View File

@@ -0,0 +1,59 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2017 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.rest.api.actions;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.rest.api.Actions;
import org.alfresco.rest.api.model.ActionParameterConstraint;
import org.alfresco.rest.framework.WebApiDescription;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.resource.EntityResource;
import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.service.Experimental;
@EntityResource(name="action-constraints", title = "Action parameter constraints")
@Experimental
public class ActionConstraintsEntityResource implements EntityResourceAction.ReadById<ActionParameterConstraint>
{
private final Actions actions;
public ActionConstraintsEntityResource(Actions actions)
{
this.actions = actions;
}
@WebApiDescription(title = "Get single action parameters constraint",
description = "Retrieves a single action parameters constraint by constraint name",
successStatus = HttpServletResponse.SC_OK)
@Experimental
@Override
public ActionParameterConstraint readById(String constraintName, Parameters parameters) throws EntityNotFoundException
{
return actions.getActionConstraint(constraintName);
}
}

View File

@@ -0,0 +1,59 @@
/*
* #%L
* Alfresco Remote API
* %%
* 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.rest.api.actions;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.rest.api.Actions;
import org.alfresco.rest.api.model.ActionParameterConstraint;
import org.alfresco.rest.framework.WebApiDescription;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.resource.EntityResource;
import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.service.Experimental;
@EntityResource(name="action-parameter-constraints", title = "Action parameter constraints")
@Experimental
public class ActionParameterConstraintsEntityResource implements EntityResourceAction.ReadById<ActionParameterConstraint>
{
private final Actions actions;
public ActionParameterConstraintsEntityResource(Actions actions)
{
this.actions = actions;
}
@WebApiDescription(title = "Get single action parameter constraint",
description = "Retrieves a single action parameter constraint by constraint name",
successStatus = HttpServletResponse.SC_OK)
@Experimental
@Override
public ActionParameterConstraint readById(String constraintName, Parameters parameters) throws EntityNotFoundException
{
return actions.getActionConstraint(constraintName);
}
}

View File

@@ -0,0 +1,38 @@
/*
* #%L
* Alfresco Remote API
* %%
* 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.rest.api.actions;
import org.alfresco.rest.api.model.rules.Action;
import org.alfresco.service.Experimental;
@Experimental
public interface ActionValidator
{
void validate(Action action);
boolean isEnabled();
}

View File

@@ -27,15 +27,22 @@ package org.alfresco.rest.api.impl;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.action.access.ActionAccessRestriction;
import org.alfresco.repo.action.constraint.FolderContentsParameterConstraint;
import org.alfresco.rest.api.Actions;
import org.alfresco.rest.api.impl.rules.ActionParameterConverter;
import org.alfresco.rest.api.model.Action;
import org.alfresco.rest.api.model.ActionDefinition;
import org.alfresco.rest.api.model.ActionParameterConstraint;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.ListPage;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.rest.framework.resource.parameters.SortColumn;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.action.ParameterConstraint;
import org.alfresco.service.cmr.action.ParameterDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryException;
@@ -59,6 +66,7 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
@@ -68,11 +76,14 @@ import static java.util.Comparator.nullsFirst;
public class ActionsImpl implements Actions
{
static final String CONSTRAINT_NOT_EXISTS = "Action parameter constraints for name %s do not exist.";
private ActionService actionService;
private DictionaryService dictionaryService;
private NamespaceService namespaceService;
private NodeService nodeService;
private NamespacePrefixResolver prefixResolver;
private ActionParameterConverter actionParameterConverter;
public void setActionService(ActionService actionService)
{
@@ -99,6 +110,11 @@ public class ActionsImpl implements Actions
this.prefixResolver = prefixResolver;
}
public void setActionParameterConverter(ActionParameterConverter actionParameterConverter)
{
this.actionParameterConverter = actionParameterConverter;
}
@Override
public ActionDefinition getActionDefinitionById(String actionDefinitionId)
{
@@ -125,10 +141,10 @@ public class ActionsImpl implements Actions
return result;
}
private ActionDefinition getActionDefinition(
private ActionDefinition getActionDefinition(
org.alfresco.service.cmr.action.ActionDefinition actionDefinitionId)
{
{
List<ActionDefinition.ParameterDefinition> paramDefs =
actionDefinitionId.
getParameterDefinitions().
@@ -145,7 +161,7 @@ public class ActionsImpl implements Actions
actionDefinitionId.getTrackStatus(),
paramDefs);
}
@Override
public CollectionWithPagingInfo<ActionDefinition> getActionDefinitions(NodeRef nodeRef, Parameters params)
{
@@ -174,7 +190,7 @@ public class ActionsImpl implements Actions
sortKey = Actions.SortKey.valueOf(sorting.get(0).column.toUpperCase());
sortAsc = sorting.get(0).asc;
}
Comparator<? super ActionDefinition> comparator;
switch (sortKey)
{
@@ -187,7 +203,7 @@ public class ActionsImpl implements Actions
default:
throw new IllegalArgumentException("Invalid sort key, must be either 'title' or 'name'.");
}
if (!sortAsc)
{
comparator = comparator.reversed();
@@ -220,7 +236,7 @@ public class ActionsImpl implements Actions
skip(skip).
limit(maxItems).
collect(Collectors.toList());
boolean hasMoreItems = actionDefinitions.size() > (skip + maxItems);
return CollectionWithPagingInfo.asPaged(
@@ -297,6 +313,52 @@ public class ActionsImpl implements Actions
return result;
}
@Override
@Experimental
public ActionParameterConstraint getActionConstraint(String constraintName)
{
final ParameterConstraint parameterConstraint = actionService.getParameterConstraint(constraintName);
if (Objects.isNull(parameterConstraint))
{
throw new NotFoundException(String.format(CONSTRAINT_NOT_EXISTS, constraintName));
}
return mapToActionConstraint(parameterConstraint);
}
@Experimental
private ActionParameterConstraint mapToActionConstraint(ParameterConstraint parameterConstraint)
{
final ActionParameterConstraint constraint = new ActionParameterConstraint();
constraint.setConstraintName(parameterConstraint.getName());
constraint.setConstraintValues(getConstraintDataList(parameterConstraint));
return constraint;
}
@Experimental
private List<ActionParameterConstraint.ConstraintData> getConstraintDataList(final ParameterConstraint parameterConstraint)
{
final Map<String, String> constraintValues = parameterConstraint.getValues();
if (parameterConstraint instanceof FolderContentsParameterConstraint)
{
return convertNodeRefConstraintValues(constraintValues).entrySet().stream()
.map(e -> new ActionParameterConstraint.ConstraintData(e.getKey(), e.getValue()))
.collect(Collectors.toList());
} else
{
return constraintValues.entrySet().stream()
.map(e -> new ActionParameterConstraint.ConstraintData(e.getKey(), e.getValue()))
.collect(Collectors.toList());
}
}
@Experimental
private Map<String, String> convertNodeRefConstraintValues(final Map<String, String> inputValues)
{
return inputValues.entrySet().stream()
.collect(Collectors.toMap(e -> actionParameterConverter.convertParamFromServiceModel(new NodeRef(e.getKey())).toString(),
Map.Entry::getValue));
}
private Map<String, Serializable> extractActionParams(org.alfresco.service.cmr.action.ActionDefinition actionDefinition, Map<String, String> params)
{
Map<String, Serializable> parameterValues = new HashMap<>();

View File

@@ -400,12 +400,10 @@ public class NodesImpl implements Nodes
@Override
public NodeRef validateNode(StoreRef storeRef, String nodeId)
{
String versionLabel = null;
int idx = nodeId.indexOf(";");
if (idx != -1)
{
versionLabel = nodeId.substring(idx + 1);
String versionLabel = nodeId.substring(idx + 1);
nodeId = nodeId.substring(0, idx);
if (versionLabel.equals("pwc"))
{
@@ -1753,7 +1751,7 @@ public class NodesImpl implements Nodes
// default false (if not provided)
boolean permanentDelete = Boolean.valueOf(parameters.getParameter(PARAM_PERMANENT));
if (permanentDelete == true)
if (permanentDelete)
{
boolean isAdmin = authorityService.hasAdminAuthority();
if (! isAdmin)

View File

@@ -26,15 +26,20 @@
package org.alfresco.rest.api.impl.mapper.rules;
import static java.util.Collections.emptyMap;
import static org.alfresco.repo.action.access.ActionAccessRestriction.ACTION_CONTEXT_PARAM_NAME;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.alfresco.repo.action.ActionImpl;
import org.alfresco.repo.action.CompositeActionImpl;
import org.alfresco.rest.api.actions.ActionValidator;
import org.alfresco.rest.api.impl.rules.ActionParameterConverter;
import org.alfresco.rest.api.model.mapper.RestModelMapper;
import org.alfresco.rest.api.model.rules.Action;
@@ -46,10 +51,13 @@ import org.apache.commons.collections.CollectionUtils;
public class RestRuleActionModelMapper implements RestModelMapper<Action, org.alfresco.service.cmr.action.Action>
{
private final ActionParameterConverter parameterConverter;
private final List<ActionValidator> actionValidators;
public RestRuleActionModelMapper(ActionParameterConverter parameterConverter)
public RestRuleActionModelMapper(ActionParameterConverter parameterConverter,
List<ActionValidator> actionValidators)
{
this.parameterConverter = parameterConverter;
this.actionValidators = actionValidators;
}
/**
@@ -100,8 +108,15 @@ public class RestRuleActionModelMapper implements RestModelMapper<Action, org.al
private org.alfresco.service.cmr.action.Action toServiceAction(Action action)
{
final Map<String, Serializable> params = Optional.ofNullable(action.getParams()).orElse(emptyMap());
validateAction(action);
final Map<String, Serializable> convertedParams =
parameterConverter.getConvertedParams(action.getParams(), action.getActionDefinitionId());
parameterConverter.getConvertedParams(params, action.getActionDefinitionId());
return new ActionImpl(null, GUID.generate(), action.getActionDefinitionId(), convertedParams);
}
private void validateAction(Action action) {
actionValidators.stream()
.filter(ActionValidator::isEnabled)
.forEach(v -> v.validate(action));
}
}

View File

@@ -35,6 +35,7 @@ import org.alfresco.repo.rule.RuleModel;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.model.Node;
import org.alfresco.rest.api.model.rules.RuleSet;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException;
@@ -65,14 +66,21 @@ public class NodeValidator
* @return folder node reference
* @throws InvalidArgumentException if node is not of an expected type
* @throws PermissionDeniedException if the user doesn't have the appropriate permission for the folder.
* @throws EntityNotFoundException if the folder node isn't found
*/
public NodeRef validateFolderNode(final String folderNodeId, boolean requireChangePermission)
{
final NodeRef nodeRef = nodes.validateOrLookupNode(folderNodeId, null);
validatePermission(requireChangePermission, nodeRef);
verifyNodeType(nodeRef, ContentModel.TYPE_FOLDER, null);
try
{
final NodeRef nodeRef = nodes.validateOrLookupNode(folderNodeId, null);
validatePermission(requireChangePermission, nodeRef);
verifyNodeType(nodeRef, ContentModel.TYPE_FOLDER, null);
return nodeRef;
return nodeRef;
} catch (EntityNotFoundException e)
{
throw new EntityNotFoundException("Folder with id " + folderNodeId + " was not found.", e);
}
}
/**
@@ -82,6 +90,8 @@ public class NodeValidator
* @param associatedFolderNodeRef - folder node ref to check the association
* @return rule set node reference
* @throws InvalidArgumentException in case of not matching associated folder node
* @throws RelationshipResourceNotFoundException if the folder doesn't have a -default- rule set
* @throws EntityNotFoundException if the rule set node isn't found
*/
public NodeRef validateRuleSetNode(final String ruleSetId, final NodeRef associatedFolderNodeRef)
{
@@ -96,13 +106,18 @@ public class NodeValidator
return ruleSetNodeRef;
}
final NodeRef ruleSetNodeRef = validateNode(ruleSetId, ContentModel.TYPE_SYSTEM_FOLDER, RULE_SET_EXPECTED_TYPE_NAME);
if (!ruleService.isRuleSetAssociatedWithFolder(ruleSetNodeRef, associatedFolderNodeRef))
{
throw new InvalidArgumentException("Rule set is not associated with folder node!");
}
try {
final NodeRef ruleSetNodeRef = validateNode(ruleSetId, ContentModel.TYPE_SYSTEM_FOLDER, RULE_SET_EXPECTED_TYPE_NAME);
return ruleSetNodeRef;
if (!ruleService.isRuleSetAssociatedWithFolder(ruleSetNodeRef, associatedFolderNodeRef))
{
throw new InvalidArgumentException("Rule set is not associated with folder node!");
}
return ruleSetNodeRef;
} catch (EntityNotFoundException e) {
throw new EntityNotFoundException("Rule set with id " + ruleSetId + " was not found.", e);
}
}
public NodeRef validateRuleSetNode(String linkToNodeId, boolean requireChangePermission)

View File

@@ -57,7 +57,6 @@ public class RuleSetLoader
private static final int MAX_LINKED_TO_BY_SIZE = 100;
private NodeService nodeService;
private RuleService ruleService;
private RestRuleModelMapper restRuleModelMapper;
/**
* Load a rule set for the given node ref.
@@ -167,8 +166,4 @@ public class RuleSetLoader
this.ruleService = ruleService;
}
public void setRestRuleModelMapper(RestRuleModelMapper restRuleModelMapper)
{
this.restRuleModelMapper = restRuleModelMapper;
}
}

View File

@@ -133,12 +133,12 @@ public class RulesImpl implements Rules
}
@Override
public RuleExecution executeRules(final String folderNodeId, final boolean eachSubFolderIncluded, final boolean eachInheritedRuleExecuted)
public RuleExecution executeRules(final String folderNodeId, final boolean eachSubFolderIncluded)
{
final NodeRef folderNodeRef = validator.validateFolderNode(folderNodeId, false);
final Map<String, Serializable> parameterValues = new HashMap<>();
parameterValues.put(ExecuteAllRulesActionExecuter.PARAM_RUN_ALL_RULES_ON_CHILDREN, eachSubFolderIncluded);
parameterValues.put(ExecuteAllRulesActionExecuter.PARAM_EXECUTE_INHERITED_RULES, eachInheritedRuleExecuted);
parameterValues.put(ExecuteAllRulesActionExecuter.PARAM_EXECUTE_INHERITED_RULES, true);
final ActionImpl action = new ActionImpl(null, GUID.generate(), ExecuteAllRulesActionExecuter.NAME);
action.setNodeRef(folderNodeRef);
action.setParameterValues(parameterValues);
@@ -148,7 +148,6 @@ public class RulesImpl implements Rules
return RuleExecution.builder()
.eachSubFolderIncluded(eachSubFolderIncluded)
.eachInheritedRuleExecuted(eachInheritedRuleExecuted)
.create();
}

View File

@@ -0,0 +1,133 @@
/*
* #%L
* Alfresco Remote API
* %%
* 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.rest.api.impl.validator.actions;
import java.io.Serializable;
import java.util.Map;
import org.alfresco.rest.api.Actions;
import org.alfresco.rest.api.actions.ActionValidator;
import org.alfresco.rest.api.model.ActionDefinition;
import org.alfresco.rest.api.model.ActionParameterConstraint;
import org.alfresco.rest.api.model.rules.Action;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
import org.alfresco.service.Experimental;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
/**
* This class will validate all action types against action parameters definitions (mandatory parameters, parameter constraints)
*/
@Experimental
public class ActionParameterDefinitionValidator implements ActionValidator
{
private static final boolean IS_ENABLED = true;
static final String INVALID_PARAMETER_VALUE =
"Action parameter: %s has invalid value (%s). Look up possible values for constraint name %s";
static final String MISSING_PARAMETER = "Missing action's mandatory parameter: %s";
static final String MUST_NOT_CONTAIN_PARAMETER = "Action of definition id: %s must not contain parameter of name: %s";
static final String PARAMS_SHOULD_NOT_BE_EMPTY =
"Action parameters should not be null or empty for this action. See Action Definition for action of: %s";
static final String INVALID_ACTION_DEFINITION = "Invalid action definition requested %s";
private final Actions actions;
public ActionParameterDefinitionValidator(Actions actions)
{
this.actions = actions;
}
/**
* Validates action against its parameters definitions (mandatory parameters, parameter constraints)
*
* @param action Action to be validated
*/
@Override
public void validate(Action action)
{
ActionDefinition actionDefinition;
try
{
actionDefinition = actions.getActionDefinitionById(action.getActionDefinitionId());
} catch (NotFoundException e) {
throw new InvalidArgumentException(String.format(INVALID_ACTION_DEFINITION, action.getActionDefinitionId()));
}
validateParametersSize(action.getParams(), actionDefinition);
final Map<String, Serializable> params = action.getParams();
if (MapUtils.isNotEmpty(params))
{
params.forEach((key, value) -> checkParameterShouldExist(key, actionDefinition));
actionDefinition.getParameterDefinitions().forEach(p -> validateParameterDefinitions(p, params));
}
}
@Override
public boolean isEnabled()
{
return IS_ENABLED;
}
private void validateParametersSize(final Map<String, Serializable> params, final ActionDefinition actionDefinition)
{
if (CollectionUtils.isNotEmpty(actionDefinition.getParameterDefinitions()) && MapUtils.isEmpty(params))
{
throw new IllegalArgumentException(String.format(PARAMS_SHOULD_NOT_BE_EMPTY, actionDefinition.getName()));
}
}
private void validateParameterDefinitions(final ActionDefinition.ParameterDefinition parameterDefinition,
final Map<String, Serializable> params)
{
final Serializable parameterValue = params.get(parameterDefinition.getName());
if (parameterDefinition.isMandatory() && parameterValue == null)
{
throw new IllegalArgumentException(String.format(MISSING_PARAMETER, parameterDefinition.getName()));
}
if (parameterDefinition.getParameterConstraintName() != null)
{
final ActionParameterConstraint actionConstraint =
actions.getActionConstraint(parameterDefinition.getParameterConstraintName());
if (parameterValue != null && actionConstraint.getConstraintValues().stream()
.noneMatch(constraintData -> constraintData.getValue().equals(parameterValue.toString())))
{
throw new IllegalArgumentException(String.format(INVALID_PARAMETER_VALUE, parameterDefinition.getName(), parameterValue,
actionConstraint.getConstraintName()));
}
}
}
private void checkParameterShouldExist(final String parameterName, final ActionDefinition actionDefinition)
{
if (actionDefinition.getParameterDefinitions().stream().noneMatch(pd -> parameterName.equals(pd.getName())))
{
throw new IllegalArgumentException(String.format(MUST_NOT_CONTAIN_PARAMETER, actionDefinition.getName(), parameterName));
}
}
}

View File

@@ -0,0 +1,99 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2021 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.rest.api.model;
import java.util.List;
import org.alfresco.service.Experimental;
/**
* Representation of action parameter constraint.
* Helps to constraint the list of allowable values for an action parameter.
* When action parameter has constraints defined (@see ActionDefinition.ParameterDefinition#getParameterConstraintName())
* they will be listed here.
*
* @author mpichura
*/
@Experimental
public class ActionParameterConstraint
{
/**
* Constraint name.
*/
private String constraintName;
/**
* List of objects representing constraint values along with additional data
*/
private List<ConstraintData> constraintValues;
public List<ConstraintData> getConstraintValues()
{
return constraintValues;
}
public void setConstraintValues(List<ConstraintData> constraintValues)
{
this.constraintValues = constraintValues;
}
public String getConstraintName()
{
return constraintName;
}
public void setConstraintName(String constraintName)
{
this.constraintName = constraintName;
}
public static class ConstraintData
{
public ConstraintData(final String value, final String label)
{
this.value = value;
this.label = label;
}
/**
* Actual constraint value
*/
private String value;
/**
* A label associated to constraint's value
*/
private String label;
public String getValue()
{
return value;
}
public String getLabel()
{
return label;
}
}
}

View File

@@ -33,7 +33,6 @@ import org.alfresco.service.Experimental;
public class RuleExecution
{
private boolean eachSubFolderIncluded;
private boolean eachInheritedRuleExecuted;
public boolean getIsEachSubFolderIncluded()
{
@@ -45,20 +44,10 @@ public class RuleExecution
this.eachSubFolderIncluded = eachSubFolderIncluded;
}
public boolean getIsEachInheritedRuleExecuted()
{
return eachInheritedRuleExecuted;
}
public void setIsEachInheritedRuleExecuted(boolean eachInheritedRuleExecuted)
{
this.eachInheritedRuleExecuted = eachInheritedRuleExecuted;
}
@Override
public String toString()
{
return "RuleExecution{" + "eachSubFolderIncluded=" + eachSubFolderIncluded + ", eachInheritedRuleExecuted=" + eachInheritedRuleExecuted + '}';
return "RuleExecution{" + "eachSubFolderIncluded=" + eachSubFolderIncluded + '}';
}
@Override
@@ -69,13 +58,13 @@ public class RuleExecution
if (o == null || getClass() != o.getClass())
return false;
RuleExecution that = (RuleExecution) o;
return eachSubFolderIncluded == that.eachSubFolderIncluded && eachInheritedRuleExecuted == that.eachInheritedRuleExecuted;
return eachSubFolderIncluded == that.eachSubFolderIncluded;
}
@Override
public int hashCode()
{
return Objects.hash(eachSubFolderIncluded, eachInheritedRuleExecuted);
return Objects.hash(eachSubFolderIncluded);
}
public static Builder builder()
@@ -86,7 +75,6 @@ public class RuleExecution
public static class Builder
{
private boolean eachSubFolderIncluded;
private boolean eachInheritedRuleExecuted;
public Builder eachSubFolderIncluded(boolean eachSubFolderIncluded)
{
@@ -94,17 +82,10 @@ public class RuleExecution
return this;
}
public Builder eachInheritedRuleExecuted(boolean eachInheritedRuleExecuted)
{
this.eachInheritedRuleExecuted = eachInheritedRuleExecuted;
return this;
}
public RuleExecution create()
{
final RuleExecution ruleExecution = new RuleExecution();
ruleExecution.setIsEachSubFolderIncluded(eachSubFolderIncluded);
ruleExecution.setIsEachInheritedRuleExecuted(eachInheritedRuleExecuted);
return ruleExecution;
}
}

View File

@@ -65,6 +65,6 @@ public class NodeRuleExecutionsRelation implements RelationshipResourceAction.Cr
public List<RuleExecution> create(String folderNodeId, List<RuleExecution> ruleExecutionParameters, Parameters parameters)
{
final RuleExecution ruleExecution = ruleExecutionParameters.stream().findFirst().orElse(new RuleExecution());
return List.of(rules.executeRules(folderNodeId, ruleExecution.getIsEachSubFolderIncluded(), ruleExecution.getIsEachInheritedRuleExecuted()));
return List.of(rules.executeRules(folderNodeId, ruleExecution.getIsEachSubFolderIncluded()));
}
}

View File

@@ -43,4 +43,9 @@ public class EntityNotFoundException extends NotFoundException
{
super(DEFAULT_MESSAGE_ID, new String[] {entityId});
}
public EntityNotFoundException(String msgId, Throwable cause)
{
super(msgId, cause);
}
}

View File

@@ -53,4 +53,9 @@ public class NotFoundException extends ApiException
super(msgId, notFoundObjects);
}
public NotFoundException(String msgId, Throwable cause)
{
super(msgId, cause);
}
}

View File

@@ -567,6 +567,7 @@
<property name="namespaceService" ref="NamespaceService"/>
<property name="nodeService" ref="NodeService"/>
<property name="prefixResolver" ref="namespaceService"/>
<property name="actionParameterConverter" ref="actionParameterConverter"/>
</bean>
<bean id="Actions" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="org.alfresco.rest.api.Actions"/>
@@ -584,7 +585,17 @@
<bean class="org.alfresco.rest.api.actions.ActionExecutionsEntityResource">
<property name="actions" ref="Actions"/>
</bean>
<bean class="org.alfresco.rest.api.actions.ActionParameterConstraintsEntityResource">
<constructor-arg name="actions" ref="Actions"/>
</bean>
<!-- action parameter validators start here -->
<bean id="actionParameterConstraintsValidator" class="org.alfresco.rest.api.impl.validator.actions.ActionParameterDefinitionValidator">
<constructor-arg name="actions" ref="Actions"/>
</bean>
<!-- action parameter validators end here-->
<bean id="Downloads" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.rest.api.Downloads</value>
@@ -865,7 +876,6 @@
<bean id="ruleSetLoader" class="org.alfresco.rest.api.impl.rules.RuleSetLoader">
<property name="nodeService" ref="NodeService" />
<property name="ruleService" ref="RuleService" />
<property name="restRuleModelMapper" ref="ruleMapper" />
</bean>
<bean id="ruleSets" class="org.alfresco.rest.api.impl.rules.RuleSetsImpl">
@@ -962,6 +972,11 @@
<bean id="actionMapper" class="org.alfresco.rest.api.impl.mapper.rules.RestRuleActionModelMapper">
<constructor-arg name="parameterConverter" ref="actionParameterConverter"/>
<constructor-arg name="actionValidators">
<list>
<ref bean="actionParameterConstraintsValidator"/>
</list>
</constructor-arg>
</bean>
<bean id="ruleMapper" class="org.alfresco.rest.api.impl.mapper.rules.RestRuleModelMapper">

View File

@@ -8,6 +8,7 @@
<property name="enabled" value="${system.webdav.servlet.enabled}" />
<property name="storeName" value="${system.webdav.storeName}" />
<property name="rootPath" value="${system.webdav.rootPath}" />
<property name="allowInsecurePOSTMethod" value="${system.webdav.allowInsecurePOSTMethod}" />
</bean>
<bean id="webDAVLockService" class="org.alfresco.repo.webdav.WebDAVLockServiceImpl">

View File

@@ -0,0 +1,82 @@
<#import "/org/springframework/extensions/webscripts/webscripts.lib.html.ftl" as wsLib/>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<@wsLib.head>${msg("alfresco.index.title")}</@wsLib.head>
<body>
<div>
<@wsLib.indexheader>Web Scripts Home</@wsLib.indexheader>
<#if failures?size &gt; 0>
<br/>
<table>
<tr><td><a href="${url.serviceContext}/index/failures">(+${failures?size} failed)</td></tr>
</table>
</#if>
<br>
<@wsLib.onlinedoc/>
<br/>
<span class="mainSubTitle">Index</span>
<#if rootfamily.children?size &gt; 0>
<table>
<#list rootfamily.children as childpath>
<tr><td><a href="${url.serviceContext}/index/family${childpath.path}">Browse '${childpath.name}' Web Scripts</a></td></tr>
</#list>
</table>
<br/>
</#if>
<table>
<tr><td><a href="${url.serviceContext}/index/all">Browse all Web Scripts</a></td></tr>
<tr><td><a href="${url.serviceContext}/index/uri/">Browse by Web Script URI</a></td></tr>
<tr><td><a href="${url.serviceContext}/index/package/">Browse by Web Script Package</a></td></tr>
<tr><td><a href="${url.serviceContext}/index/lifecycle/">Browse by Web Script Lifecycle</a></td></tr>
</table>
<br/>
<br/>
<span class="mainSubTitle">Maintenance</span>
<form id="refresh" action="${url.serviceContext}${url.match}" method="post">
<input type="hidden" name="reset" value="on"/>
<table>
<#if failures?size &gt; 0>
<tr><td><a href="${url.serviceContext}/index/failures">Browse failed Web Scripts</a></td></tr>
</#if>
<tr><td><a href="${url.serviceContext}/api/javascript/debugger">Alfresco Javascript Debugger</a></td></tr>
</table>
<br/>
<table>
<tr><td><input type="submit" name="submit" value="Refresh Web Scripts"/></td></tr>
</table>
</form>
</div>
<#assign CSRF=(config.scoped["CSRFPolicy"]["filter"].getChildren("rule")?size != 0)!false>
<#if CSRF>
<script type="text/javascript">
function addCsrfTokenToRefreshForm() {
const properties = {};
<#if config.scoped["CSRFPolicy"]["properties"]??>
<#assign csrfProperties = (config.scoped["CSRFPolicy"]["properties"].children)![]>
<#list csrfProperties as p>
properties["${p.name?js_string}"] = "${(p.value!"")?js_string}";
</#list>
</#if>
function substitute(str) {
for (const prop in properties) {
str = str.replace("{" + prop + "}", properties[prop]);
}
return str;
}
const csrfCookieName = substitute("${config.scoped["CSRFPolicy"]["client"].getChildValue("cookie")!""}");
const csrfParamName = substitute("${config.scoped["CSRFPolicy"]["client"].getChildValue("parameter")!""}");
const matchingCookies = document.cookie.match(new RegExp("(?:^|; )" + csrfCookieName + "=([^;]*)"));
if (matchingCookies) {
const csrfToken = decodeURIComponent(matchingCookies[1]).replace(/"/g, '');
const form = document.getElementById('refresh');
const originalAction = form.attributes.action.value;
form.attributes.action.value = originalAction + (originalAction.lastIndexOf('?') === -1 ? "?" : "&") + csrfParamName + "=" + encodeURIComponent(csrfToken);
}
}
window.addEventListener('load', addCsrfTokenToRefreshForm, false);
</script>
</#if>
</body>
</html>

View File

@@ -99,6 +99,7 @@ import org.junit.runners.Suite;
org.alfresco.repo.webdav.WebDAVMethodTest.class,
org.alfresco.repo.webdav.PutMethodTest.class,
org.alfresco.repo.webdav.WebDAVonContentUpdateTest.class,
org.alfresco.repo.webdav.WebDAVInsecurePostMethodTest.class,
// [classpath:test-rest-context.xml]
org.alfresco.rest.framework.tests.core.ExceptionResolverTests.class,

View File

@@ -0,0 +1,131 @@
/*
* #%L
* Alfresco Remote API
* %%
* 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.webdav;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Hashtable;
import org.alfresco.repo.webdav.WebDAVServlet.WebDAVInitParameters;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
/**
* Tests for the allowInsecurePOSTMethod flag.
*
* @see WebDAVInitParameters
* @author Aleksandra Onych
*/
@RunWith(MockitoJUnitRunner.class)
public class WebDAVInsecurePostMethodTest
{
private WebDAVServlet davServlet;
private @Mock WebDAVInitParameters webDAVInitParameters;
private @Mock HttpServletRequest request;
private @Mock HttpServletResponse response;
private @Mock Hashtable<String,Class<? extends WebDAVMethod>> davMethods;
@Before
public void setUp()
{
davServlet = new WebDAVServlet();
ReflectionTestUtils.setField(davServlet, "initParams", webDAVInitParameters);
ReflectionTestUtils.setField(davServlet, "m_davMethods", davMethods);
when(webDAVInitParameters.getEnabled()).thenReturn(true);
}
@Test
public void shouldReturn405StatusWhenPostMethodIsNotAllowed() throws ServletException, IOException
{
prepareRequest(WebDAV.METHOD_POST);
when(webDAVInitParameters.allowInsecurePOSTMethod()).thenReturn(false);
davServlet.service(request, response);
verify(response).sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}
@Test
public void shouldNotReturn405StatusWhenPostMethodIsAllowed() throws ServletException, IOException
{
prepareRequest(WebDAV.METHOD_POST);
when(webDAVInitParameters.allowInsecurePOSTMethod()).thenReturn(true);
davServlet.service(request, response);
verify(response, never()).sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}
@Test
public void shouldNotReturn405StatusForPutMethod() throws ServletException, IOException
{
prepareRequest(WebDAV.METHOD_PUT);
davServlet.service(request, response);
verify(response, never()).sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}
@Test
public void shouldNotReturn405StatusForGetMethod() throws ServletException, IOException
{
prepareRequest(WebDAV.METHOD_GET);
davServlet.service(request, response);
verify(response, never()).sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}
@Test
public void shouldNotReturn405StatusForDeleteMethod() throws ServletException, IOException
{
prepareRequest(WebDAV.METHOD_DELETE);
davServlet.service(request, response);
verify(response, never()).sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}
private void prepareRequest(String requestMethodName)
{
doReturn(PutMethod.class).when(davMethods).get(requestMethodName);
when(request.getMethod()).thenReturn(requestMethodName);
}
}

View File

@@ -0,0 +1,66 @@
/*
* #%L
* Alfresco Remote API
* %%
* 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.rest.api.actions;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import org.alfresco.rest.api.Actions;
import org.alfresco.rest.api.model.ActionParameterConstraint;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class ActionConstraintsEntityResourceTest
{
@Mock
private Actions actionsMock;
@Mock
private Parameters parametersMock;
@InjectMocks
private ActionConstraintsEntityResource objectUnderTest;
@Test
public void testReadById() {
final String name = "name";
final ActionParameterConstraint dummyConstraint = new ActionParameterConstraint();
given(actionsMock.getActionConstraint(name)).willReturn(dummyConstraint);
//when
ActionParameterConstraint result = objectUnderTest.readById(name, parametersMock);
then(actionsMock).should().getActionConstraint(name);
then(actionsMock).shouldHaveNoMoreInteractions();
assertThat(result).isNotNull().usingRecursiveComparison().isEqualTo(dummyConstraint);
}
}

View File

@@ -0,0 +1,66 @@
/*
* #%L
* Alfresco Remote API
* %%
* 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.rest.api.actions;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import org.alfresco.rest.api.Actions;
import org.alfresco.rest.api.model.ActionParameterConstraint;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class ActionParameterConstraintsEntityResourceTest
{
@Mock
private Actions actionsMock;
@Mock
private Parameters parametersMock;
@InjectMocks
private ActionParameterConstraintsEntityResource objectUnderTest;
@Test
public void testReadById() {
final String name = "name";
final ActionParameterConstraint dummyConstraint = new ActionParameterConstraint();
given(actionsMock.getActionConstraint(name)).willReturn(dummyConstraint);
//when
ActionParameterConstraint result = objectUnderTest.readById(name, parametersMock);
then(actionsMock).should().getActionConstraint(name);
then(actionsMock).shouldHaveNoMoreInteractions();
assertThat(result).isNotNull().usingRecursiveComparison().isEqualTo(dummyConstraint);
}
}

View File

@@ -0,0 +1,165 @@
/*
* #%L
* Alfresco Remote API
* %%
* 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.rest.api.impl;
import static org.alfresco.rest.api.impl.ActionsImpl.CONSTRAINT_NOT_EXISTS;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.mock;
import java.util.Map;
import org.alfresco.repo.action.constraint.FolderContentsParameterConstraint;
import org.alfresco.rest.api.impl.rules.ActionParameterConverter;
import org.alfresco.rest.api.model.ActionParameterConstraint;
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.action.ParameterConstraint;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class ActionsImplTest
{
private static final String NAME = "name";
private static final String CONSTRAINT = "constraint";
private static final String LABEL = "label";
private static final String DISPLAY = "display ";
@Mock
private ActionService actionServiceMock;
@Mock
private Parameters parametersMock;
@Mock
private ActionParameterConverter parameterConverterMock;
@InjectMocks
private ActionsImpl objectUnderTest;
@Test
public void testGetSingleActionConstraint()
{
final String name = "name";
final String value = CONSTRAINT;
final String label = LABEL;
final Map<String, String> values = Map.of(value, label);
final ParameterConstraint testConstraint = createTestConstraint(name, values);
given(actionServiceMock.getParameterConstraint(name)).willReturn(testConstraint);
//when
final ActionParameterConstraint actualConstraint = objectUnderTest.getActionConstraint(name);
then(parametersMock).shouldHaveNoInteractions();
then(actionServiceMock).should().getParameterConstraint(name);
then(actionServiceMock).shouldHaveNoMoreInteractions();
assertThat(actualConstraint).isNotNull();
assertThat(actualConstraint.getConstraintName()).isEqualTo(testConstraint.getName());
ActionParameterConstraint.ConstraintData expectedConstraintData = new ActionParameterConstraint.ConstraintData(value, label);
assertThat(actualConstraint.getConstraintValues()).isNotNull().hasSize(1);
ActionParameterConstraint.ConstraintData actualConstraintData = actualConstraint.getConstraintValues().get(0);
assertThat(actualConstraintData).usingRecursiveComparison().isEqualTo(expectedConstraintData);
}
@Test
public void testGetSingleActionNodeConstraint()
{
final String name = "name1";
final String dummyNodeId = "dummy-node-id";
final String value = "workspace://DummyStore/" + dummyNodeId;
final Map<String, String> values = Map.of(value, LABEL);
final FolderContentsParameterConstraint testConstraint = mock(FolderContentsParameterConstraint.class);
given(testConstraint.getName()).willReturn(name);
given(testConstraint.getValues()).willReturn(values);
given(actionServiceMock.getParameterConstraint(name)).willReturn(testConstraint);
given(parameterConverterMock.convertParamFromServiceModel(any())).willReturn(dummyNodeId);
//when
final ActionParameterConstraint actualConstraint = objectUnderTest.getActionConstraint(name);
then(parametersMock).shouldHaveNoInteractions();
then(actionServiceMock).should().getParameterConstraint(name);
then(actionServiceMock).shouldHaveNoMoreInteractions();
assertThat(actualConstraint).isNotNull();
assertThat(actualConstraint.getConstraintName()).isEqualTo(testConstraint.getName());
ActionParameterConstraint.ConstraintData expectedConstraintData = new ActionParameterConstraint.ConstraintData(dummyNodeId, LABEL);
assertThat(actualConstraint.getConstraintValues()).isNotNull().hasSize(1);
ActionParameterConstraint.ConstraintData actualConstraintData = actualConstraint.getConstraintValues().get(0);
assertThat(actualConstraintData).usingRecursiveComparison().isEqualTo(expectedConstraintData);
}
@Test
public void testGetActionConstraintsWithNameFilterNonExistingConstraint()
{
final String name = "name";
given(actionServiceMock.getParameterConstraint(name)).willReturn(null);
//when
assertThatExceptionOfType(NotFoundException.class).isThrownBy(() -> objectUnderTest.getActionConstraint(name))
.withMessageContaining(String.format(CONSTRAINT_NOT_EXISTS, name));
then(parametersMock).shouldHaveNoInteractions();
then(actionServiceMock).should().getParameterConstraint(name);
then(actionServiceMock).shouldHaveNoMoreInteractions();
}
private ParameterConstraint createTestConstraint(final String name, final Map<String, String> values)
{
return new ParameterConstraint()
{
@Override
public String getName()
{
return name;
}
@Override
public boolean isValidValue(String value)
{
return true;
}
@Override
public String getValueDisplayLabel(String value)
{
return DISPLAY + name;
}
@Override
public Map<String, String> getAllowableValues()
{
return values;
}
};
}
}

View File

@@ -26,6 +26,8 @@
package org.alfresco.rest.api.impl.mapper.rules;
import static java.util.Collections.emptyMap;
import static org.alfresco.repo.action.access.ActionAccessRestriction.ACTION_CONTEXT_PARAM_NAME;
import static org.alfresco.repo.action.executer.SetPropertyValueActionExecuter.PARAM_PROPERTY;
import static org.alfresco.repo.action.executer.SetPropertyValueActionExecuter.PARAM_VALUE;
@@ -41,11 +43,14 @@ import java.util.List;
import java.util.Map;
import org.alfresco.repo.action.ActionImpl;
import org.alfresco.rest.api.actions.ActionValidator;
import org.alfresco.rest.api.impl.rules.ActionParameterConverter;
import org.alfresco.rest.api.model.rules.Action;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
@@ -63,10 +68,17 @@ public class RestRuleActionModelMapperTest
@Mock
private ActionParameterConverter parameterConverter;
@Mock
private ActionValidator sampleValidatorMock;
@InjectMocks
private RestRuleActionModelMapper objectUnderTest;
@Before
public void setUp() {
objectUnderTest = new RestRuleActionModelMapper(parameterConverter, List.of(sampleValidatorMock));
given(sampleValidatorMock.isEnabled()).willReturn(true);
}
@Test
public void testToRestModel()
{
@@ -89,7 +101,7 @@ public class RestRuleActionModelMapperTest
public void testToRestModelWithNullValues()
{
final org.alfresco.service.cmr.action.Action actionServiceModel = new ActionImpl(null, null, null);
final Action expectedAction = Action.builder().params(Collections.emptyMap()).create();
final Action expectedAction = Action.builder().params(emptyMap()).create();
//when
final Action actualAction = objectUnderTest.toRestModel(actionServiceModel);
@@ -122,4 +134,16 @@ public class RestRuleActionModelMapperTest
assertThat(serviceModelAction).isNull();
}
@Test
public void testToServiceModelWithNullParams()
{
final Action action = Action.builder().actionDefinitionId(ACTION_DEFINITION_NAME).params(null).create();
final List<Action> actions = List.of(action);
//when
final org.alfresco.service.cmr.action.Action serviceModelAction = objectUnderTest.toServiceModel(actions);
then(parameterConverter).should().getConvertedParams(emptyMap(), ACTION_DEFINITION_NAME);
then(parameterConverter).shouldHaveNoMoreInteractions();
assertThat(serviceModelAction).isNotNull();
}
}

View File

@@ -634,12 +634,9 @@ public class RulesImplTest extends TestCase
public void testExecuteRule()
{
// when
final RuleExecution actualRuleExecution = rules.executeRules(FOLDER_NODE_ID, INCLUDE_SUB_FOLDERS, EXECUTE_INHERITED_RULES);
final RuleExecution actualRuleExecution = rules.executeRules(FOLDER_NODE_ID, INCLUDE_SUB_FOLDERS);
final RuleExecution expectedRuleExecution = RuleExecution.builder()
.eachSubFolderIncluded(INCLUDE_SUB_FOLDERS)
.eachInheritedRuleExecuted(EXECUTE_INHERITED_RULES)
.create();
final RuleExecution expectedRuleExecution = RuleExecution.builder().eachSubFolderIncluded(INCLUDE_SUB_FOLDERS).create();
final ActionImpl expectedAction = new ActionImpl(null, null, ExecuteAllRulesActionExecuter.NAME);
expectedAction.setNodeRef(FOLDER_NODE_REF);
expectedAction.setParameterValues(Map.of(

View File

@@ -0,0 +1,217 @@
/*
* #%L
* Alfresco Remote API
* %%
* 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.rest.api.impl.validator.actions;
import static org.alfresco.rest.api.impl.validator.actions.ActionParameterDefinitionValidator.MISSING_PARAMETER;
import static org.alfresco.rest.api.impl.validator.actions.ActionParameterDefinitionValidator.MUST_NOT_CONTAIN_PARAMETER;
import static org.alfresco.rest.api.impl.validator.actions.ActionParameterDefinitionValidator.PARAMS_SHOULD_NOT_BE_EMPTY;
import static org.alfresco.service.cmr.dictionary.DataTypeDefinition.BOOLEAN;
import static org.alfresco.service.cmr.dictionary.DataTypeDefinition.TEXT;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.BDDMockito.then;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.rest.api.Actions;
import org.alfresco.rest.api.model.ActionDefinition;
import org.alfresco.rest.api.model.rules.Action;
import org.alfresco.service.Experimental;
import org.alfresco.service.namespace.QName;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.BDDMockito;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@Experimental
@RunWith(MockitoJUnitRunner.class)
public class ActionParameterDefinitionValidatorTest
{
private static final String MANDATORY_PARAM_KEY = "paramKey";
private static final String NON_MANDATORY_PARAM_KEY = "nonMandatoryParamKey";
@Mock
private Actions actionsMock;
@InjectMocks
private ActionParameterDefinitionValidator objectUnderTest;
@Test
public void testSimpleValidationPasses()
{
final Action action = new Action();
final String actionDefinitionId = "properActionDefinition";
action.setActionDefinitionId(actionDefinitionId);
action.setParams(Map.of(MANDATORY_PARAM_KEY, "paramValue"));
final List<ActionDefinition.ParameterDefinition> parameterDefinitions =
List.of(createParameterDefinition(MANDATORY_PARAM_KEY, TEXT, true, null));
final ActionDefinition actionDefinition = createActionDefinition(actionDefinitionId, parameterDefinitions);
BDDMockito.given(actionsMock.getActionDefinitionById(actionDefinitionId)).willReturn(actionDefinition);
//when
objectUnderTest.validate(action);
then(actionsMock).should().getActionDefinitionById(actionDefinitionId);
then(actionsMock).shouldHaveNoMoreInteractions();
}
@Test
public void testValidationPassesWhenNoParametersNeeded()
{
final Action action = new Action();
final String actionDefinitionId = "properActionDefinition";
action.setActionDefinitionId(actionDefinitionId);
final ActionDefinition actionDefinition = createActionDefinition(actionDefinitionId, null);
BDDMockito.given(actionsMock.getActionDefinitionById(actionDefinitionId)).willReturn(actionDefinition);
//when
objectUnderTest.validate(action);
then(actionsMock).should().getActionDefinitionById(actionDefinitionId);
then(actionsMock).shouldHaveNoMoreInteractions();
}
@Test
public void testValidationPassesWhenNoMandatoryParameters()
{
final Action action = new Action();
final String actionDefinitionId = "properActionDefinition";
action.setActionDefinitionId(actionDefinitionId);
action.setParams(Map.of(MANDATORY_PARAM_KEY, "paramValue"));
final List<ActionDefinition.ParameterDefinition> parameterDefinitions =
List.of(createParameterDefinition(MANDATORY_PARAM_KEY, TEXT, true, null),
createParameterDefinition(NON_MANDATORY_PARAM_KEY, BOOLEAN, false, null));
final ActionDefinition actionDefinition = createActionDefinition(actionDefinitionId, parameterDefinitions);
BDDMockito.given(actionsMock.getActionDefinitionById(actionDefinitionId)).willReturn(actionDefinition);
//when
objectUnderTest.validate(action);
then(actionsMock).should().getActionDefinitionById(actionDefinitionId);
then(actionsMock).shouldHaveNoMoreInteractions();
}
@Test
public void testValidationFailsWhenTooManyParameters()
{
final Action action = new Action();
final String actionDefinitionId = "properActionDefinition";
action.setActionDefinitionId(actionDefinitionId);
action.setParams(Map.of(MANDATORY_PARAM_KEY, "paramValue", NON_MANDATORY_PARAM_KEY, false));
final List<ActionDefinition.ParameterDefinition> parameterDefinitions =
List.of(createParameterDefinition(MANDATORY_PARAM_KEY, TEXT, true, null));
final ActionDefinition actionDefinition = createActionDefinition(actionDefinitionId, parameterDefinitions);
BDDMockito.given(actionsMock.getActionDefinitionById(actionDefinitionId)).willReturn(actionDefinition);
//when
assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> objectUnderTest.validate(action))
.withMessageContaining(String.format(MUST_NOT_CONTAIN_PARAMETER, actionDefinitionId, NON_MANDATORY_PARAM_KEY));
then(actionsMock).should().getActionDefinitionById(actionDefinitionId);
then(actionsMock).shouldHaveNoMoreInteractions();
}
@Test
public void testValidationFailsWhenMissingParameters()
{
final Action action = new Action();
final String actionDefinitionId = "properActionDefinition";
action.setActionDefinitionId(actionDefinitionId);
final List<ActionDefinition.ParameterDefinition> parameterDefinitions =
List.of(createParameterDefinition(MANDATORY_PARAM_KEY, TEXT, true, null));
final ActionDefinition actionDefinition = createActionDefinition(actionDefinitionId, parameterDefinitions);
BDDMockito.given(actionsMock.getActionDefinitionById(actionDefinitionId)).willReturn(actionDefinition);
//when
assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> objectUnderTest.validate(action))
.withMessageContaining(String.format(PARAMS_SHOULD_NOT_BE_EMPTY, actionDefinitionId));
then(actionsMock).should().getActionDefinitionById(actionDefinitionId);
then(actionsMock).shouldHaveNoMoreInteractions();
}
@Test
public void testValidationFailsWhenMissingParameterValue()
{
final Action action = new Action();
final String actionDefinitionId = "properActionDefinition";
action.setActionDefinitionId(actionDefinitionId);
final Map<String, java.io.Serializable> params = new HashMap<>();
params.put(MANDATORY_PARAM_KEY, null);
action.setParams(params);
final List<ActionDefinition.ParameterDefinition> parameterDefinitions =
List.of(createParameterDefinition(MANDATORY_PARAM_KEY, TEXT, true, null));
final ActionDefinition actionDefinition = createActionDefinition(actionDefinitionId, parameterDefinitions);
BDDMockito.given(actionsMock.getActionDefinitionById(actionDefinitionId)).willReturn(actionDefinition);
//when
assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> objectUnderTest.validate(action))
.withMessageContaining(String.format(MISSING_PARAMETER, MANDATORY_PARAM_KEY));
then(actionsMock).should().getActionDefinitionById(actionDefinitionId);
then(actionsMock).shouldHaveNoMoreInteractions();
}
@Test
public void testValidationFailsWhenMandatoryParameterIsMissing()
{
final Action action = new Action();
final String actionDefinitionId = "properActionDefinition";
action.setActionDefinitionId(actionDefinitionId);
action.setParams(Map.of(NON_MANDATORY_PARAM_KEY, true));
final List<ActionDefinition.ParameterDefinition> parameterDefinitions =
List.of(createParameterDefinition(MANDATORY_PARAM_KEY, TEXT, true, null),
createParameterDefinition(NON_MANDATORY_PARAM_KEY, BOOLEAN, false, null));
final ActionDefinition actionDefinition = createActionDefinition(actionDefinitionId, parameterDefinitions);
BDDMockito.given(actionsMock.getActionDefinitionById(actionDefinitionId)).willReturn(actionDefinition);
//when
assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> objectUnderTest.validate(action))
.withMessageContaining(String.format(MISSING_PARAMETER, MANDATORY_PARAM_KEY));
then(actionsMock).should().getActionDefinitionById(actionDefinitionId);
then(actionsMock).shouldHaveNoMoreInteractions();
}
private ActionDefinition createActionDefinition(final String actionDefinitionId,
List<ActionDefinition.ParameterDefinition> parameterDefinitions)
{
return new ActionDefinition(actionDefinitionId, actionDefinitionId, "title", "description", Collections.emptyList(), false, false,
parameterDefinitions);
}
private ActionDefinition.ParameterDefinition createParameterDefinition(final String name, final QName qName, final boolean mandatory,
final String constraint)
{
return new ActionDefinition.ParameterDefinition(name, qName.toPrefixString(), false, mandatory, "label", constraint);
}
}

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>17.152</version>
<version>17.162</version>
</parent>
<dependencies>

View File

@@ -1,34 +1,34 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 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%
*/
/*
* #%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.constraint;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
@@ -55,19 +55,22 @@ public class AspectParameterConstraint extends BaseParameterConstraint
* @see org.alfresco.service.cmr.action.ParameterConstraint#getAllowableValues()
*/
protected Map<String, String> getAllowableValuesImpl()
{
Collection<QName> aspects = dictionaryService.getAllAspects();
Map<String, String> result = new LinkedHashMap<String, String>(aspects.size());
for (QName aspect : aspects)
{
AspectDefinition aspectDef = dictionaryService.getAspect(aspect);
if (aspectDef != null && aspectDef.getTitle(dictionaryService) != null)
{
result.put(aspect.toPrefixString(), aspectDef.getTitle(dictionaryService));
}
}
return result;
}
{
final Map<String, String> values = getValues();
values.values().removeIf(Objects::isNull);
return values;
}
@Override
public Map<String, String> getValues()
{
return dictionaryService.getAllAspects().stream()
.collect(LinkedHashMap::new, (m, v) -> m.put(v.toPrefixString(), getTitle(v)), LinkedHashMap::putAll);
}
private String getTitle(QName aspect)
{
final AspectDefinition aspectDef = dictionaryService.getAspect(aspect);
return aspectDef != null ? aspectDef.getTitle(dictionaryService) : null;
}
}

View File

@@ -1,34 +1,34 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 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%
*/
/*
* #%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.constraint;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
@@ -55,17 +55,22 @@ public class PropertyParameterConstraint extends BaseParameterConstraint
* @see org.alfresco.service.cmr.action.ParameterConstraint#getAllowableValues()
*/
protected Map<String, String> getAllowableValuesImpl()
{
Collection<QName> properties = dictionaryService.getAllProperties(null);
Map<String, String> result = new LinkedHashMap<String, String>(properties.size());
for (QName property : properties)
{
PropertyDefinition propertyDef = dictionaryService.getProperty(property);
if (propertyDef != null && propertyDef.getTitle(dictionaryService) != null)
{
result.put(property.toPrefixString(), propertyDef.getTitle(dictionaryService));
}
}
return result;
}
{
final Map<String, String> values = getValues();
values.values().removeIf(Objects::isNull);
return values;
}
@Override
public Map<String, String> getValues()
{
return dictionaryService.getAllProperties(null).stream()
.collect(LinkedHashMap::new, (m, v) -> m.put(v.toPrefixString(), getTitle(v)), LinkedHashMap::putAll);
}
private String getTitle(QName property)
{
final PropertyDefinition propertyDef = dictionaryService.getProperty(property);
return propertyDef != null ? propertyDef.getTitle(dictionaryService) : null;
}
}

View File

@@ -1,34 +1,35 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 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%
*/
/*
* #%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.constraint;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
@@ -55,17 +56,22 @@ public class TypeParameterConstraint extends BaseParameterConstraint
* @see org.alfresco.service.cmr.action.ParameterConstraint#getAllowableValues()
*/
protected Map<String, String> getAllowableValuesImpl()
{
Collection<QName> types = dictionaryService.getAllTypes();
Map<String, String> result = new LinkedHashMap<String, String>(types.size());
for (QName type : types)
{
TypeDefinition typeDef = dictionaryService.getType(type);
if (typeDef != null && typeDef.getTitle(dictionaryService) != null)
{
result.put(type.toPrefixString(), typeDef.getTitle(dictionaryService));
}
}
return result;
}
{
final Map<String, String> values = getValues();
values.values().removeIf(Objects::isNull);
return values;
}
@Override
public Map<String, String> getValues()
{
return dictionaryService.getAllTypes().stream()
.collect(LinkedHashMap::new, (m, v) -> m.put(v.toPrefixString(), getTitle(v)), LinkedHashMap::putAll);
}
private String getTitle(QName type)
{
final TypeDefinition typeDef = dictionaryService.getType(type);
return typeDef != null ? typeDef.getTitle(dictionaryService) : null;
}
}

View File

@@ -1,28 +1,28 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 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%
*/
/*
* #%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.service.cmr.action;
@@ -63,4 +63,12 @@ public interface ParameterConstraint
* The implementers are expected to return allowed values in the insertion order.
*/
Map<String, String> getAllowableValues();
/**
* Returns possible constraint values.
* By default returns getAllowableValues() to be backwards compatible.
*/
default Map<String, String> getValues() {
return getAllowableValues();
}
}

View File

@@ -53,6 +53,7 @@ system.webdav.servlet.enabled=true
system.webdav.url.path.prefix=
system.webdav.storeName=${protocols.storeName}
system.webdav.rootPath=${protocols.rootPath}
system.webdav.allowInsecurePOSTMethod=false
# File name patterns that trigger rename shuffle detection
# pattern is used by move - tested against full path after it has been lower cased.
system.webdav.renameShufflePattern=(.*/\\..*)|(.*[a-f0-9]{8}+$)|(.*\\.tmp$)|(.*atmp[0-9]+$)|(.*\\.wbk$)|(.*\\.bak$)|(.*\\~$)|(.*backup.*\\.do[ct]{1}[x]?[m]?$)|(.*\\.sb\\-\\w{8}\\-\\w{6}$)