mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
PublishingQueue.scheduleNewEvent() now includes a permission check to ensure user has 'Add CHild' access to the relevant Channels.
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@29440 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -66,6 +66,7 @@
|
||||
<property name="publishingEventHelper" ref="publishingEventHelper" />
|
||||
<property name="retryingTransactionHelper" ref="retryingTransactionHelper" />
|
||||
<property name="transferManifestNodeFactory" ref="transferManifestNodeFactory" />
|
||||
<property name="permissionService" ref="PermissionService" />
|
||||
<property name="publishingStore" value="${spaces.store}" />
|
||||
<property name="publishingRootPath" value="${publishing.root}" />
|
||||
</bean>
|
||||
@@ -75,6 +76,7 @@
|
||||
<property name="contentService" ref="ContentService" />
|
||||
<property name="serializer" ref="publishingPackageSerializer" />
|
||||
<property name="workflowService" ref="WorkflowService" />
|
||||
<property name="permissionService" ref="PermissionService" />
|
||||
<property name="workflowEngineId" value="jbpm" />
|
||||
</bean>
|
||||
|
||||
|
@@ -62,8 +62,6 @@ public abstract class AbstractPublishingIntegrationTest extends BaseSpringTest
|
||||
protected Environment environment;
|
||||
protected NodeRef docLib;
|
||||
|
||||
protected UserTransaction transaction;
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void onSetUp() throws Exception
|
||||
@@ -76,10 +74,6 @@ public abstract class AbstractPublishingIntegrationTest extends BaseSpringTest
|
||||
this.fileFolderService = serviceRegistry.getFileFolderService();
|
||||
this.nodeService = serviceRegistry.getNodeService();
|
||||
|
||||
transaction = serviceRegistry.getTransactionService().getUserTransaction();
|
||||
transaction.begin();
|
||||
transaction.setRollbackOnly();
|
||||
|
||||
this.siteId = GUID.generate();
|
||||
siteService.createSite("test", siteId,
|
||||
"Site created by publishing test",
|
||||
@@ -89,30 +83,21 @@ public abstract class AbstractPublishingIntegrationTest extends BaseSpringTest
|
||||
|
||||
this.environment = rootObject.getEnvironment();
|
||||
this.queue = rootObject.getPublishingQueue();
|
||||
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
|
||||
}
|
||||
|
||||
@After
|
||||
public void onTearDown() throws Exception
|
||||
{
|
||||
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
|
||||
siteService.deleteSite(siteId);
|
||||
try
|
||||
{
|
||||
if (transaction.getStatus() == Status.STATUS_MARKED_ROLLBACK)
|
||||
{
|
||||
transaction.rollback();
|
||||
}
|
||||
else
|
||||
{
|
||||
transaction.commit();
|
||||
}
|
||||
siteService.deleteSite(siteId);
|
||||
}
|
||||
catch (Exception e)
|
||||
finally
|
||||
{
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
super.onTearDown();
|
||||
}
|
||||
super.onTearDown();
|
||||
}
|
||||
|
||||
protected ChannelType mockChannelType()
|
||||
|
@@ -26,6 +26,8 @@ import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.repo.transfer.manifest.TransferManifestNodeFactory;
|
||||
import org.alfresco.repo.transfer.manifest.TransferManifestNormalNode;
|
||||
import org.alfresco.service.cmr.publishing.MutablePublishingPackage;
|
||||
@@ -68,7 +70,20 @@ public class MutablePublishingPackageImpl implements MutablePublishingPackage
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void addNodesToPublish(Collection<NodeRef> nodesToAdd)
|
||||
public void addNodesToPublish(final Collection<NodeRef> nodesToAdd)
|
||||
{
|
||||
AuthenticationUtil.runAs(new RunAsWork<Void>()
|
||||
{
|
||||
public Void doWork() throws Exception
|
||||
{
|
||||
versionNodes(nodesToAdd);
|
||||
return null;
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
nodesToPublish.addAll(nodesToAdd);
|
||||
}
|
||||
|
||||
private void versionNodes(Collection<NodeRef> nodesToAdd)
|
||||
{
|
||||
for (NodeRef nodeRef : nodesToAdd)
|
||||
{
|
||||
@@ -85,7 +100,6 @@ public class MutablePublishingPackageImpl implements MutablePublishingPackage
|
||||
entryMap.put(nodeRef, publishingPackage);
|
||||
}
|
||||
}
|
||||
nodesToPublish.addAll(nodesToAdd);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -59,6 +59,7 @@ import java.util.TimeZone;
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.node.NodeUtils;
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.repo.workflow.WorkflowModel;
|
||||
import org.alfresco.service.cmr.publishing.PublishingEvent;
|
||||
import org.alfresco.service.cmr.publishing.PublishingEventFilter;
|
||||
@@ -72,6 +73,8 @@ import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowPath;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowService;
|
||||
@@ -98,6 +101,7 @@ public class PublishingEventHelper
|
||||
private ContentService contentService;
|
||||
private WorkflowService workflowService;
|
||||
private PublishingPackageSerializer serializer;
|
||||
private PermissionService permissionService;
|
||||
|
||||
private String workflowEngineId;
|
||||
|
||||
@@ -143,6 +147,14 @@ public class PublishingEventHelper
|
||||
this.serializer = serializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param permissionService the permissionService to set
|
||||
*/
|
||||
public void setPermissionService(PermissionService permissionService)
|
||||
{
|
||||
this.permissionService = permissionService;
|
||||
}
|
||||
|
||||
public PublishingEvent getPublishingEvent(NodeRef eventNode) throws AlfrescoRuntimeException
|
||||
{
|
||||
if(eventNode == null)
|
||||
@@ -198,6 +210,12 @@ public class PublishingEventHelper
|
||||
public NodeRef createNode(NodeRef queueNode, PublishingPackage publishingPackage, String channelId, Calendar schedule, String comment, StatusUpdate statusUpdate)
|
||||
throws Exception
|
||||
{
|
||||
checkChannelAccess(channelId);
|
||||
if(statusUpdate != null && isEmpty(statusUpdate.getChannelIds())==false )
|
||||
for (String statusChannelId : statusUpdate.getChannelIds())
|
||||
{
|
||||
checkChannelAccess(statusChannelId);
|
||||
}
|
||||
if (schedule == null)
|
||||
{
|
||||
schedule = Calendar.getInstance();
|
||||
@@ -214,6 +232,16 @@ public class PublishingEventHelper
|
||||
return eventNode;
|
||||
}
|
||||
|
||||
private void checkChannelAccess(String channelId)
|
||||
{
|
||||
NodeRef channelNode = new NodeRef(channelId);
|
||||
AccessStatus accessStatus = permissionService.hasPermission(channelNode, PermissionService.ADD_CHILDREN);
|
||||
if(AccessStatus.ALLOWED != accessStatus)
|
||||
{
|
||||
throw new AccessDeniedException("You do not have access to channel: " + channelId);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<QName, Serializable> buildPublishingEventProperties(PublishingPackage publishingPackage,
|
||||
String channelId, Calendar schedule, String comment, StatusUpdate statusUpdate, String name)
|
||||
{
|
||||
|
@@ -32,6 +32,7 @@ import static org.alfresco.repo.publishing.PublishingModel.PROP_PUBLISHING_EVENT
|
||||
import static org.alfresco.repo.publishing.PublishingModel.TYPE_PUBLISHING_EVENT;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyMap;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -59,6 +60,8 @@ import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -84,6 +87,9 @@ public class PublishingEventHelperTest
|
||||
@Resource(name="ContentService")
|
||||
ContentService contentService;
|
||||
|
||||
@Resource(name="PermissionService")
|
||||
PermissionService permissionService;
|
||||
|
||||
@Test
|
||||
public void testGetPublishingEventNode() throws Exception
|
||||
{
|
||||
@@ -168,6 +174,7 @@ public class PublishingEventHelperTest
|
||||
@Test
|
||||
public void testCreateNode() throws Exception
|
||||
{
|
||||
when(permissionService.hasPermission(any(NodeRef.class), anyString())).thenReturn(AccessStatus.ALLOWED);
|
||||
// Mock serializer since this behaviour is already tested in PublishingPackageSerializerTest.
|
||||
ContentWriter writer = mock(ContentWriter.class);
|
||||
when(contentService.getWriter(any(NodeRef.class), eq(PROP_PUBLISHING_EVENT_PAYLOAD), eq(true)))
|
||||
@@ -186,7 +193,7 @@ public class PublishingEventHelperTest
|
||||
|
||||
Map<NodeRef, PublishingPackageEntry> entires = Collections.emptyMap();
|
||||
PublishingPackage pckg = new PublishingPackageImpl(entires);
|
||||
String channelName = "The channel";
|
||||
String channelName = "test://channel/id";
|
||||
Calendar schedule = Calendar.getInstance();
|
||||
String comment = "The comment";
|
||||
|
||||
|
@@ -32,8 +32,12 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.repo.security.person.TestPersonManager;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.publishing.MutablePublishingPackage;
|
||||
import org.alfresco.service.cmr.publishing.PublishingEvent;
|
||||
import org.alfresco.service.cmr.publishing.PublishingPackage;
|
||||
@@ -41,11 +45,17 @@ import org.alfresco.service.cmr.publishing.PublishingPackageEntry;
|
||||
import org.alfresco.service.cmr.publishing.PublishingService;
|
||||
import org.alfresco.service.cmr.publishing.Status;
|
||||
import org.alfresco.service.cmr.publishing.StatusUpdate;
|
||||
import org.alfresco.service.cmr.publishing.channels.Channel;
|
||||
import org.alfresco.service.cmr.publishing.channels.ChannelType;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.security.MutableAuthenticationService;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowInstance;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowPath;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.GUID;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
@@ -58,9 +68,11 @@ public class PublishingQueueImplTest extends AbstractPublishingIntegrationTest
|
||||
private static final String channelId = "test://channel/node";
|
||||
private static final String comment = "The Comment";
|
||||
|
||||
protected PublishingService publishingService;
|
||||
|
||||
private PublishingService publishingService;
|
||||
private WorkflowService workflowService;
|
||||
private PermissionService permissionService;
|
||||
private TestPersonManager personManager;
|
||||
private ChannelServiceImpl channelService;
|
||||
|
||||
private String eventId;
|
||||
|
||||
@@ -142,7 +154,7 @@ public class PublishingQueueImplTest extends AbstractPublishingIntegrationTest
|
||||
NodeRef firstNode = createContent("First");
|
||||
NodeRef secondNode = createContent("Second");
|
||||
|
||||
List<String> channelNames = Arrays.asList("Channel1", "Channel2", "Channel3" );
|
||||
List<String> channelNames = Arrays.asList("test://channel/Channel1", "test://channel/Channel2", "test://channel/Channel3" );
|
||||
String message = "The message";
|
||||
StatusUpdate update = queue.createStatusUpdate(message, secondNode, channelNames);
|
||||
|
||||
@@ -162,6 +174,74 @@ public class PublishingQueueImplTest extends AbstractPublishingIntegrationTest
|
||||
assertTrue(names.containsAll(channelNames));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScheduleNewEventPermissions() throws Exception
|
||||
{
|
||||
// Create Channels as Admin
|
||||
ChannelType channelType = mockChannelType();
|
||||
channelService.register(channelType);
|
||||
Channel publishChannel = channelService.createChannel(channelType.getId(), "Channel1", null);
|
||||
NodeRef publishChannelNode = new NodeRef(publishChannel.getId());
|
||||
Channel statusChannel = channelService.createChannel(channelType.getId(), "Channel2", null);
|
||||
NodeRef statusChannelNode = new NodeRef(statusChannel.getId());
|
||||
|
||||
NodeRef firstNode = createContent("First");
|
||||
NodeRef secondNode = createContent("Second");
|
||||
|
||||
// Create User1, add read permissions and set as current user.
|
||||
String user1 = GUID.generate();
|
||||
personManager.createPerson(user1);
|
||||
permissionService.setPermission(publishChannelNode, user1, PermissionService.READ, true);
|
||||
permissionService.setPermission(statusChannelNode, user1, PermissionService.READ, true);
|
||||
personManager.setUser(user1);
|
||||
|
||||
// Publish an event
|
||||
MutablePublishingPackage publishingPackage = queue.createPublishingPackage();
|
||||
publishingPackage.addNodesToPublish(firstNode, secondNode);
|
||||
Calendar schedule = Calendar.getInstance();
|
||||
schedule.add(Calendar.HOUR, 2);
|
||||
try
|
||||
{
|
||||
this.eventId = queue.scheduleNewEvent(publishingPackage, publishChannel.getId(), schedule, comment, null);
|
||||
fail("shceduleNewEvent should have thrown an AccessDeniedException!");
|
||||
}
|
||||
catch(AlfrescoRuntimeException e)
|
||||
{
|
||||
//NOOP
|
||||
}
|
||||
|
||||
// Set Add Child permission on publish channel.
|
||||
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
|
||||
permissionService.setPermission(publishChannelNode, user1, PermissionService.ADD_CHILDREN, true);
|
||||
personManager.setUser(user1);
|
||||
|
||||
// Check publish works now.
|
||||
this.eventId = queue.scheduleNewEvent(publishingPackage, publishChannel.getId(), schedule, comment, null);
|
||||
assertNotNull(eventId);
|
||||
publishingService.cancelPublishingEvent(eventId);
|
||||
|
||||
String message = "The message";
|
||||
StatusUpdate update = queue.createStatusUpdate(message, secondNode, statusChannel.getId());
|
||||
try
|
||||
{
|
||||
this.eventId = queue.scheduleNewEvent(publishingPackage, publishChannel.getId(), schedule, comment, update);
|
||||
fail("shceduleNewEvent with status update should have thrown an AccessDeniedException!");
|
||||
}
|
||||
catch(AlfrescoRuntimeException e)
|
||||
{
|
||||
//NOOP
|
||||
}
|
||||
|
||||
// Set Add Child permission on status channel.
|
||||
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
|
||||
permissionService.setPermission(statusChannelNode, user1, PermissionService.ADD_CHILDREN, true);
|
||||
personManager.setUser(user1);
|
||||
|
||||
// Check publish works now.
|
||||
this.eventId = queue.scheduleNewEvent(publishingPackage, publishChannel.getId(), schedule, comment, null);
|
||||
assertNotNull(eventId);
|
||||
}
|
||||
|
||||
private NodeRef createContent(String name)
|
||||
{
|
||||
return fileFolderService.create(docLib, name, ContentModel.TYPE_CONTENT).getNodeRef();
|
||||
@@ -176,6 +256,13 @@ public class PublishingQueueImplTest extends AbstractPublishingIntegrationTest
|
||||
super.onSetUp();
|
||||
this.workflowService = serviceRegistry.getWorkflowService();
|
||||
this.publishingService = (PublishingService) getApplicationContext().getBean("publishingService");
|
||||
this.channelService = (ChannelServiceImpl) getApplicationContext().getBean("channelService");
|
||||
|
||||
this.permissionService = (PermissionService) getApplicationContext().getBean(ServiceRegistry.PERMISSIONS_SERVICE.getLocalName());
|
||||
MutableAuthenticationService authenticationService= (MutableAuthenticationService) getApplicationContext().getBean(ServiceRegistry.AUTHENTICATION_SERVICE.getLocalName());
|
||||
PersonService personService= (PersonService) getApplicationContext().getBean(ServiceRegistry.PERSON_SERVICE.getLocalName());
|
||||
|
||||
this.personManager = new TestPersonManager(authenticationService, personService, nodeService);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,6 +272,7 @@ public class PublishingQueueImplTest extends AbstractPublishingIntegrationTest
|
||||
@Override
|
||||
public void onTearDown() throws Exception
|
||||
{
|
||||
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
|
||||
if(eventId!=null)
|
||||
{
|
||||
try
|
||||
|
@@ -38,6 +38,7 @@ 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.search.SearchService;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.cmr.version.VersionService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
@@ -62,12 +63,11 @@ public class PublishingRootObject
|
||||
private VersionService versionService;
|
||||
private TransferManifestNodeFactory transferManifestNodeFactory;
|
||||
private RetryingTransactionHelper retryingTransactionHelper;
|
||||
// private TenantAdminService tenantAdminService;
|
||||
private PermissionService permissionService;
|
||||
|
||||
private StoreRef publishingStore;
|
||||
private String publishingRootPath;
|
||||
|
||||
// private Map<String, Environment> environments = new HashMap<String, Environment>();
|
||||
|
||||
/**
|
||||
* @return the approprieate {@link Environment} for the current domain.
|
||||
@@ -75,15 +75,6 @@ public class PublishingRootObject
|
||||
*/
|
||||
public Environment getEnvironment() throws BeansException
|
||||
{
|
||||
// String tenantDomain = tenantAdminService.getCurrentUserDomain();
|
||||
// Environment environment = environments.get(tenantDomain);
|
||||
// if(environment != null)
|
||||
// {
|
||||
// return environment;
|
||||
// }
|
||||
// environment = createEnvironment();
|
||||
// environments.put(tenantDomain, environment);
|
||||
// return environment;
|
||||
return createEnvironment();
|
||||
}
|
||||
|
||||
@@ -145,6 +136,7 @@ public class PublishingRootObject
|
||||
ASSOC_PUBLISHING_QUEUE,
|
||||
QName.createQName(NAMESPACE, "publishingQueue"),
|
||||
TYPE_PUBLISHING_QUEUE).getChildRef();
|
||||
permissionService.setPermission(queueNode, PermissionService.ALL_AUTHORITIES, PermissionService.ADD_CHILDREN, true);
|
||||
}
|
||||
return queueNode;
|
||||
}
|
||||
@@ -228,14 +220,6 @@ public class PublishingRootObject
|
||||
this.searchService = searchService;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @param tenantAdminService the tenantAdminService to set
|
||||
// */
|
||||
// public void setTenantAdminService(TenantAdminService tenantAdminService)
|
||||
// {
|
||||
// this.tenantAdminService = tenantAdminService;
|
||||
// }
|
||||
|
||||
/**
|
||||
* @param transferManifestNodeFactory the transferManifestNodeFactory to set
|
||||
*/
|
||||
@@ -251,4 +235,12 @@ public class PublishingRootObject
|
||||
{
|
||||
this.versionService = versionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param permissionService the permissionService to set
|
||||
*/
|
||||
public void setPermissionService(PermissionService permissionService)
|
||||
{
|
||||
this.permissionService = permissionService;
|
||||
}
|
||||
}
|
@@ -41,7 +41,6 @@ public class PublishingRootObjectTest extends AbstractPublishingIntegrationTest
|
||||
{
|
||||
super.onSetUp();
|
||||
this.rootObject = (PublishingRootObject) getApplicationContext().getBean(PublishingRootObject.NAME);
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@@ -42,7 +42,7 @@ public interface PublishingQueue
|
||||
* @param channelId The name of the channel that the package is to be published to
|
||||
* @param schedule The time at which the new publishing event should be scheduled (optional - <code>null</code> indicates "as soon as possible")
|
||||
* @param comment A comment to be stored with this new event (optional - may be <code>null</code>)
|
||||
* @param statusUpdate TODO
|
||||
* @param statusUpdate defines the status update (if any). If <code>null</code> then no status update is sent.
|
||||
* @return The identifier of the newly scheduled event
|
||||
*/
|
||||
String scheduleNewEvent(PublishingPackage publishingPackage, String channelId, Calendar schedule, String comment, StatusUpdate statusUpdate);
|
||||
|
Reference in New Issue
Block a user