Merged HEAD-BUG-FIX (5.1/Cloud) to HEAD (5.0/Cloud)

85943: Merged V4.2-BUG-FIX (4.2.4) to HEAD-BUG-FIX (5.0/Cloud)
      85883: Merged DEV to V4.2-BUG-FIX (4.2.4)
         85645 : MNT-12382 : No access to process items of (unclaimed) pooled group task via Activiti REST API if user being member of assigned candidate group is not in administrators group
            - Add unit test
         85718 : MNT-12382 : No access to process items of (unclaimed) pooled group task via Activiti REST API if user being member of assigned candidate group is not in administrators group
            - Add check for unclaimed process
            - Add unit test
         85771 : MNT-12382 : No access to process items of (unclaimed) pooled group task via Activiti REST API if user being member of assigned candidate group is not in administrators group
            - Added check for membership in the assigned group for unclaimed pooled workflow


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@94521 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Alan Davis
2015-01-31 09:35:20 +00:00
parent dcb6c94e32
commit cee8cc5346
2 changed files with 142 additions and 1 deletions

View File

@@ -17,6 +17,7 @@ import org.activiti.engine.ProcessEngine;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricTaskInstanceQuery;
import org.activiti.engine.history.HistoricVariableInstance;
import org.activiti.engine.task.Task;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.dictionary.constraint.ListOfValuesConstraint;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
@@ -50,6 +51,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.security.AuthorityService;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.apache.commons.beanutils.ConversionException;
@@ -493,13 +495,26 @@ public class WorkflowRestImpl
return variableInstances;
}
if (authorityService.isAdminAuthority(AuthenticationUtil.getRunAsUser()))
String username = AuthenticationUtil.getRunAsUser();
if (authorityService.isAdminAuthority(username))
{
// Admin is allowed to read all processes in the current tenant
return variableInstances;
}
else
{
// MNT-12382 check for membership in the assigned group
ActivitiScriptNode group = (ActivitiScriptNode) variableMap.get("bpm_groupAssignee");
if (group != null)
{
// check that the process is unclaimed
Task task = activitiProcessEngine.getTaskService().createTaskQuery().processInstanceId(processId).singleResult();
if ((task != null) && (task.getAssignee() == null) && isUserInGroup(username, group.getNodeRef()))
{
return variableInstances;
}
}
// If non-admin user, involvement in the task is required (either owner, assignee or externally involved).
HistoricTaskInstanceQuery query = activitiProcessEngine.getHistoryService()
.createHistoricTaskInstanceQuery()
@@ -550,4 +565,16 @@ public class WorkflowRestImpl
{
this.activitiWorkflowEngine = activitiWorkflowEngine;
}
private boolean isUserInGroup(String username, NodeRef group)
{
// Get the group name
String groupName = (String) nodeService.getProperty(group, ContentModel.PROP_AUTHORITY_NAME);
// Get all group members
Set<String> groupMembers = authorityService.getContainedAuthorities(AuthorityType.USER, groupName, false);
// Check if the user is a group member.
return (groupMembers != null) && groupMembers.contains(username);
}
}

View File

