ACS-3214 Update rules. (#1254)

This commit is contained in:
Tom Page
2022-07-27 15:16:46 +01:00
committed by GitHub
parent 69b6fc4603
commit 13ee559a29
5 changed files with 268 additions and 6 deletions

View File

@@ -0,0 +1,197 @@
/*
* #%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.rest.rules;
import static org.alfresco.utility.constants.UserRole.SiteCollaborator;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.junit.Assert.fail;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.CREATED;
import static org.springframework.http.HttpStatus.FORBIDDEN;
import static org.springframework.http.HttpStatus.NOT_FOUND;
import static org.springframework.http.HttpStatus.OK;
import org.alfresco.rest.RestTest;
import org.alfresco.rest.model.RestRuleModel;
import org.alfresco.rest.model.RestRuleSetModel;
import org.alfresco.utility.constants.UserRole;
import org.alfresco.utility.model.FolderModel;
import org.alfresco.utility.model.SiteModel;
import org.alfresco.utility.model.TestGroup;
import org.alfresco.utility.model.UserModel;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
* Tests for PUT /nodes/{nodeId}/rule-sets/{ruleSetId}/rules.
*/
@Test (groups = { TestGroup.RULES })
public class UpdateRulesTests extends RestTest
{
private UserModel user;
private SiteModel site;
private FolderModel ruleFolder;
@BeforeClass (alwaysRun = true)
public void dataPreparation()
{
user = dataUser.createRandomTestUser();
site = dataSite.usingUser(user).createPublicRandomSite();
ruleFolder = dataContent.usingUser(user).usingSite(site).createFolder();
}
/** Check we can update a rule. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void updateRule()
{
RestRuleModel rule = createRule("Rule name");
STEP("Try to update the rule.");
RestRuleModel updatedRuleModel = new RestRuleModel();
updatedRuleModel.setName("Updated rule name");
RestRuleModel updatedRule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.updateRule(rule.getId(), updatedRuleModel);
restClient.assertStatusCodeIs(OK);
updatedRule.assertThat().field("id").is(rule.getId())
.assertThat().field("name").is("Updated rule name");
}
/** Check we get a 404 if trying to update a rule in a folder that doesn't exist. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void updateRuleForNonExistentFolder()
{
RestRuleModel rule = createRule("Rule name");
STEP("Try to update a rule in a non-existent folder.");
FolderModel nonExistentFolder = FolderModel.getRandomFolderModel();
nonExistentFolder.setNodeRef("fake-id");
RestRuleModel updatedRuleModel = new RestRuleModel();
updatedRuleModel.setName("Updated rule name");
restClient.authenticateUser(user).withCoreAPI().usingNode(nonExistentFolder).usingDefaultRuleSet()
.updateRule(rule.getId(), updatedRuleModel);
restClient.assertLastError().statusCodeIs(NOT_FOUND)
.containsSummary("fake-id was not found");
}
/** Check we get a 404 if trying to update a rule in a rule set that doesn't exist. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void updateRuleForNonExistentRuleSet()
{
RestRuleModel rule = createRule("Rule name");
STEP("Try to update a rule in a non-existent rule set.");
RestRuleModel updatedRuleModel = new RestRuleModel();
updatedRuleModel.setName("Updated rule name");
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingRuleSet("fake-id")
.updateRule(rule.getId(), updatedRuleModel);
restClient.assertLastError().statusCodeIs(NOT_FOUND)
.containsSummary("fake-id was not found");
}
/** Check we get a 404 if trying to update a rule that doesn't exist. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void updateRuleForNonExistentRuleId()
{
STEP("Try to update a rule that doesn't exist.");
RestRuleModel updatedRuleModel = new RestRuleModel();
updatedRuleModel.setName("Updated rule name");
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.updateRule("fake-id", updatedRuleModel);
restClient.assertLastError().statusCodeIs(NOT_FOUND)
.containsSummary("fake-id was not found");
}
/** Check that a user without permission cannot update a rule. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void requirePermissionToUpdateRule()
{
STEP("Create a user and use them to create a private site containing a folder");
UserModel privateUser = dataUser.createRandomTestUser();
SiteModel privateSite = dataSite.usingUser(privateUser).createPrivateRandomSite();
FolderModel privateFolder = dataContent.usingUser(privateUser).usingSite(privateSite).createFolder();
STEP("Create a collaborator and check they don't have permission to create a rule");
UserModel collaborator = dataUser.createRandomTestUser();
dataUser.addUserToSite(collaborator, privateSite, SiteCollaborator);
RestRuleModel ruleModel = new RestRuleModel();
ruleModel.setName("ruleName");
restClient.authenticateUser(user).withCoreAPI().usingNode(privateFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
restClient.assertStatusCodeIs(FORBIDDEN);
restClient.assertLastError().containsSummary("Insufficient permissions to manage rules");
}
/** Check we get an error trying to update a rule to have no name. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void updateRuleToHaveEmptyName()
{
RestRuleModel rule = createRule("Rule name");
STEP("Try to update the rule to have no name.");
RestRuleModel updatedRuleModel = new RestRuleModel();
updatedRuleModel.setName("");
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet().updateRule(rule.getId(), updatedRuleModel);
restClient.assertLastError().statusCodeIs(BAD_REQUEST)
.containsSummary("Rule name is a mandatory parameter");
}
/** Check that updates to the rule's id are ignored. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void tryToUpdateRuleId()
{
RestRuleModel rule = createRule("Rule name");
STEP("Try to update the rule id and check it isn't changed.");
RestRuleModel updatedRuleModel = new RestRuleModel();
updatedRuleModel.setId("new-rule-id");
updatedRuleModel.setName("Rule name");
RestRuleModel updatedRule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.updateRule(rule.getId(), updatedRuleModel);
updatedRule.assertThat().field("id").is(rule.getId());
}
/**
* Create a rule.
*
* @param name The name for the rule.
* @return The created rule.
*/
private RestRuleModel createRule(String name)
{
STEP("Create a rule called " + name);
RestRuleModel ruleModel = new RestRuleModel();
ruleModel.setName(name);
return restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
}
}

View File

@@ -74,6 +74,17 @@ public interface Rules
*/
List<Rule> createRules(String folderNodeId, String ruleSetId, List<Rule> rule);
/**
* Update a rule.
*
* @param folderNodeId The id of a folder.
* @param ruleSetId The id of a rule set within the folder (or "_default_" to use the default rule set for the folder).
* @param ruleId The rule id.
* @param rule The new version of the rule.
* @return The newly updated rule.
*/
Rule updateRuleById(String folderNodeId, String ruleSetId, String ruleId, Rule rule);
/**
* Delete rule for rule's ID and check associations with folder node and rule set node
*

View File

@@ -30,6 +30,7 @@ import static org.alfresco.service.cmr.security.AccessStatus.ALLOWED;
import static org.alfresco.service.cmr.security.PermissionService.CHANGE_PERMISSIONS;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@@ -49,10 +50,13 @@ import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.rule.RuleService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.QName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Experimental
public class RulesImpl implements Rules
{
private static final Logger LOGGER = LoggerFactory.getLogger(RulesImpl.class);
private static final String RULE_SET_EXPECTED_TYPE_NAME = "rule set";
private Nodes nodes;
@@ -99,6 +103,18 @@ public class RulesImpl implements Rules
.collect(Collectors.toList());
}
@Override
public Rule updateRuleById(String folderNodeId, String ruleSetId, String ruleId, Rule rule)
{
LOGGER.debug("Updating rule in folder {}, rule set {}, rule {} to {}", folderNodeId, ruleSetId, ruleId, rule);
NodeRef folderNodeRef = validateFolderNode(folderNodeId, true);
NodeRef ruleSetNodeRef = validateRuleSetNode(ruleSetId, folderNodeRef);
validateRuleNode(ruleId, ruleSetNodeRef);
return Rule.from(ruleService.saveRule(folderNodeRef, rule.toServiceModel(nodes)));
}
@Override
public void deleteRuleById(String folderNodeId, String ruleSetId, String ruleId)
{

View File

@@ -47,8 +47,12 @@ import java.util.List;
*/
@Experimental
@RelationshipResource(name = "rules", entityResource = NodeRuleSetsRelation.class, title = "Folder node rules")
public class NodeRulesRelation implements RelationshipResourceAction.Read<Rule>, RelationshipResourceAction.ReadById<Rule>,
RelationshipResourceAction.Create<Rule>, RelationshipResourceAction.Delete, InitializingBean
public class NodeRulesRelation implements RelationshipResourceAction.Read<Rule>,
RelationshipResourceAction.ReadById<Rule>,
RelationshipResourceAction.Create<Rule>,
RelationshipResourceAction.Update<Rule>,
RelationshipResourceAction.Delete,
InitializingBean
{
private Rules rules;
@@ -107,6 +111,8 @@ public class NodeRulesRelation implements RelationshipResourceAction.Read<Rule>,
/**
* Create one or more rules inside a given folder and rule set.
* <p>
* POST /nodes/{folderNodeId}/rule-sets/{ruleSetId}/rules
*
* @param folderNodeId The folder in which to create the rule.
* @param ruleList The list of rules to create.
@@ -126,9 +132,28 @@ public class NodeRulesRelation implements RelationshipResourceAction.Read<Rule>,
return rules.createRules(folderNodeId, ruleSetId, ruleList);
}
public void setRules(Rules rules)
/**
* Update the specified folder rule.
* <p>
* PUT /nodes/{folderNodeId}/rule-sets/{ruleSetId}/rules/{ruleId}
*
* @param folderNodeId The id of the folder containing the rule.
* @param rule The updated rule.
* @param parameters List of parameters including the rule set id and rule id.
* @return The updated rule.
* @throws RelationshipResourceNotFoundException in case resource was not found
*/
@WebApiDescription (
title = "Update folder node rule",
description = "Update a single rule definition for given node's, rule set's and rule's IDs",
successStatus = HttpServletResponse.SC_OK
)
@Override
public Rule update(String folderNodeId, Rule rule, Parameters parameters)
{
this.rules = rules;
String ruleSetId = parameters.getRelationshipId();
String ruleId = parameters.getRelationship2Id();
return rules.updateRuleById(folderNodeId, ruleSetId, ruleId, rule);
}
/**
@@ -152,4 +177,9 @@ public class NodeRulesRelation implements RelationshipResourceAction.Read<Rule>,
final String ruleId = parameters.getRelationship2Id();
rules.deleteRuleById(folderNodeId, ruleSetId, ruleId);
}
public void setRules(Rules rules)
{
this.rules = rules;
}
}

View File

@@ -79,6 +79,7 @@ public class ResourceWebScriptPut extends AbstractResourceWebScript implements P
final Map<String, String> resourceVars = locator.parseTemplateVars(req.getServiceMatch().getTemplateVars());
final String entityId = resourceVars.get(ResourceLocator.ENTITY_ID);
final String relationshipId = resourceVars.get(ResourceLocator.RELATIONSHIP_ID);
final String relationship2Id = resourceVars.get(ResourceLocator.RELATIONSHIP2_ID);
final RecognizedParams params = getRecognizedParams(req);
final ResourceOperation operation = resourceMeta.getOperation(HttpMethod.PUT);
@@ -99,9 +100,16 @@ public class ResourceWebScriptPut extends AbstractResourceWebScript implements P
if (StringUtils.isBlank(relationshipId))
{
throw new UnsupportedResourceOperationException("PUT is executed against the instance URL");
} else
{
}
Object putRel = extractJsonContent(req, assistant.getJsonHelper(), resourceMeta.getObjectType(operation));
if (StringUtils.isNotBlank(relationship2Id))
{
ResourceWebScriptHelper.setUniqueId(putRel, relationship2Id);
return Params.valueOf(false, entityId, relationshipId, relationship2Id,
putRel, null, null, params, null, req);
}
else
{
ResourceWebScriptHelper.setUniqueId(putRel,relationshipId);
return Params.valueOf(entityId, params, putRel, req);
}