From 080cfe1102722af04942c24b560767e142a28d70 Mon Sep 17 00:00:00 2001 From: Alan Davis Date: Fri, 24 Jun 2016 15:37:13 +0000 Subject: [PATCH] Merged 5.1.N (5.1.2) to 5.2.N (5.2.1) 128318 jvonka: MNT-16446: Edit Comment permission (part 1) - for v0 api so far (as per specifically described test case) ... more to follow ! git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.2.N/root@128334 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../repository/comments/comment.put.json.js | 10 + .../web/scripts/comment/CommentsApiTest.java | 396 ++++++++++++------ 2 files changed, 284 insertions(+), 122 deletions(-) diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/comments/comment.put.json.js b/config/alfresco/templates/webscripts/org/alfresco/repository/comments/comment.put.json.js index aaf57c1ff0..2861250cdb 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/repository/comments/comment.put.json.js +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/comments/comment.put.json.js @@ -28,6 +28,16 @@ function main() { return; } + + // MNT-16446 (pending future ACE-5437) + // TODO: commentedOn node is locked or pwc + var commentData = getCommentData(node); + var canEdit = commentData.canEditComment; + if (! canEdit) + { + status.setCode(status.STATUS_FORBIDDEN, "Cannot edit comment"); + return null; + } // update comment updateComment(node); diff --git a/source/test-java/org/alfresco/repo/web/scripts/comment/CommentsApiTest.java b/source/test-java/org/alfresco/repo/web/scripts/comment/CommentsApiTest.java index 185edbc1bb..61c79ef9c6 100644 --- a/source/test-java/org/alfresco/repo/web/scripts/comment/CommentsApiTest.java +++ b/source/test-java/org/alfresco/repo/web/scripts/comment/CommentsApiTest.java @@ -1,28 +1,28 @@ -/* - * #%L - * Alfresco Remote API - * %% - * 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 . - * #L% - */ +/* + * #%L + * Alfresco Remote API + * %% + * 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 . + * #L% + */ package org.alfresco.repo.web.scripts.comment; import java.io.IOException; @@ -34,10 +34,10 @@ import javax.transaction.UserTransaction; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; -import org.alfresco.repo.activities.feed.FeedGenerator; -import org.alfresco.repo.activities.post.lookup.PostLookup; +import org.alfresco.repo.activities.feed.FeedGenerator; +import org.alfresco.repo.activities.post.lookup.PostLookup; import org.alfresco.repo.content.MimetypeMap; -import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory; +import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory; import org.alfresco.repo.node.archive.NodeArchiveService; import org.alfresco.repo.security.authentication.AuthenticationComponent; import org.alfresco.repo.security.authentication.AuthenticationUtil; @@ -47,7 +47,7 @@ import org.alfresco.repo.security.permissions.impl.ModelDAO; import org.alfresco.repo.security.permissions.impl.SimplePermissionEntry; import org.alfresco.repo.site.SiteModel; import org.alfresco.repo.web.scripts.BaseWebScriptTest; -import org.alfresco.service.cmr.activities.ActivityService; +import org.alfresco.service.cmr.activities.ActivityService; import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; @@ -72,20 +72,28 @@ import org.springframework.context.ApplicationContext; import org.springframework.extensions.webscripts.Status; import org.springframework.extensions.webscripts.TestWebScriptServer.DeleteRequest; import org.springframework.extensions.webscripts.TestWebScriptServer.PostRequest; +import org.springframework.extensions.webscripts.TestWebScriptServer.PutRequest; import org.springframework.extensions.webscripts.TestWebScriptServer.Response; import org.springframework.extensions.webscripts.WebScriptException; /** * TODO: Fix the loose transaction handling. + * TODO: Rationalise with other v0 Comment REST API tests (eg. see BlogServiceTest ... etc). See also ACE-5437. */ public class CommentsApiTest extends BaseWebScriptTest { + // V0 Comments REST API private static final String URL_POST_COMMENT = "api/node/{0}/{1}/{2}/comments"; private static final String URL_DELETE_COMMENT = "api/comment/node/{0}/{1}/{2}?site={3}&itemtitle={4}&page={5}&pageParams={6}"; + private static final String URL_PUT_COMMENT = "api/comment/node/{0}/{1}/{2}"; + private static final String JSON = "application/json"; - private static final String SITE_SHORT_NAME = "SomeTestSiteShortName"; + private static final String SITE_SHORT_NAME = "SomeTestSiteShortName-"+System.currentTimeMillis(); + private static final String USER_ONE = "SomeTestUserOne"; private static final String USER_TWO = "SomeTestUserTwo"; + private static final String USER_THREE = "SomeTestUserThree"; + private static final String USER_FOUR = "SomeTestUserFour"; private static final String JSON_KEY_NODEREF = "nodeRef"; private static final String JSON_KEY_ITEM = "item"; @@ -103,16 +111,19 @@ public class CommentsApiTest extends BaseWebScriptTest private AuthenticationComponent authenticationComponent; protected PermissionServiceSPI permissionService; protected ModelDAO permissionModelDAO; - private ActivityService activityService; - private FeedGenerator feedGenerator; - private PostLookup postLookup; - + private ActivityService activityService; + private FeedGenerator feedGenerator; + private PostLookup postLookup; + private NodeRef rootNodeRef; - private NodeRef companyHomeNodeRef; + private NodeRef companyHomeNodeRef; + private NodeRef sharedHomeNodeRef; private NodeRef nodeRef; private NodeRef sitePage; - + private static final String USER_TEST = "UserTest"; + + private static final String DOCLIB_CONTAINER = "documentLibrary"; private UserTransaction txn; @@ -140,26 +151,35 @@ public class CommentsApiTest extends BaseWebScriptTest siteService = (SiteService)getServer().getApplicationContext().getBean("SiteService"); personService = (PersonService)getServer().getApplicationContext().getBean("PersonService"); nodeArchiveService = (NodeArchiveService)getServer().getApplicationContext().getBean("nodeArchiveService"); - activityService = (ActivityService)getServer().getApplicationContext().getBean("activityService"); - ChildApplicationContextFactory activitiesFeed = (ChildApplicationContextFactory)getServer().getApplicationContext().getBean("ActivitiesFeed"); - ApplicationContext activitiesFeedCtx = activitiesFeed.getApplicationContext(); - feedGenerator = (FeedGenerator)activitiesFeedCtx.getBean("feedGenerator"); - postLookup = (PostLookup)activitiesFeedCtx.getBean("postLookup"); + activityService = (ActivityService)getServer().getApplicationContext().getBean("activityService"); + ChildApplicationContextFactory activitiesFeed = (ChildApplicationContextFactory)getServer().getApplicationContext().getBean("ActivitiesFeed"); + ApplicationContext activitiesFeedCtx = activitiesFeed.getApplicationContext(); + feedGenerator = (FeedGenerator)activitiesFeedCtx.getBean("feedGenerator"); + postLookup = (PostLookup)activitiesFeedCtx.getBean("postLookup"); AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); txn = transactionService.getUserTransaction(); txn.begin(); + // Get Company Home rootNodeRef = nodeService.getRootNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE); List results = searchService.selectNodes(rootNodeRef, "/app:company_home", null, namespaceService, false); if (results.size() == 0) { throw new AlfrescoRuntimeException("Can't find /app:company_home"); } - companyHomeNodeRef = results.get(0); + // Get Shared + results = searchService.selectNodes(rootNodeRef, "/app:company_home/app:shared", null, namespaceService, false); + if (results.size() == 0) + { + throw new AlfrescoRuntimeException("Can't find /app:company_home/app:shared"); + } + + sharedHomeNodeRef = results.get(0); + results = searchService.selectNodes(rootNodeRef, "/app:company_home/cm:Commenty", null, namespaceService, false); if (results.size() > 0) { @@ -189,13 +209,23 @@ public class CommentsApiTest extends BaseWebScriptTest siteInfo = siteService.createSite("SomeTestSite", SITE_SHORT_NAME, "SiteTitle", "SiteDescription", SiteVisibility.PUBLIC); } + NodeRef docLibContainer = siteService.getContainer(SITE_SHORT_NAME, DOCLIB_CONTAINER); + if (docLibContainer == null) + { + siteService.createContainer(SITE_SHORT_NAME, DOCLIB_CONTAINER, ContentModel.TYPE_FOLDER, null); + } + txn = transactionService.getUserTransaction(); txn.begin(); // Create users + createUser(USER_ONE, SiteModel.SITE_CONSUMER); createUser(USER_TWO, SiteModel.SITE_CONTRIBUTOR); + createUser(USER_THREE, SiteModel.SITE_COLLABORATOR); + createUser(USER_FOUR, SiteModel.SITE_COLLABORATOR); + // Create site page sitePage = nodeService.createNode(siteInfo.getNodeRef(), ContentModel.ASSOC_CONTAINS, @@ -240,11 +270,13 @@ public class CommentsApiTest extends BaseWebScriptTest // delete the users deleteUser(USER_ONE); deleteUser(USER_TWO); + deleteUser(USER_THREE); + deleteUser(USER_FOUR); } - + /** * add a comment to given node ref - * + * * @param nodeRef * @param user * @param status @@ -257,7 +289,7 @@ public class CommentsApiTest extends BaseWebScriptTest UserTransaction txn = transactionService.getUserTransaction(); txn.begin(); - + // Not allowed if you're not an admin AuthenticationUtil.setFullyAuthenticatedUser(user); @@ -298,6 +330,94 @@ public class CommentsApiTest extends BaseWebScriptTest return response; } + + + /** + * delete comment + * + * @param commentNodeRef + * @param parentNodeRef + * @param user + * @param status + * @throws Exception + */ + private void deleteComment(NodeRef commentNodeRef, NodeRef parentNodeRef, String user, int status) throws Exception + { + Response response = null; + + UserTransaction txn = transactionService.getUserTransaction(); + txn.begin(); + + // Not allowed if you're not an admin + AuthenticationUtil.setFullyAuthenticatedUser(user); + + String itemTitle = "Test Title"; + String page = "document-details"; + + StringBuilder pageParamsBuilder = new StringBuilder("{"); + pageParamsBuilder.append("\"nodeRef\" : \""); + pageParamsBuilder.append(parentNodeRef.toString()); + pageParamsBuilder.append("\", "); + pageParamsBuilder.append("}"); + String pageParams = pageParamsBuilder.toString(); + + String URL = MessageFormat.format(URL_DELETE_COMMENT, new Object[] { commentNodeRef.getStoreRef().getProtocol(), + commentNodeRef.getStoreRef().getIdentifier(), commentNodeRef.getId(), SITE_SHORT_NAME, itemTitle, page, pageParams }); + response = sendRequest(new DeleteRequest(URL), status); + assertEquals(status, response.getStatus()); + + // Normally, webscripts are in their own transaction. The test + // infrastructure here forces us to have a transaction + // around the calls. if the WebScript fails, then we should rollback. + if (response.getStatus() == 500) + { + txn.rollback(); + } + else + { + txn.commit(); + } + } + + /** + * + * @param nodeRef + * @param user + * @param expectedStatus + * @return + * @throws Exception + */ + private Response updateComment(NodeRef nodeRef, String user, int expectedStatus) throws Exception + { + Response response = null; + UserTransaction txn = transactionService.getUserTransaction(); + txn.begin(); + AuthenticationUtil.setFullyAuthenticatedUser(user); + + String now = System.currentTimeMillis()+""; + + JSONObject comment = new JSONObject(); + comment.put("title", "Test title updated "+now); + comment.put("content", "Test comment updated "+now); + + response = sendRequest(new PutRequest(MessageFormat.format(URL_PUT_COMMENT, + new Object[] {nodeRef.getStoreRef().getProtocol(), nodeRef.getStoreRef().getIdentifier(), nodeRef.getId()}), comment.toString(), JSON), expectedStatus); + + assertEquals(expectedStatus, response.getStatus()); + + // Normally, webscripts are in their own transaction. The test infrastructure here forces us to have a transaction + // around the calls. if the WebScript fails, then we should rollback. + if (response.getStatus() == 500) + { + txn.rollback(); + } + else + { + txn.commit(); + } + + return response; + } private String getCurrentVersion(NodeRef nodeRef) throws Exception { @@ -345,8 +465,88 @@ public class CommentsApiTest extends BaseWebScriptTest txn.commit(); } - - + + /** + * MNT-16446 + * @throws Exception + */ + public void testCommentUpdateAndDeletePermission() throws Exception + { + authenticationComponent.setCurrentUser(AuthenticationUtil.getAdminUserName()); + + NodeRef sharedContent = null; + NodeRef siteContent = null; + + { + // + // in Shared folder + // + UserTransaction txn = transactionService.getUserTransaction(); + txn.begin(); + sharedContent = fileFolderService.create(sharedHomeNodeRef, "SharedContent" + System.currentTimeMillis(), ContentModel.TYPE_CONTENT).getNodeRef(); + txn.commit(); + + Response response = addComment(sharedContent, USER_THREE, 200); + JSONObject jsonResponse = parseResponseJSON(response); + NodeRef commentNodeRef = new NodeRef(getOrNull(jsonResponse, JSON_KEY_NODEREF)); + + // MNT-16446 - now returns 403 rather than 500 + // -ve test: + updateComment(commentNodeRef, USER_FOUR, 403); + + updateComment(commentNodeRef, USER_THREE, 200); + + // -ve test: ideally would return 403, but currently v0 REST API returns 500 :-( + deleteComment(commentNodeRef, sharedContent, USER_FOUR, 500); + + deleteComment(commentNodeRef, sharedContent, USER_THREE, 200); + } + + { + // + // in a public Site + // + txn = transactionService.getUserTransaction(); + txn.begin(); + NodeRef siteDocLibNodeRef = siteService.getContainer(SITE_SHORT_NAME, DOCLIB_CONTAINER); + siteContent = fileFolderService.create(siteDocLibNodeRef, "SiteContent" + System.currentTimeMillis(), ContentModel.TYPE_CONTENT).getNodeRef(); + txn.commit(); + + Response response = addComment(siteContent, USER_THREE, 200); + JSONObject jsonResponse = parseResponseJSON(response); + NodeRef commentNodeRef = new NodeRef(getOrNull(jsonResponse, JSON_KEY_NODEREF)); + + // MNT-16446 - now returns 403 rather than 200 !! + // -ve test: + updateComment(commentNodeRef, USER_FOUR, 403); + + updateComment(commentNodeRef, USER_THREE, 200); + + // -ve test: ideally would return 403, but currently v0 REST API returns 500 :-( + deleteComment(commentNodeRef, siteContent, USER_FOUR, 500); + + deleteComment(commentNodeRef, siteContent, USER_THREE, 200); + } + + { + // cleanup + authenticationComponent.setCurrentUser(AuthenticationUtil.getAdminUserName()); + txn = transactionService.getUserTransaction(); + txn.begin(); + + if (sharedContent != null) + { + nodeService.deleteNode(sharedContent); + } + + if (siteContent != null) + { + nodeService.deleteNode(siteContent); + } + txn.commit(); + } + } + private void createUser(String userName) { // if user with given user name doesn't already exist then create user @@ -432,34 +632,34 @@ public class CommentsApiTest extends BaseWebScriptTest assertEquals(modifiedDateBefore.getTime(), modifiedDateAfter.getTime()); assertEquals(modifierBefore, modifierAfter); } - + + /** + * REPO-828 (MNT-16401) + * @throws Exception + */ + public void testDeleteCommentPostActivity() throws Exception + { + permissionService.setPermission(sitePage, USER_TWO, PermissionService.ALL_PERMISSIONS, true); + postLookup.execute(); + feedGenerator.execute(); + int activityNumStart = activityService.getSiteFeedEntries(SITE_SHORT_NAME).size(); + Response response = addComment(sitePage, USER_TWO, 200); + postLookup.execute(); + feedGenerator.execute(); + int activityNumNext = activityService.getSiteFeedEntries(SITE_SHORT_NAME).size(); + assertEquals("The activity feeds were not generated after adding a comment", activityNumStart + 1, activityNumNext); + JSONObject jsonResponse = parseResponseJSON(response); + String nodeRefComment = getOrNull(jsonResponse, JSON_KEY_NODEREF); + NodeRef commentNodeRef = new NodeRef(nodeRefComment); + deleteComment(commentNodeRef, sitePage, USER_TWO, 200); + activityNumStart = activityNumNext; + postLookup.execute(); + feedGenerator.execute(); + activityNumNext = activityService.getSiteFeedEntries(SITE_SHORT_NAME).size(); + assertEquals("The activity feeds were not generated after deleting a comment", activityNumStart + 1, activityNumNext); + } + /** - * REPO-828 (MNT-16401) - * @throws Exception - */ - public void testDeleteCommentPostActivity() throws Exception - { - permissionService.setPermission(sitePage, USER_TWO, PermissionService.ALL_PERMISSIONS, true); - postLookup.execute(); - feedGenerator.execute(); - int activityNumStart = activityService.getSiteFeedEntries(SITE_SHORT_NAME).size(); - Response response = addComment(sitePage, USER_TWO, 200); - postLookup.execute(); - feedGenerator.execute(); - int activityNumNext = activityService.getSiteFeedEntries(SITE_SHORT_NAME).size(); - assertEquals("The activity feeds were not generated after adding a comment", activityNumStart + 1, activityNumNext); - JSONObject jsonResponse = parseResponseJSON(response); - String nodeRefComment = getOrNull(jsonResponse, JSON_KEY_NODEREF); - NodeRef commentNodeRef = new NodeRef(nodeRefComment); - deleteComment(commentNodeRef, sitePage, USER_TWO, 200); - activityNumStart = activityNumNext; - postLookup.execute(); - feedGenerator.execute(); - activityNumNext = activityService.getSiteFeedEntries(SITE_SHORT_NAME).size(); - assertEquals("The activity feeds were not generated after deleting a comment", activityNumStart + 1, activityNumNext); - } - - /** * MNT-12082 */ public void testConsumerCanNotComment() throws Exception @@ -516,54 +716,6 @@ public class CommentsApiTest extends BaseWebScriptTest authenticationService.deleteAuthentication(user); } } - - - /** - * delete comment - * - * @param commentNodeRef - * @param parentNodeRef - * @param user - * @param status - * @throws Exception - */ - private void deleteComment(NodeRef commentNodeRef, NodeRef parentNodeRef, String user, int status) throws Exception - { - Response response = null; - - UserTransaction txn = transactionService.getUserTransaction(); - txn.begin(); - - // Not allowed if you're not an admin - AuthenticationUtil.setFullyAuthenticatedUser(user); - - String itemTitle = "Test Title"; - String page = "document-details"; - - StringBuilder pageParamsBuilder = new StringBuilder("{"); - pageParamsBuilder.append("\"nodeRef\" : \""); - pageParamsBuilder.append(parentNodeRef.toString()); - pageParamsBuilder.append("\", "); - pageParamsBuilder.append("}"); - String pageParams = pageParamsBuilder.toString(); - - String URL = MessageFormat.format(URL_DELETE_COMMENT, new Object[] { commentNodeRef.getStoreRef().getProtocol(), - commentNodeRef.getStoreRef().getIdentifier(), commentNodeRef.getId(), SITE_SHORT_NAME, itemTitle, page, pageParams }); - response = sendRequest(new DeleteRequest(URL), status); - assertEquals(status, response.getStatus()); - - // Normally, webscripts are in their own transaction. The test - // infrastructure here forces us to have a transaction - // around the calls. if the WebScript fails, then we should rollback. - if (response.getStatus() == 500) - { - txn.rollback(); - } - else - { - txn.commit(); - } - } /** * returns value from JSON for a given key