@@ -24,24 +24,33 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.task.Task;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.tenant.TenantUtil;
import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.workflow.activiti.ActivitiScriptNode;
import org.alfresco.rest.api.tests.PersonInfo;
import org.alfresco.rest.api.tests.RepoService.TestNetwork;
import org.alfresco.rest.api.tests.RepoService.TestPerson;
import org.alfresco.rest.api.tests.RepoService.TestSite;
import org.alfresco.rest.api.tests.client.HttpResponse;
import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse;
import org.alfresco.rest.api.tests.client.PublicApiException;
import org.alfresco.rest.api.tests.client.RequestContext;
import org.alfresco.rest.api.tests.client.data.Document;
import org.alfresco.rest.api.tests.client.data.MemberOfSite;
import org.alfresco.rest.api.tests.client.data.SiteRole;
import org.alfresco.rest.workflow.api.model.ProcessInfo;
import org.alfresco.rest.workflow.api.model.Variable;
import org.alfresco.rest.workflow.api.tests.WorkflowApiClient.ProcessesClient;
@@ -49,6 +58,7 @@ import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.test_category.OwnJVMTestsCategory;
import org.alfresco.util.ISO8601DateFormat;
import org.alfresco.util.Pair;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.junit.experimental.categories.Category;
@@ -1285,6 +1295,110 @@ public class ProcessWorkflowApiTest extends EnterpriseWorkflowTestApi
}
}
@Test
public void testMNT12382() throws Exception
{
currentNetwork = getTestFixture().getRandomNetwork();
TestPerson initiator = currentNetwork.getPeople().get(0);
RequestContext requestContext = new RequestContext(currentNetwork.getId(), initiator.getId());
publicApiClient.setRequestContext(requestContext);
ProcessInfo processInfo = startReviewPooledProcess(requestContext);
final List<TestPerson> persons = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<List<TestPerson>>()
{
@SuppressWarnings("synthetic-access")
public List<TestPerson> execute() throws Throwable
{
ArrayList<TestPerson> persons = new ArrayList<TestPerson>();
persons.add(currentNetwork.createUser(new PersonInfo("Maxim0", "Bobyleu0", "maxim0.bobyleu0", "password", null, "skype", "location", "telephone", "mob", "instant", "google")));
persons.add(currentNetwork.createUser(new PersonInfo("Maxim1", "Bobyleu1", "maxim1.bobyleu1", "password", null, "skype", "location", "telephone", "mob", "instant", "google")));
persons.add(currentNetwork.createUser(new PersonInfo("Maxim2", "Bobyleu2", "maxim2.bobyleu2", "password", null, "skype", "location", "telephone", "mob", "instant", "google")));
return persons;
}
}, false, true);
final MemberOfSite memberOfSite = currentNetwork.getSiteMemberships(initiator.getId()).get(0);
// startReviewPooledProcess() uses initiator's site id and role name for construct bpm_groupAssignee, thus we need appropriate things for created users
transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>()
{
public Void execute() throws Throwable
{
TenantUtil.runAsUserTenant(new TenantRunAsWork<Void>()
{
@Override
public Void doWork() throws Exception
{
TestSite initiatorSite = (TestSite) memberOfSite.getSite();
initiatorSite.inviteToSite(persons.get(0).getId(), memberOfSite.getRole());
initiatorSite.inviteToSite(persons.get(1).getId(), memberOfSite.getRole());
// this user wouldn't be in group
initiatorSite.inviteToSite(persons.get(2).getId(), SiteRole.SiteConsumer == memberOfSite.getRole() ? SiteRole.SiteCollaborator : SiteRole.SiteConsumer);
return null;
}
}, AuthenticationUtil.getAdminUserName(), currentNetwork.getId());
return null;
}
}, false, true);
String processId = processInfo.getId();
// getting process items by workflow initiator
ProcessesClient processesClient = publicApiClient.processesClient();
JSONObject initiatorItems = processesClient.findProcessItems(processId);
// getting unclaimed process items by user in group
requestContext = new RequestContext(currentNetwork.getId(), persons.get(0).getId());
publicApiClient.setRequestContext(requestContext);
JSONObject items1 = processesClient.findProcessItems(processId);
assertEquals(initiatorItems.toJSONString(), items1.toJSONString());
// getting unclaimed process items by user not in group
requestContext = new RequestContext(currentNetwork.getId(), persons.get(2).getId());
publicApiClient.setRequestContext(requestContext);
try
{
JSONObject items2 = processesClient.findProcessItems(processId);
fail("User not from group should not see items.");
}
catch (PublicApiException e)
{
// expected
assertEquals(403, e.getHttpResponse().getStatusCode());
}
// claim task
TaskService taskService = activitiProcessEngine.getTaskService();
Task task = taskService.createTaskQuery().processInstanceId(processId).singleResult();
TestPerson assignee = persons.get(1);
taskService.setAssignee(task.getId(), assignee.getId());
// getting claimed process items by assignee
requestContext = new RequestContext(currentNetwork.getId(), assignee.getId());
publicApiClient.setRequestContext(requestContext);
JSONObject items3 = processesClient.findProcessItems(processId);
assertEquals(initiatorItems.toJSONString(), items3.toJSONString());
// getting claimed process items by user in group
requestContext = new RequestContext(currentNetwork.getId(), persons.get(0).getId());
publicApiClient.setRequestContext(requestContext);
try
{
JSONObject items4 = processesClient.findProcessItems(processId);
fail("User from group should not see items for claimed task by another user.");
}
catch (PublicApiException e)
{
// expected
assertEquals(403, e.getHttpResponse().getStatusCode());
}
finally
{
cleanupProcessInstance(processId);
}
}
@Test
public void testGetProcessItems() throws Exception
{