mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
- Added isTaskEditable, isTaskReassignable, isTaskClaimable and isTaskReleasable to WorkflowService
- Added isEditable, isReassignable, isClaimable and isReleasable flags to task model in REST API - Added outcome property to task model in REST API (label instead of raw value) - Change "definitionTypeTitle" property to "type" and fixed up fallout - Changed UI to use the isXXX flags above rather than copious amount of repeated checks - Updated workflow details page to use outcome label, isEditable flag and some changes following discussion with Linton - Added tests git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@21890 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -30,6 +30,8 @@ inwf_invite-workflow-model.property.inwf_inviteeRole.title=Invitee Role
|
|||||||
# Invite Process Definitions
|
# Invite Process Definitions
|
||||||
inwf_invitation-nominated.node.start.title=Start
|
inwf_invitation-nominated.node.start.title=Start
|
||||||
inwf_invitation-nominated.node.start.description=Send an invitation
|
inwf_invitation-nominated.node.start.description=Send an invitation
|
||||||
|
inwf_invitation-nominated.node.start.transition.sendInvite.title=Send Invite
|
||||||
|
inwf_invitation-nominated.node.start.transition.sendInvite.description=Send Invite
|
||||||
|
|
||||||
inwf_invitation-nominated.node.invitePending.title=Invite Pending
|
inwf_invitation-nominated.node.invitePending.title=Invite Pending
|
||||||
inwf_invitation-nominated.node.invitePending.description=Invite Pending
|
inwf_invitation-nominated.node.invitePending.description=Invite Pending
|
||||||
|
@@ -57,6 +57,7 @@ public interface WorkflowModel
|
|||||||
static final QName PROP_PACKAGE_ACTION_GROUP = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "packageActionGroup");
|
static final QName PROP_PACKAGE_ACTION_GROUP = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "packageActionGroup");
|
||||||
static final QName PROP_PACKAGE_ITEM_ACTION_GROUP = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "packageItemActionGroup");
|
static final QName PROP_PACKAGE_ITEM_ACTION_GROUP = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "packageItemActionGroup");
|
||||||
static final QName PROP_HIDDEN_TRANSITIONS = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "hiddenTransitions");
|
static final QName PROP_HIDDEN_TRANSITIONS = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "hiddenTransitions");
|
||||||
|
static final QName PROP_REASSIGNABLE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "reassignable");
|
||||||
static final QName ASSOC_PACKAGE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "package");
|
static final QName ASSOC_PACKAGE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "package");
|
||||||
|
|
||||||
// workflow task contstants
|
// workflow task contstants
|
||||||
|
@@ -22,6 +22,7 @@ package org.alfresco.repo.workflow;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -647,6 +648,121 @@ public class WorkflowServiceImpl implements WorkflowService
|
|||||||
return component.endTask(taskId, transition);
|
return component.endTask(taskId, transition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.alfresco.service.cmr.workflow.WorkflowService#isTaskEditable(org.alfresco.service.cmr.workflow.WorkflowTask, java.lang.String)
|
||||||
|
*/
|
||||||
|
public boolean isTaskEditable(WorkflowTask task, String username)
|
||||||
|
{
|
||||||
|
// if the task is complete it is not editable
|
||||||
|
if (task.getState() == WorkflowTaskState.COMPLETED)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isUserOwnerOrInitiator(task, username))
|
||||||
|
{
|
||||||
|
// editable if the current user is the task owner or initiator
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the current user is not the owner or initiator check whether they are
|
||||||
|
// a member of the pooled actors for the task (if it has any)
|
||||||
|
return isUserInPooledActors(task, username);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.alfresco.service.cmr.workflow.WorkflowService#isTaskReassignable(org.alfresco.service.cmr.workflow.WorkflowTask, java.lang.String)
|
||||||
|
*/
|
||||||
|
public boolean isTaskReassignable(WorkflowTask task, String username)
|
||||||
|
{
|
||||||
|
// if the task is complete it is not reassignable
|
||||||
|
if (task.getState() == WorkflowTaskState.COMPLETED)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the task has the 'reassignable' property set to false it can not be reassigned
|
||||||
|
Map<QName, Serializable> properties = task.getProperties();
|
||||||
|
Boolean reassignable = (Boolean)properties.get(WorkflowModel.PROP_REASSIGNABLE);
|
||||||
|
if (reassignable != null && reassignable.booleanValue() == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the task has pooled actors and an owner it can not be reassigned (it must be released)
|
||||||
|
Collection<?> actors = (Collection<?>) properties.get(WorkflowModel.ASSOC_POOLED_ACTORS);
|
||||||
|
String owner = (String)properties.get(ContentModel.PROP_OWNER);
|
||||||
|
if (actors != null && !actors.isEmpty() && owner != null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isUserOwnerOrInitiator(task, username))
|
||||||
|
{
|
||||||
|
// reassignable if the current user is the task owner or initiator
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.alfresco.service.cmr.workflow.WorkflowService#isTaskClaimable(org.alfresco.service.cmr.workflow.WorkflowTask, java.lang.String)
|
||||||
|
*/
|
||||||
|
public boolean isTaskClaimable(WorkflowTask task, String username)
|
||||||
|
{
|
||||||
|
// if the task is complete it is not claimable
|
||||||
|
if (task.getState() == WorkflowTaskState.COMPLETED)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the task has an owner it can not be claimed
|
||||||
|
if (task.getProperties().get(ContentModel.PROP_OWNER) != null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// a task can only be claimed if the user is a member of
|
||||||
|
// of the pooled actors for the task
|
||||||
|
return isUserInPooledActors(task, username);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.alfresco.service.cmr.workflow.WorkflowService#isTaskReleasable(org.alfresco.service.cmr.workflow.WorkflowTask, java.lang.String)
|
||||||
|
*/
|
||||||
|
public boolean isTaskReleasable(WorkflowTask task, String username)
|
||||||
|
{
|
||||||
|
// if the task is complete it is not releasable
|
||||||
|
if (task.getState() == WorkflowTaskState.COMPLETED)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the task doesn't have pooled actors it is not releasable
|
||||||
|
Map<QName, Serializable> properties = task.getProperties();
|
||||||
|
Collection<?> actors = (Collection<?>) properties.get(WorkflowModel.ASSOC_POOLED_ACTORS);
|
||||||
|
if (actors == null || actors.isEmpty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the task does not have an owner it is not releasable
|
||||||
|
String owner = (String)properties.get(ContentModel.PROP_OWNER);
|
||||||
|
if (owner == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isUserOwnerOrInitiator(task, username))
|
||||||
|
{
|
||||||
|
// releasable if the current user is the task owner or initiator
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see
|
* @see
|
||||||
@@ -837,4 +953,88 @@ public class WorkflowServiceImpl implements WorkflowService
|
|||||||
}
|
}
|
||||||
return contents;
|
return contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the given user is a member of the pooled actors assigned to the task
|
||||||
|
*
|
||||||
|
* @param task The task instance to check
|
||||||
|
* @param username The username to check
|
||||||
|
* @return true if the user is a pooled actor, false otherwise
|
||||||
|
*/
|
||||||
|
private boolean isUserInPooledActors(WorkflowTask task, String username)
|
||||||
|
{
|
||||||
|
// get groups that the current user has to belong (at least one of them)
|
||||||
|
final Collection<?> actors = (Collection<?>)task.getProperties().get(WorkflowModel.ASSOC_POOLED_ACTORS);
|
||||||
|
if (actors != null && !actors.isEmpty())
|
||||||
|
{
|
||||||
|
for (Object actor : actors)
|
||||||
|
{
|
||||||
|
// retrieve the name of the group
|
||||||
|
Map<QName, Serializable> props = nodeService.getProperties((NodeRef)actor);
|
||||||
|
String name = (String)props.get(ContentModel.PROP_AUTHORITY_NAME);
|
||||||
|
|
||||||
|
// retrieve the users of the group
|
||||||
|
Set<String> users = this.authorityService.getContainedAuthorities(AuthorityType.USER, name, true);
|
||||||
|
|
||||||
|
// see if the user is one of the users in the group
|
||||||
|
if (users != null && !users.isEmpty() && users.contains(username))
|
||||||
|
{
|
||||||
|
// they are a member of the group so stop looking!
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the given user is the owner of the given task or
|
||||||
|
* the initiator of the workflow the task is part of
|
||||||
|
*
|
||||||
|
* @param task The task to check
|
||||||
|
* @param username The username to check
|
||||||
|
* @return true if the user is the owner or the workflow initiator
|
||||||
|
*/
|
||||||
|
private boolean isUserOwnerOrInitiator(WorkflowTask task, String username)
|
||||||
|
{
|
||||||
|
boolean result = false;
|
||||||
|
String owner = (String)task.getProperties().get(ContentModel.PROP_OWNER);
|
||||||
|
|
||||||
|
if (username.equals(owner))
|
||||||
|
{
|
||||||
|
// user owns the task
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
else if (username.equals(getWorkflowInitiatorUsername(task)))
|
||||||
|
{
|
||||||
|
// user is the workflow initiator
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the username of the user that initiated the workflow the
|
||||||
|
* given task is part of.
|
||||||
|
*
|
||||||
|
* @param task The task to get the workflow initiator for
|
||||||
|
* @return Username or null if the initiator could not be found
|
||||||
|
*/
|
||||||
|
private String getWorkflowInitiatorUsername(WorkflowTask task)
|
||||||
|
{
|
||||||
|
String initiator = null;
|
||||||
|
|
||||||
|
NodeRef initiatorRef = task.getPath().getInstance().getInitiator();
|
||||||
|
|
||||||
|
if (initiator != null)
|
||||||
|
{
|
||||||
|
// TODO: deal with missing users!
|
||||||
|
|
||||||
|
initiator = (String)this.nodeService.getProperty(initiatorRef, ContentModel.PROP_USERNAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
return initiator;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -207,6 +207,7 @@ public interface WorkflowService
|
|||||||
*
|
*
|
||||||
* @param workflowDefinitionId the workflow definition id
|
* @param workflowDefinitionId the workflow definition id
|
||||||
* @return the list of "in-flight" workflow instances
|
* @return the list of "in-flight" workflow instances
|
||||||
|
* @since 3.4
|
||||||
*/
|
*/
|
||||||
@Auditable(parameters = {"workflowDefinitionId"})
|
@Auditable(parameters = {"workflowDefinitionId"})
|
||||||
public List<WorkflowInstance> getCompletedWorkflows(String workflowDefinitionId);
|
public List<WorkflowInstance> getCompletedWorkflows(String workflowDefinitionId);
|
||||||
@@ -216,6 +217,7 @@ public interface WorkflowService
|
|||||||
*
|
*
|
||||||
* @param workflowDefinitionId the workflow definition id
|
* @param workflowDefinitionId the workflow definition id
|
||||||
* @return the list of "in-flight" workflow instances
|
* @return the list of "in-flight" workflow instances
|
||||||
|
* @since 3.4
|
||||||
*/
|
*/
|
||||||
@Auditable(parameters = {"workflowDefinitionId"})
|
@Auditable(parameters = {"workflowDefinitionId"})
|
||||||
public List<WorkflowInstance> getWorkflows(String workflowDefinitionId);
|
public List<WorkflowInstance> getWorkflows(String workflowDefinitionId);
|
||||||
@@ -374,6 +376,49 @@ public interface WorkflowService
|
|||||||
@Auditable(parameters = {"taskId", "transitionId"})
|
@Auditable(parameters = {"taskId", "transitionId"})
|
||||||
public WorkflowTask endTask(String taskId, String transitionId);
|
public WorkflowTask endTask(String taskId, String transitionId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the given user can edit the given task
|
||||||
|
*
|
||||||
|
* @param task The task to check
|
||||||
|
* @param username The user to check
|
||||||
|
* @return true if the user can edit the task
|
||||||
|
* @since 3.4
|
||||||
|
*/
|
||||||
|
@Auditable(parameters = {"task", "username"})
|
||||||
|
public boolean isTaskEditable(WorkflowTask task, String username);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the given user can reassign the given task
|
||||||
|
*
|
||||||
|
* @param task The task to check
|
||||||
|
* @param username The user to check
|
||||||
|
* @return true if the user can reassign the task
|
||||||
|
* @since 3.4
|
||||||
|
*/
|
||||||
|
@Auditable(parameters = {"task", "username"})
|
||||||
|
public boolean isTaskReassignable(WorkflowTask task, String username);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the given user can claim the given task
|
||||||
|
*
|
||||||
|
* @param task The task to check
|
||||||
|
* @param username The user to check
|
||||||
|
* @return true if the user can claim the task
|
||||||
|
* @since 3.4
|
||||||
|
*/
|
||||||
|
@Auditable(parameters = {"task", "username"})
|
||||||
|
public boolean isTaskClaimable(WorkflowTask task, String username);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the given user can release the given task
|
||||||
|
*
|
||||||
|
* @param task The task to check
|
||||||
|
* @param username The user to check
|
||||||
|
* @return true if the user can release the task
|
||||||
|
* @since 3.4
|
||||||
|
*/
|
||||||
|
@Auditable(parameters = {"task", "username"})
|
||||||
|
public boolean isTaskReleasable(WorkflowTask task, String username);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Package Management
|
// Package Management
|
||||||
|
Reference in New Issue
Block a user