Files
alfresco-community-repo/source/test-java/org/alfresco/repo/quickshare/QuickShareServiceIntegrationTest.java
Alexandra Leahu f0ac5fd4e9 Merged 5.1.N (5.1.2) to 5.2.N (5.2.1)
127454 jkaabimofrad: MNT-16224, RA-1093: Fixed Quickshare issue where deleting a shared node didn't remove the 'shared' aspect. The fix also takes care of the shared nodes that have been deleted but not yet restored, as well as, shared nodes that have already been restored from the trashcan (allow the user to un-share).


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.2.N/root@127465 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
2016-06-01 13:26:30 +00:00

591 lines
22 KiB
Java

/*
* #%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%
*/
package org.alfresco.repo.quickshare;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.ByteArrayInputStream;
import java.io.Serializable;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.model.QuickShareModel;
import org.alfresco.repo.model.Repository;
import org.alfresco.repo.node.archive.NodeArchiveService;
import org.alfresco.repo.node.archive.RestoreNodeReport;
import org.alfresco.repo.node.archive.RestoreNodeReport.RestoreStatus;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.repo.tenant.TenantUtil;
import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork;
import org.alfresco.service.cmr.attributes.AttributeService;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.quickshare.InvalidSharedIdException;
import org.alfresco.service.cmr.quickshare.QuickShareDTO;
import org.alfresco.service.cmr.quickshare.QuickShareService;
import org.alfresco.service.cmr.repository.CopyService;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.test.junitrules.AlfrescoPerson;
import org.alfresco.util.test.junitrules.ApplicationContextInit;
import org.alfresco.util.test.junitrules.TemporaryModels;
import org.alfresco.util.test.junitrules.TemporaryNodes;
import org.apache.commons.codec.binary.Base64;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.RuleChain;
import org.safehaus.uuid.UUID;
import org.safehaus.uuid.UUIDGenerator;
import org.springframework.context.ApplicationContext;
/**
* Quick share service tests.
*
* @author Alex Miller
* @since Cloud/4.2
*/
public class QuickShareServiceIntegrationTest
{
private static final ApplicationContextInit testContext = new ApplicationContextInit();
private static final String MODEL =
"<?xml version='1.0' encoding='UTF-8'?>" +
"<model name='lx:lxmodel' xmlns='http://www.alfresco.org/model/dictionary/1.0'>" +
"<description>LX model</description>" +
"<author>Peter Löfgren</author>" +
"<version>1.0</version>" +
"<imports>" +
"<import uri='http://www.alfresco.org/model/dictionary/1.0' prefix='d' />" +
"<import uri='http://www.alfresco.org/model/content/1.0' prefix='cm' />" +
"</imports>" +
"<namespaces>" +
"<namespace uri='http://bugtestmodel' prefix='lx' />" +
"</namespaces>" +
"<constraints>" +
"</constraints>" +
"<types>" +
"<type name='lx:doc'>" +
"<title>LX dokument</title>" +
"<parent>cm:content</parent>" +
"<mandatory-aspects>" +
"<aspect>cm:generalclassifiable</aspect>" +
"</mandatory-aspects>" +
"</type>" +
"<type name='lx:doc2'>" +
"<title>LX dokument 2</title>" +
"<parent>cm:cmobject</parent>" +
"</type>" +
"</types>" +
"</model>";
private static CopyService copyService;
private static NodeService nodeService;
private static QuickShareService quickShareService;
private static DictionaryService dictionaryService;
private static Repository repository;
private static AttributeService attributeService;
private static PermissionService permissionService;
private static NodeArchiveService nodeArchiveService;
private static AlfrescoPerson user1 = new AlfrescoPerson(testContext, "UserOne");
private static AlfrescoPerson user2 = new AlfrescoPerson(testContext, "UserTwo");
// A rule to manage test nodes reused across all the test methods
@Rule public TemporaryNodes testNodes = new TemporaryNodes(testContext);
@Rule public TemporaryModels temporaryModels = new TemporaryModels(testContext);
@ClassRule public static RuleChain classChain = RuleChain.outerRule(testContext)
.around(user1)
.around(user2);
private NodeRef testNode;
private NodeRef userHome;
@BeforeClass public static void beforeClass() throws Exception
{
findServices();
}
private static void findServices()
{
ApplicationContext ctx = testContext.getApplicationContext();
copyService = ctx.getBean("CopyService", CopyService.class);
dictionaryService = ctx.getBean("dictionaryService", DictionaryService.class);
nodeService = ctx.getBean("NodeService", NodeService.class);
quickShareService = ctx.getBean("QuickShareService", QuickShareService.class);
repository = ctx.getBean("repositoryHelper", Repository.class);
attributeService = ctx.getBean("AttributeService", AttributeService.class);
permissionService = ctx.getBean("PermissionService", PermissionService.class);
nodeArchiveService = ctx.getBean("nodeArchiveService", NodeArchiveService.class);
}
@Before public void createTestData()
{
userHome = repository.getUserHome(user1.getPersonNode());
testNode = testNodes.createNodeWithTextContent(userHome,
"Quick Share Test Node",
ContentModel.TYPE_CONTENT,
user1.getUsername(),
"Quick Share Test Node Content");
}
@Test public void getMetaDataFromNodeRefByOwner()
{
Map<String, Object> metadata = AuthenticationUtil.runAs(new RunAsWork<Map<String,Object>>(){
@Override
public Map<String, Object> doWork() throws Exception
{
return quickShareService.getMetaData(testNode);
}
}, user1.getUsername());
assertNotNull(metadata);
assertTrue(metadata.size() > 0);
}
@Test(expected=AccessDeniedException.class)
public void getMetaDataFromNodeRefByNonOwner()
{
Map<String, Object> metadata = AuthenticationUtil.runAs(new RunAsWork<Map<String,Object>>(){
@Override
public Map<String, Object> doWork() throws Exception
{
return quickShareService.getMetaData(testNode);
}
}, user2.getUsername());
}
@Test public void share()
{
share(testNode, user1.getUsername());
AuthenticationUtil.runAsSystem(new RunAsWork<Void>(){
@Override
public Void doWork() throws Exception
{
assertTrue( nodeService.getAspects(testNode).contains(QuickShareModel.ASPECT_QSHARE));
assertNotNull(nodeService.getProperty(testNode, QuickShareModel.PROP_QSHARE_SHAREDID));
assertEquals(user1.getUsername(), nodeService.getProperty(testNode, QuickShareModel.PROP_QSHARE_SHAREDBY));
return null;
}
});
}
@Test public void unshare() {
final QuickShareDTO dto = share(testNode, user1.getUsername());
unshare(dto.getId(), user1.getUsername());
AuthenticationUtil.runAsSystem(new RunAsWork<Void>(){
@Override
public Void doWork() throws Exception
{
assertFalse( nodeService.getAspects(testNode).contains(QuickShareModel.ASPECT_QSHARE));
assertNull(nodeService.getProperty(testNode, QuickShareModel.PROP_QSHARE_SHAREDID));
assertNull(nodeService.getProperty(testNode, QuickShareModel.PROP_QSHARE_SHAREDBY));
return null;
}
});
}
// MNT-16224, RA-1093
@Test public void testDeleteAndRestoreSharedNode()
{
// Share the test node
share(testNode, user1.getUsername());
AuthenticationUtil.runAsSystem(new RunAsWork<Void>()
{
@Override
public Void doWork() throws Exception
{
assertTrue(nodeService.hasAspect(testNode, QuickShareModel.ASPECT_QSHARE));
return null;
}
});
// Delete and restore the shared node.
testNode = AuthenticationUtil.runAs(new RunAsWork<NodeRef>()
{
@Override
public NodeRef doWork() throws Exception
{
// Delete the shared node
nodeService.deleteNode(testNode);
// Check if the node has been archived
final NodeRef archivedNode = nodeArchiveService.getArchivedNode(testNode);
assertNotNull(archivedNode);
// Restore the deleted shared node from trashcan
RestoreNodeReport restoreNodeReport = nodeArchiveService.restoreArchivedNode(archivedNode);
assertNotNull(restoreNodeReport);
assertTrue(restoreNodeReport.getStatus() == RestoreStatus.SUCCESS);
NodeRef restoredNodeRef = restoreNodeReport.getRestoredNodeRef();
assertNotNull(restoredNodeRef);
return restoredNodeRef;
}
}, user1.getUsername());
// Check the restored node doesn't have the 'shared' aspect.
AuthenticationUtil.runAsSystem(new RunAsWork<Void>()
{
@Override
public Void doWork() throws Exception
{
assertFalse(nodeService.hasAspect(testNode, QuickShareModel.ASPECT_QSHARE));
assertNull(nodeService.getProperty(testNode, QuickShareModel.PROP_QSHARE_SHAREDID));
assertNull(nodeService.getProperty(testNode, QuickShareModel.PROP_QSHARE_SHAREDBY));
return null;
}
});
/**
* Tests the scenario where the shared node has been deleted and restored before the fix (MNT-16224).
* In this scenario the user should be able to un-share the restored node.
*/
{
// Share the test node again
final QuickShareDTO dto = share(testNode, user1.getUsername());
// Delete only the sharedId without removing the 'shared' aspect!(The cause of MNT-16224 and RA-1093)
TenantUtil.runAsDefaultTenant(new TenantRunAsWork<Void>()
{
public Void doWork() throws Exception
{
attributeService.removeAttribute(".sharedIds", dto.getId());
return null;
}
});
// Check the 'shared' aspect does exist
AuthenticationUtil.runAsSystem(new RunAsWork<Void>()
{
@Override
public Void doWork() throws Exception
{
assertTrue(nodeService.hasAspect(testNode, QuickShareModel.ASPECT_QSHARE));
return null;
}
});
try
{
// Try to un-share the node even though the sharedId was deleted.
unshare(dto.getId(), user2.getUsername());
fail("user2 shouldn't be able to un-share the node.");
}
catch (InvalidSharedIdException ex)
{
// Expected
}
// Un-share the node even though the sharedId was deleted.
// This should succeed as the lookup will use TMDQ.
unshare(dto.getId(), user1.getUsername());
// Check the 'shared' aspect does not exist
AuthenticationUtil.runAsSystem(new RunAsWork<Void>()
{
@Override
public Void doWork() throws Exception
{
assertFalse(nodeService.hasAspect(testNode, QuickShareModel.ASPECT_QSHARE));
return null;
}
});
}
}
private void unshare(final String sharedId, final String userName) {
AuthenticationUtil.runAs(new RunAsWork<Void>()
{
@Override
public Void doWork() throws Exception
{
quickShareService.unshareContent(sharedId);
return null;
}
}, userName);
}
private QuickShareDTO share(final NodeRef nodeRef, String username)
{
return AuthenticationUtil.runAs(new RunAsWork<QuickShareDTO>()
{
@Override
public QuickShareDTO doWork() throws Exception
{
return quickShareService.shareContent(nodeRef);
}
}, username);
}
@Test public void getMetadataFromShareId()
{
QuickShareDTO dto = share(testNode, user1.getUsername());
Map<String, Object> metadata = quickShareService.getMetaData(dto.getId());
assertNotNull(metadata);
assertTrue(metadata.size() > 0);
}
@Test(expected=InvalidSharedIdException.class) public void getMetadataFromShareIdWithInvalidId()
{
UUID uuid = UUIDGenerator.getInstance().generateRandomBasedUUID();
String sharedId = Base64.encodeBase64URLSafeString(uuid.toByteArray()); // => 22 chars (eg. q3bEKPeDQvmJYgt4hJxOjw)
Map<String, Object> metadata = quickShareService.getMetaData(sharedId);
}
@Test public void copyNode()
{
share(testNode, user1.getUsername());
AuthenticationUtil.runAs(new RunAsWork<Object>()
{
@Override
public Object doWork() throws Exception
{
Assert.assertTrue(nodeService.hasAspect(testNode, QuickShareModel.ASPECT_QSHARE));
Assert.assertNotNull(nodeService.getProperty(testNode, QuickShareModel.PROP_QSHARE_SHAREDBY));
Assert.assertNotNull(nodeService.getProperty(testNode, QuickShareModel.PROP_QSHARE_SHAREDID));
Map<QName, Serializable> originalProps = nodeService.getProperties(testNode);
NodeRef copyNodeRef = copyService.copyAndRename(testNode, userHome, ContentModel.ASSOC_CONTAINS,
QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "copy"), true);
Map<QName, Serializable> copyProps = nodeService.getProperties(copyNodeRef);
Assert.assertFalse(nodeService.hasAspect(copyNodeRef, QuickShareModel.ASPECT_QSHARE));
Assert.assertNull(nodeService.getProperty(copyNodeRef, QuickShareModel.PROP_QSHARE_SHAREDBY));
Assert.assertNull(nodeService.getProperty(copyNodeRef, QuickShareModel.PROP_QSHARE_SHAREDID));
for (QName property : originalProps.keySet())
{
if (property.equals(QuickShareModel.PROP_QSHARE_SHAREDBY) ||
property.equals(QuickShareModel.PROP_QSHARE_SHAREDID))
{
continue;
}
Assert.assertTrue("Mising property " + property, copyProps.containsKey(property));
}
return null;
}
}, user1.getUsername());
}
/**
* Content types that extend cm:content should be shareable.
*
* See https://issues.alfresco.com/jira/browse/ALF-16274.
*/
@Test public void testWithCustomContentType()
{
ByteArrayInputStream modelStream = new ByteArrayInputStream(MODEL.getBytes());
temporaryModels.loadModel(modelStream);
QName sharableType = QName.createQName("{http://bugtestmodel}doc");
QName unsharableType = QName.createQName("{http://bugtestmodel}doc2");
final NodeRef sharableNode = testNodes.createNodeWithTextContent(userHome,
"Quick Share Custom Type Sharable Test Node",
sharableType,
user1.getUsername(),
"Quick Share Test Node Content");
Map<String, Object> metadata = getMetadata(sharableNode, user1);
assertTrue((Boolean)metadata.get("sharable"));
QuickShareDTO dto = share(sharableNode, user1.getUsername());
unshare(dto.getId(), user1.getUsername());
final NodeRef unsharableNode = testNodes.createNodeWithTextContent(userHome,
"Quick Share Custom Type Unsharable Test Node",
unsharableType,
user1.getUsername(),
"Quick Share Test Node Content");
metadata = getMetadata(unsharableNode, user1);
assertFalse((Boolean)metadata.get("sharable"));
boolean exceptionThrown = false;
try {
// Prior to fixing ALF-16274, this would throw an InvalidNodeRefException.
share(unsharableNode, user1.getUsername());
}
catch(InvalidNodeRefException ex)
{
exceptionThrown = true;
}
assertTrue("InvalidNodeRefException not thrown on trying to share an unsharable content type", exceptionThrown);
}
@SuppressWarnings("unchecked")
private Map<String, Object> getMetadata(final NodeRef nodeRef, AlfrescoPerson user) {
Map<String, Object> container = AuthenticationUtil.runAs(new RunAsWork<Map<String, Object>>()
{
@Override
public Map<String, Object> doWork() throws Exception
{
return quickShareService.getMetaData(nodeRef);
}
}, user.getUsername());
return (Map<String, Object>)container.get("item");
}
@Test public void cloud928()
{
final NodeRef node = testNodes.createNodeWithTextContent(userHome,
"CLOUD-928 Test Node",
ContentModel.TYPE_CONTENT,
user1.getUsername(),
"Quick Share Test Node Content");
QuickShareDTO dto = share(node, user1.getUsername());
attributeService.removeAttribute(QuickShareServiceImpl.ATTR_KEY_SHAREDIDS_ROOT, dto.getId());
AuthenticationUtil.runAs(new RunAsWork<Object>(){
@Override
public Object doWork() throws Exception {
nodeService.deleteNode(node);
return null;
}
}, user1.getUsername());
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
Assert.assertFalse(nodeService.exists(node));
}
/**
* Test for MNT-11960
* <p> The node is created by user1 and shared by user2.
* <p> The modifier should not change to user2 after sharing.
*/
@Test
public void testModifierAfterSharing()
{
AuthenticationUtil.runAs(new RunAsWork<Void>(){
@Override
public Void doWork() throws Exception
{
permissionService.setPermission(testNode, user2.getUsername(), PermissionService.CONSUMER, true);
return null;
}
}, user1.getUsername());
final Serializable modifiedDate = AuthenticationUtil.runAsSystem(new RunAsWork<Serializable>(){
@Override
public Serializable doWork() throws Exception
{
return nodeService.getProperty(testNode, ContentModel.PROP_MODIFIED);
}
});
share(testNode, user2.getUsername());
AuthenticationUtil.runAsSystem(new RunAsWork<Void>(){
@Override
public Void doWork() throws Exception
{
assertTrue(nodeService.getAspects(testNode).contains(ContentModel.ASPECT_AUDITABLE));
assertNotNull(nodeService.getProperty(testNode, ContentModel.PROP_MODIFIER));
assertEquals("The modifier has changed after sharing.", user1.getUsername(), nodeService.getProperty(testNode, ContentModel.PROP_MODIFIER));
assertNotNull(nodeService.getProperty(testNode, ContentModel.PROP_MODIFIED));
assertEquals("The modified date has changed after sharing.", modifiedDate, nodeService.getProperty(testNode, ContentModel.PROP_MODIFIED));
return null;
}
});
}
/**
* Test for MNT-15654
* <p> The node is created and shared by user1. Then unshared by user2
* <p> The modifier should not change to user2 after unsharing.
*/
@Test
public void testModifierAfterUnSharing()
{
AuthenticationUtil.runAs(new RunAsWork<Void>(){
@Override
public Void doWork() throws Exception
{
permissionService.setPermission(testNode, user2.getUsername(), PermissionService.CONSUMER, true);
return null;
}
}, user1.getUsername());
QuickShareDTO dto = share(testNode, user1.getUsername());
unshare(dto.getId(), user2.getUsername());
String modifier = AuthenticationUtil.runAsSystem(new RunAsWork<String>(){
@Override
public String doWork() throws Exception
{
return (String )nodeService.getProperty(testNode, ContentModel.PROP_MODIFIER);
}
});
assertEquals("The modifier has changed after sharing.", user1.getUsername(), modifier);
}
}