diff --git a/packaging/tests/tas-restapi/src/test/java/org/alfresco/rest/rules/GetRuleSetsTests.java b/packaging/tests/tas-restapi/src/test/java/org/alfresco/rest/rules/GetRuleSetsTests.java index 020951f8db..963ef1d060 100644 --- a/packaging/tests/tas-restapi/src/test/java/org/alfresco/rest/rules/GetRuleSetsTests.java +++ b/packaging/tests/tas-restapi/src/test/java/org/alfresco/rest/rules/GetRuleSetsTests.java @@ -354,7 +354,7 @@ public class GetRuleSetsTests extends RestTest RestRuleSetLinkModel ruleSetLink = new RestRuleSetLinkModel(); ruleSetLink.setId(ruleFolder.getNodeRef()); coreAPIForUser().usingNode(publicFolder).createRuleLink(ruleSetLink); - coreAPIForUser().usingNode(privateFolder).createRuleLink(ruleSetLink); + coreAPIForAdmin().usingNode(privateFolder).createRuleLink(ruleSetLink); STEP("Get the rule set and linkedToBy field"); RestRuleSetModel ruleSet = coreAPIForUser().usingNode(ruleFolder) diff --git a/remote-api/src/main/java/org/alfresco/rest/api/impl/rules/RuleSetLoader.java b/remote-api/src/main/java/org/alfresco/rest/api/impl/rules/RuleSetLoader.java index 6fd9e8f338..58d983ecc2 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/impl/rules/RuleSetLoader.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/impl/rules/RuleSetLoader.java @@ -30,7 +30,6 @@ import static org.alfresco.rest.api.model.rules.InclusionType.LINKED; import static org.alfresco.rest.api.model.rules.InclusionType.OWNED; import java.util.List; -import java.util.stream.Collectors; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.rest.api.model.rules.RuleSet; @@ -93,12 +92,7 @@ public class RuleSetLoader } if (includes.contains(LINKED_TO_BY)) { - List linkedToBy = nodeService.getParentAssocs(ruleSetNodeRef) - .stream() - .map(ChildAssociationRef::getParentRef) - .filter(folder -> !folder.equals(parentRef)) - .collect(Collectors.toList()); - ruleSet.setLinkedToBy(linkedToBy); + ruleSet.setLinkedToBy(loadLinkedToBy(ruleSetNodeRef)); } if (includes.contains(IS_INHERITED)) { @@ -113,6 +107,11 @@ public class RuleSetLoader return ruleService.getFoldersInheritingRuleSet(ruleSetNodeRef, MAX_INHERITED_BY_SIZE); } + private List loadLinkedToBy(NodeRef ruleSetNodeRef) + { + return ruleService.getFoldersLinkingToRuleSet(ruleSetNodeRef); + } + private boolean loadIsInherited(NodeRef ruleSetNodeRef) { return AuthenticationUtil.runAsSystem(() -> !ruleService.getFoldersInheritingRuleSet(ruleSetNodeRef, 1).isEmpty()); diff --git a/repository/src/main/java/org/alfresco/repo/rule/RuleServiceImpl.java b/repository/src/main/java/org/alfresco/repo/rule/RuleServiceImpl.java index db591fbbf7..b833e426c8 100644 --- a/repository/src/main/java/org/alfresco/repo/rule/RuleServiceImpl.java +++ b/repository/src/main/java/org/alfresco/repo/rule/RuleServiceImpl.java @@ -689,6 +689,20 @@ public class RuleServiceImpl return inheritors; } + /** {@inheritDoc} */ + @Override + @Experimental + public List getFoldersLinkingToRuleSet(NodeRef ruleSet) + { + NodeRef parentRef = nodeService.getPrimaryParent(ruleSet).getParentRef(); + return nodeService.getParentAssocs(ruleSet) + .stream() + .map(ChildAssociationRef::getParentRef) + .filter(folder -> !folder.equals(parentRef)) + .filter(folder -> permissionService.hasReadPermission(folder) == ALLOWED) + .collect(Collectors.toList()); + } + /** * Gets the inherited rules for a given node reference * diff --git a/repository/src/main/java/org/alfresco/service/cmr/rule/RuleService.java b/repository/src/main/java/org/alfresco/service/cmr/rule/RuleService.java index 3b03eb329b..330e731f03 100644 --- a/repository/src/main/java/org/alfresco/service/cmr/rule/RuleService.java +++ b/repository/src/main/java/org/alfresco/service/cmr/rule/RuleService.java @@ -232,13 +232,23 @@ public interface RuleService * * @param ruleSet The rule set node. * @param maxFoldersToReturn A limit on the number of folders to return (since otherwise this could traverse a very large proportion of - * the repository. - * @return The list of the specified + * the repository). + * @return The list of the inheriting folders. */ @Auditable (parameters = { "ruleSet", "maxFoldersToReturn" }) @Experimental List getFoldersInheritingRuleSet(NodeRef ruleSet, int maxFoldersToReturn); + /** + * Get a list of folders linking to the specified rule set. + * + * @param ruleSet The rule set node. + * @return The list linking folders. + */ + @Auditable (parameters = { "ruleSet" }) + @Experimental + List getFoldersLinkingToRuleSet(NodeRef ruleSet); + /** * Get the rule given its node reference * diff --git a/repository/src/test/java/org/alfresco/repo/rule/RuleServiceImplUnitTest.java b/repository/src/test/java/org/alfresco/repo/rule/RuleServiceImplUnitTest.java index 8c085abaea..939743efc1 100644 --- a/repository/src/test/java/org/alfresco/repo/rule/RuleServiceImplUnitTest.java +++ b/repository/src/test/java/org/alfresco/repo/rule/RuleServiceImplUnitTest.java @@ -714,4 +714,46 @@ public class RuleServiceImplUnitTest assertEquals("Unexpected list of inheriting folders.", List.of(child), actual); } + + /** Check that a linked folder can be retrieved from a rule set node. */ + @Test + public void testGetFoldersLinkingToRuleSet() + { + NodeRef ruleSetNode = new NodeRef("rule://set/"); + NodeRef owningFolder = new NodeRef("owning://folder/"); + ChildAssociationRef owningAssocMock = mock(ChildAssociationRef.class); + given(owningAssocMock.getParentRef()).willReturn(owningFolder); + given(nodeService.getPrimaryParent(ruleSetNode)).willReturn(owningAssocMock); + // Simulate a folder linking to the rule set. + NodeRef linkingFolder = new NodeRef("linking://folder/"); + ChildAssociationRef linkingAssocMock = mock(ChildAssociationRef.class); + given(linkingAssocMock.getParentRef()).willReturn(linkingFolder); + given(nodeService.getParentAssocs(ruleSetNode)).willReturn(List.of(owningAssocMock, linkingAssocMock)); + + List linkingFolders = ruleService.getFoldersLinkingToRuleSet(ruleSetNode); + + assertEquals("Unexpected list of linking folders.", List.of(linkingFolder), linkingFolders); + } + + /** Check that permissions affect which linked folders are returned to the user. */ + @Test + public void testGetFoldersLinkingToRuleSet_respectsPermissions() + { + NodeRef ruleSetNode = new NodeRef("rule://set/"); + NodeRef owningFolder = new NodeRef("owning://folder/"); + ChildAssociationRef owningAssocMock = mock(ChildAssociationRef.class); + given(owningAssocMock.getParentRef()).willReturn(owningFolder); + given(nodeService.getPrimaryParent(ruleSetNode)).willReturn(owningAssocMock); + // Simulate a folder linking to the rule set. + NodeRef linkingFolder = new NodeRef("linking://folder/"); + ChildAssociationRef linkingAssocMock = mock(ChildAssociationRef.class); + given(linkingAssocMock.getParentRef()).willReturn(linkingFolder); + given(nodeService.getParentAssocs(ruleSetNode)).willReturn(List.of(owningAssocMock, linkingAssocMock)); + // The currect user does not have permission to view the folder. + given(permissionService.hasReadPermission(linkingFolder)).willReturn(DENIED); + + List linkingFolders = ruleService.getFoldersLinkingToRuleSet(ruleSetNode); + + assertEquals("Unexpected list of linking folders.", emptyList(), linkingFolders); + } }