diff --git a/config/alfresco/public-rest-context.xml b/config/alfresco/public-rest-context.xml
index 09c096ca83..cfb4536abc 100644
--- a/config/alfresco/public-rest-context.xml
+++ b/config/alfresco/public-rest-context.xml
@@ -142,6 +142,7 @@
+
@@ -781,26 +782,20 @@
-
-
-
-
-
-
+
+
-
-
-
-
+
-
-
-
-
+
+
+
+
+
@@ -1201,4 +1196,90 @@
+
+
+
+
+
+
+ org.alfresco.service.cmr.repository.NodeService
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.alfresco.service.cmr.repository.NodeService.getStores=ACL_ALLOW,AFTER_ACL_NODE.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.createStore=ACL_METHOD.ROLE_ADMINISTRATOR
+ org.alfresco.service.cmr.repository.NodeService.exists=ACL_ALLOW
+ org.alfresco.service.cmr.repository.NodeService.getNodeStatus=ACL_NODE.0.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.getNodeRef=AFTER_ACL_NODE.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.getAllRootNodes=ACL_NODE.0.sys:base.ReadProperties,AFTER_ACL_NODE.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.getRootNode=ACL_NODE.0.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.createNode=ACL_NODE.0.sys:base.CreateChildren
+ org.alfresco.service.cmr.repository.NodeService.moveNode=ACL_NODE.0.sys:base.DeleteNode,ACL_NODE.1.sys:base.CreateChildren
+ org.alfresco.service.cmr.repository.NodeService.setChildAssociationIndex=ACL_PARENT.0.sys:base.WriteProperties
+ org.alfresco.service.cmr.repository.NodeService.getType=ACL_ALLOW
+ org.alfresco.service.cmr.repository.NodeService.setType=ACL_NODE.0.sys:base.WriteProperties
+ org.alfresco.service.cmr.repository.NodeService.addAspect=ACL_NODE.0.sys:base.WriteProperties,ACL_ITEM.0.cm:ownable.TakeOwnership
+ org.alfresco.service.cmr.repository.NodeService.removeAspect=ACL_NODE.0.sys:base.WriteProperties
+ org.alfresco.service.cmr.repository.NodeService.hasAspect=ACL_NODE.0.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.getAspects=ACL_NODE.0.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.deleteNode=ACL_NODE.0.sys:base.DeleteNode
+ org.alfresco.service.cmr.repository.NodeService.addChild=ACL_NODE.0.sys:base.CreateChildren,ACL_NODE.1.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.removeChild=ACL_NODE.0.sys:base.DeleteChildren,ACL_PRI_CHILD_ASSOC_ON_CHILD.0.1.sys:base.DeleteNode
+ org.alfresco.service.cmr.repository.NodeService.removeChildAssociation=ACL_PARENT.0.sys:base.DeleteChildren,ACL_PRI_CHILD_ASSOC_ON_CHILD.0.sys:base.DeleteNode
+ org.alfresco.service.cmr.repository.NodeService.removeSeconaryChildAssociation=ACL_PARENT.0.sys:base.DeleteChildren
+ org.alfresco.service.cmr.repository.NodeService.removeSecondaryChildAssociation=ACL_PARENT.0.sys:base.DeleteChildren
+ org.alfresco.service.cmr.repository.NodeService.getProperties=ACL_NODE.0.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.getProperty=ACL_NODE.0.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.setProperties=ACL_NODE.0.sys:base.WriteProperties,ACL_ITEM.0.cm:ownable.TakeOwnership
+ org.alfresco.service.cmr.repository.NodeService.addProperties=ACL_NODE.0.sys:base.WriteProperties,ACL_ITEM.0.cm:ownable.TakeOwnership
+ org.alfresco.service.cmr.repository.NodeService.setProperty=ACL_NODE.0.sys:base.WriteProperties,ACL_ITEM.0.cm:ownable.TakeOwnership
+ org.alfresco.service.cmr.repository.NodeService.removeProperty=ACL_NODE.0.sys:base.WriteProperties
+ org.alfresco.service.cmr.repository.NodeService.getParentAssocs=ACL_NODE.0.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.getChildAssocs=ACL_NODE.0.sys:base.ReadChildren,AFTER_ACL_NODE.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.getChildByName=ACL_NODE.0.sys:base.ReadChildren,AFTER_ACL_NODE.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.getChildAssocsByPropertyValue=ACL_NODE.0.sys:base.ReadChildren,AFTER_ACL_NODE.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.getChildrenByName=ACL_NODE.0.sys:base.ReadChildren,AFTER_ACL_NODE.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.getPrimaryParent=ACL_NODE.0.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.createAssociation=ACL_NODE.0.sys:base.WriteProperties,ACL_NODE.1.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.removeAssociation=ACL_NODE.0.sys:base.DeleteNode,ACL_NODE.1.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.setAssociations=ACL_NODE.0.sys:base.WriteProperties,ACL_NODE.2.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.getTargetAssocs=ACL_NODE.0.sys:base.ReadProperties,AFTER_ACL_NODE.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.getSourceAssocs=ACL_NODE.0.sys:base.ReadProperties,AFTER_ACL_PARENT.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.getAssoc=ACL_ALLOW,AFTER_ACL_NODE.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.getPath=ACL_NODE.0.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.getPaths=ACL_NODE.0.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.getStoreArchiveNode=ACL_NODE.0.sys:base.Read
+ org.alfresco.service.cmr.repository.NodeService.restoreNode=ACL_NODE.0.sys:base.DeleteNode,ACL_NODE.1.sys:base.CreateChildren
+ org.alfresco.service.cmr.repository.NodeService.getChildAssocsWithoutParentAssocsOfType=ACL_NODE.0.sys:base.ReadProperties,AFTER_ACL_NODE.sys:base.ReadProperties
+ org.alfresco.service.cmr.repository.NodeService.countChildAssocs=ACL_NODE.0.sys:base.ReadChildren
+ org.alfresco.service.cmr.repository.NodeService.*=ACL_DENY
+
+
+
+
diff --git a/source/java/org/alfresco/rest/api/nodes/AbstractNodeRelation.java b/source/java/org/alfresco/rest/api/nodes/AbstractNodeRelation.java
index a54247ed39..9a4571b18a 100644
--- a/source/java/org/alfresco/rest/api/nodes/AbstractNodeRelation.java
+++ b/source/java/org/alfresco/rest/api/nodes/AbstractNodeRelation.java
@@ -82,13 +82,19 @@ public class AbstractNodeRelation implements InitializingBean
this.sr = sr;
}
+ // Introduces permissions for Node Assoc (see public-rest-context.xml)
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
@Override
public void afterPropertiesSet()
{
PropertyCheck.mandatory(this, "serviceRegistry", sr);
ParameterCheck.mandatory("nodes", this.nodes);
- this.nodeService = sr.getNodeService();
+ //this.nodeService = sr.getNodeService();
this.namespaceService = sr.getNamespaceService();
this.dictionaryService = sr.getDictionaryService();
}
diff --git a/source/test-java/org/alfresco/rest/api/tests/NodeAssociationsApiTest.java b/source/test-java/org/alfresco/rest/api/tests/NodeAssociationsApiTest.java
index 9ec6c2e45d..f7626957eb 100644
--- a/source/test-java/org/alfresco/rest/api/tests/NodeAssociationsApiTest.java
+++ b/source/test-java/org/alfresco/rest/api/tests/NodeAssociationsApiTest.java
@@ -18,17 +18,26 @@
*/
package org.alfresco.rest.api.tests;
+import org.alfresco.repo.node.archive.NodeArchiveService;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.model.AssocChild;
import org.alfresco.rest.api.model.AssocTarget;
+import org.alfresco.rest.api.nodes.NodesEntityResource;
import org.alfresco.rest.api.tests.client.HttpResponse;
import org.alfresco.rest.api.tests.client.PublicApiClient.Paging;
+import org.alfresco.rest.api.tests.client.RequestContext;
import org.alfresco.rest.api.tests.client.data.Association;
import org.alfresco.rest.api.tests.client.data.Node;
+import org.alfresco.rest.api.tests.util.JacksonUtil;
import org.alfresco.rest.api.tests.util.RestApiUtil;
+import org.alfresco.rest.framework.jacksonextensions.JacksonHelper;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.security.MutableAuthenticationService;
+import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.security.PersonService;
import org.junit.After;
import org.junit.Before;
@@ -97,14 +106,17 @@ public class NodeAssociationsApiTest extends AbstractBaseApiTest
private List users = new ArrayList<>();
protected MutableAuthenticationService authenticationService;
+ protected PermissionService permissionService;
protected PersonService personService;
private final String RUNID = System.currentTimeMillis()+"";
+
@Before
public void setup() throws Exception
{
authenticationService = applicationContext.getBean("authenticationService", MutableAuthenticationService.class);
+ permissionService = applicationContext.getBean("permissionService", PermissionService.class);
personService = applicationContext.getBean("personService", PersonService.class);
// note: createUser currently relies on repoService
@@ -447,6 +459,140 @@ public class NodeAssociationsApiTest extends AbstractBaseApiTest
}
}
+ @Test
+ public void testNodePeerAssocsPermissions() throws Exception
+ {
+ // as user 1
+
+ String sharedFolderNodeId = getSharedNodeId(user1);
+ String sfId = createFolder(user1, sharedFolderNodeId, "shared folder "+RUNID).getId();
+
+ String u1myNodeId = getMyNodeId(user1);
+ String u1f1Id = createFolder(user1, u1myNodeId, "f1").getId();
+
+ // create content node
+ Node n = new Node();
+ n.setName("o1");
+ n.setNodeType(TYPE_CM_CONTENT);
+ n.setAspectNames(Arrays.asList(ASPECT_CM_REFERENCING, ASPECT_CM_PARTABLE));
+ HttpResponse response = post(getNodeChildrenUrl(u1f1Id), user1, toJsonAsStringNonNull(n), 201);
+ String u1o1Id = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Node.class).getId();
+
+ // as user 2
+
+ String u2myNodeId = getMyNodeId(user2);
+ String u2f1Id = createFolder(user2, u2myNodeId, "f1").getId();
+
+ // create content node
+ n = new Node();
+ n.setName("o1");
+ n.setNodeType(TYPE_CM_CONTENT);
+ n.setAspectNames(Arrays.asList(ASPECT_CM_REFERENCING, ASPECT_CM_PARTABLE));
+ response = post(getNodeChildrenUrl(u2f1Id), user2, toJsonAsStringNonNull(n), 201);
+ String u2o1Id = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Node.class).getId();
+
+ try
+ {
+ Paging paging = getPaging(0, 100);
+
+ // empty lists - before
+
+ response = getAll(getNodeTargetsUrl(u1f1Id), user1, paging, null, 200);
+ List nodes = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Node.class);
+ assertEquals(0, nodes.size());
+
+ response = getAll(getNodeTargetsUrl(u2f1Id), user2, paging, null, 200);
+ nodes = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Node.class);
+ assertEquals(0, nodes.size());
+
+ // Create some assocs
+
+ AssocTarget tgt = new AssocTarget(u1o1Id, ASSOC_TYPE_CM_REFERENCES);
+ post(getNodeTargetsUrl(u1f1Id), user1, toJsonAsStringNonNull(tgt), 201);
+
+ tgt = new AssocTarget(u2o1Id, ASSOC_TYPE_CM_REFERENCES);
+ post(getNodeTargetsUrl(u2f1Id), user2, toJsonAsStringNonNull(tgt), 201);
+
+ response = getAll(getNodeTargetsUrl(u1f1Id), user1, paging, null, 200);
+ nodes = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Node.class);
+ assertEquals(1, nodes.size());
+
+ response = getAll(getNodeTargetsUrl(u2f1Id), user2, paging, null, 200);
+ nodes = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Node.class);
+ assertEquals(1, nodes.size());
+
+ // -ve tests
+ {
+ // source/target not readable
+
+ // list
+ getAll(getNodeTargetsUrl(u1f1Id), user2, paging, null, 403);
+ getAll(getNodeSourcesUrl(u1o1Id), user2, paging, null, 403);
+
+ // create
+ tgt = new AssocTarget(u2o1Id, ASSOC_TYPE_CM_REFERENCES);
+ post(getNodeTargetsUrl(u1f1Id), user1, toJsonAsStringNonNull(tgt), 403);
+
+ tgt = new AssocTarget(u1o1Id, ASSOC_TYPE_CM_REFERENCES);
+ post(getNodeTargetsUrl(u2f1Id), user1, toJsonAsStringNonNull(tgt), 403);
+
+ // remove
+ delete(getNodeTargetsUrl(u1f1Id), user2, u2o1Id, null, 403);
+ delete(getNodeTargetsUrl(u2f1Id), user2, u1o1Id, null, 404);
+ }
+
+
+ // Test listing targets with permissions applied
+
+ // update permission
+ // TODO refactor with remote permission api calls (use v0 until we have v1 ?)
+ AuthenticationUtil.setFullyAuthenticatedUser(user1);
+ permissionService.setPermission(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, sfId), user2, PermissionService.EDITOR, true);
+
+ // TODO improve - admin-related tests
+ publicApiClient.setRequestContext(new RequestContext("-default-", "admin", "admin"));
+ response = publicApiClient.get(getScope(), "nodes/"+sfId+"/targets", null, null, null, createParams(paging, null));
+ checkStatus(200, response.getStatusCode());
+ nodes = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Node.class);
+ assertEquals(0, nodes.size());
+
+ // user 1
+ tgt = new AssocTarget(u1o1Id, ASSOC_TYPE_CM_REFERENCES);
+ post(getNodeTargetsUrl(sfId), user1, toJsonAsStringNonNull(tgt), 201);
+
+ // user 2
+ tgt = new AssocTarget(u2o1Id, ASSOC_TYPE_CM_REFERENCES);
+ post(getNodeTargetsUrl(sfId), user2, toJsonAsStringNonNull(tgt), 201);
+
+ // TODO improve - admin-related tests
+ publicApiClient.setRequestContext(new RequestContext("-default-", "admin", "admin"));
+ response = publicApiClient.get(getScope(), "nodes/"+sfId+"/targets", null, null, null, createParams(paging, null));
+ checkStatus(200, response.getStatusCode());
+ nodes = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Node.class);
+ assertEquals(2, nodes.size());
+
+ response = getAll(getNodeTargetsUrl(sfId), user1, paging, null, 200);
+ nodes = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Node.class);
+ assertEquals(1, nodes.size());
+ assertEquals(u1o1Id, nodes.get(0).getId());
+
+ response = getAll(getNodeTargetsUrl(sfId), user2, paging, null, 200);
+ nodes = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Node.class);
+ assertEquals(1, nodes.size());
+ assertEquals(u2o1Id, nodes.get(0).getId());
+
+ // TODO test listing sources with permissions applied
+ }
+ finally
+ {
+ // some cleanup
+ Map params = Collections.singletonMap("permanent", "true");
+ delete(URL_NODES, user1, u1f1Id, params, 204);
+ delete(URL_NODES, user2, u2f1Id, params, 204);
+ delete(URL_NODES, user1, sfId, params, 204);
+ }
+ }
+
/**
* Tests basic api to manage (add, list, remove) node secondary child associations (ie. parent node -> child node)
*