use of org.alfresco.rest.framework.core.exceptions.PermissionDeniedException in project alfresco-remote-api by Alfresco.
the class TasksImpl method getValidTask.
/**
* Get a valid {@link org.activiti.engine.task.Task} based on the given task id. Checks if current logged
* in user is assignee/owner/involved with the task. In case true was passed for "validIfClaimable",
* the task is also valid if the current logged in user is a candidate for claiming the task.
*
* @throws EntityNotFoundException when the task was not found
* @throws PermissionDeniedException when the current logged in user isn't allowed to access task.
*/
protected org.activiti.engine.task.Task getValidTask(String taskId) {
if (taskId == null) {
throw new InvalidArgumentException("Task id is required.");
}
TaskQuery query = activitiProcessEngine.getTaskService().createTaskQuery().taskId(taskId);
if (authorityService.isAdminAuthority(AuthenticationUtil.getRunAsUser())) {
// Admin is allowed to read all tasks in the current tenant
if (tenantService.isEnabled()) {
query.processVariableValueEquals(ActivitiConstants.VAR_TENANT_DOMAIN, TenantUtil.getCurrentDomain());
}
} else {
// If non-admin user, involvement in the task is required (either owner, assignee or externally involved).
query.taskInvolvedUser(AuthenticationUtil.getRunAsUser());
}
org.activiti.engine.task.Task taskInstance = query.singleResult();
if (taskInstance == null) {
// Either the task doesn't exist or the user is not involved directly. We can differentiate by
// checking if the task exists without applying the additional filtering
taskInstance = activitiProcessEngine.getTaskService().createTaskQuery().taskId(taskId).singleResult();
if (taskInstance == null) {
// Full error message will be "Task with id: 'id' was not found"
throw new EntityNotFoundException(taskId);
} else {
// Task is not yet finished, so potentially claimable. If user is part of a "candidateGroup", the task is accessible to the
// user regardless of not being involved/owner/assignee
boolean isTaskClaimable = activitiProcessEngine.getTaskService().createTaskQuery().taskCandidateGroupIn(new ArrayList<String>(authorityService.getAuthoritiesForUser(AuthenticationUtil.getRunAsUser()))).taskId(taskId).count() == 1;
if (isTaskClaimable == false) {
throw new PermissionDeniedException();
}
}
}
return taskInstance;
}
use of org.alfresco.rest.framework.core.exceptions.PermissionDeniedException in project alfresco-remote-api by Alfresco.
the class TasksImpl method update.
@Override
public Task update(String taskId, Task task, Parameters parameters) {
TaskStateTransition taskAction = null;
List<String> selectedProperties = parameters.getSelectedProperties();
if (selectedProperties.contains("state")) {
taskAction = TaskStateTransition.getTaskActionFromString(task.getState());
}
// Fetch the task unfiltered, we check authorization below
TaskQuery query = activitiProcessEngine.getTaskService().createTaskQuery().taskId(taskId);
org.activiti.engine.task.Task taskInstance = query.singleResult();
if (taskInstance == null) {
// Check if task exists in history, to be able to return appropriate error when trying to update an
// existing completed task vs. an unexisting task vs. unauthorized
boolean taskHasExisted = activitiProcessEngine.getHistoryService().createHistoricTaskInstanceQuery().taskId(taskId).count() > 0;
if (taskHasExisted) {
throw new UnsupportedResourceOperationException("Task with id: " + taskId + " cannot be updated, it's completed");
} else {
throw new EntityNotFoundException(taskId);
}
} else {
String user = AuthenticationUtil.getRunAsUser();
// Check if user is either assignee, owner or admin
boolean authorized = authorityService.isAdminAuthority(user) || user.equals(taskInstance.getOwner()) || user.equals(taskInstance.getAssignee());
Set<String> candidateGroups = new HashSet<String>();
if (!authorized) {
// Check if user is initiator of the process this task is involved with
List<IdentityLink> linksForTask = activitiProcessEngine.getTaskService().getIdentityLinksForTask(taskId);
// the identity-links, there is no reason why we should check candidate using a DB-query
for (IdentityLink link : linksForTask) {
if (user.equals(link.getUserId()) && IdentityLinkType.STARTER.equals(link.getType())) {
authorized = true;
break;
}
// MNT-13276
if ((taskInstance.getAssignee() == null) && (link.getGroupId() != null) && link.getType().equals(IdentityLinkType.CANDIDATE)) {
Set<String> userGroups = authorityService.getAuthoritiesForUser(user);
if (userGroups.contains(link.getGroupId())) {
authorized = true;
break;
}
}
if (taskAction == TaskStateTransition.CLAIMED && link.getGroupId() != null && link.getType().equals(IdentityLinkType.CANDIDATE)) {
candidateGroups.add(link.getGroupId());
}
if (taskAction == TaskStateTransition.CLAIMED && link.getUserId() != null && link.getType().equals(IdentityLinkType.CANDIDATE) && user.equals(link.getUserId())) {
// User is a direct candidate for the task, authorized to claim
authorized = true;
break;
}
}
}
// When claiming, a limited update (set assignee through claim) is allowed
if (!authorized && taskAction == TaskStateTransition.CLAIMED) {
Set<String> userGroups = authorityService.getAuthoritiesForUser(user);
for (String group : candidateGroups) {
if (userGroups.contains(group)) {
authorized = true;
break;
}
}
}
if (!authorized) {
// None of the above conditions are met, not authorized to update task
throw new PermissionDeniedException();
}
}
// Update fields if no action is required
if (taskAction == null) {
// Only update task in Activiti API if actual properties are changed
if (updateTaskProperties(selectedProperties, task, taskInstance)) {
activitiProcessEngine.getTaskService().saveTask(taskInstance);
}
} else {
// Perform actions associated to state transition
if (taskAction != null) {
// look for variables submitted with task action
Map<String, Object> globalVariables = new HashMap<String, Object>();
Map<String, Object> localVariables = new HashMap<String, Object>();
if (selectedProperties.contains("variables") && task.getVariables() != null && task.getVariables().size() > 0) {
for (TaskVariable taskVariable : task.getVariables()) {
taskVariable = convertToTypedVariable(taskVariable, taskInstance);
if (taskVariable.getVariableScope() == VariableScope.GLOBAL) {
globalVariables.put(taskVariable.getName(), taskVariable.getValue());
} else {
localVariables.put(taskVariable.getName(), taskVariable.getValue());
}
}
}
switch(taskAction) {
case CLAIMED:
try {
activitiProcessEngine.getTaskService().claim(taskId, AuthenticationUtil.getRunAsUser());
} catch (ActivitiTaskAlreadyClaimedException atace) {
throw new ConstraintViolatedException("The task is already claimed by another user.");
}
break;
case COMPLETED:
if (localVariables.size() > 0) {
activitiProcessEngine.getTaskService().setVariablesLocal(taskId, localVariables);
}
setOutcome(taskId);
if (globalVariables.size() > 0) {
activitiProcessEngine.getTaskService().complete(taskId, globalVariables);
} else {
activitiProcessEngine.getTaskService().complete(taskId);
}
break;
case DELEGATED:
if (selectedProperties.contains("assignee") && task.getAssignee() != null) {
if (taskInstance.getAssignee() == null || !taskInstance.getAssignee().equals(AuthenticationUtil.getRunAsUser())) {
// Alter assignee before delegating to preserve trail of who actually delegated
activitiProcessEngine.getTaskService().setAssignee(taskId, AuthenticationUtil.getRunAsUser());
}
activitiProcessEngine.getTaskService().delegateTask(taskId, task.getAssignee());
} else {
throw new InvalidArgumentException("When delegating a task, assignee should be selected and provided in the request.");
}
break;
case RESOLVED:
if (localVariables.size() > 0) {
activitiProcessEngine.getTaskService().setVariablesLocal(taskId, localVariables);
}
setOutcome(taskId);
if (globalVariables.size() > 0) {
activitiProcessEngine.getTaskService().resolveTask(taskId, globalVariables);
} else {
activitiProcessEngine.getTaskService().resolveTask(taskId);
}
break;
case UNCLAIMED:
activitiProcessEngine.getTaskService().setAssignee(taskId, null);
break;
}
}
}
Task responseTask = new Task(activitiProcessEngine.getHistoryService().createHistoricTaskInstanceQuery().taskId(taskId).singleResult());
// if the task is not ended the task state might be pending or resolved
if (responseTask.getEndedAt() == null) {
try {
org.activiti.engine.task.Task runningTask = activitiProcessEngine.getTaskService().createTaskQuery().taskId(taskId).singleResult();
if (runningTask != null) {
if (runningTask.getDelegationState() == DelegationState.PENDING) {
responseTask.setState(TaskStateTransition.DELEGATED.name().toLowerCase());
} else if (runningTask.getDelegationState() == DelegationState.RESOLVED) {
responseTask.setState(TaskStateTransition.RESOLVED.name().toLowerCase());
}
}
} catch (Exception e) {
// ignore the exception
}
}
return responseTask;
}
use of org.alfresco.rest.framework.core.exceptions.PermissionDeniedException in project alfresco-remote-api by Alfresco.
the class TasksImpl method getValidHistoricTask.
/**
* Get a valid {@link HistoricTaskInstance} based on the given task id. Checks if current logged
* in user is assignee/owner/involved with the task. In case true was passed for "validIfClaimable",
* the task is also valid if the current logged in user is a candidate for claiming the task.
*
* @throws EntityNotFoundException when the task was not found
* @throws PermissionDeniedException when the current logged in user isn't allowed to access task.
*/
protected HistoricTaskInstance getValidHistoricTask(String taskId) {
HistoricTaskInstanceQuery query = activitiProcessEngine.getHistoryService().createHistoricTaskInstanceQuery().taskId(taskId);
if (authorityService.isAdminAuthority(AuthenticationUtil.getRunAsUser())) {
// Admin is allowed to read all tasks in the current tenant
if (tenantService.isEnabled()) {
query.processVariableValueEquals(ActivitiConstants.VAR_TENANT_DOMAIN, TenantUtil.getCurrentDomain());
}
} else {
// If non-admin user, involvement in the task is required (either owner, assignee or externally involved).
query.taskInvolvedUser(AuthenticationUtil.getRunAsUser());
}
HistoricTaskInstance taskInstance = query.singleResult();
if (taskInstance == null) {
// Either the task doesn't exist or the user is not involved directly. We can differentiate by
// checking if the task exists without applying the additional filtering
taskInstance = activitiProcessEngine.getHistoryService().createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
if (taskInstance == null) {
// Full error message will be "Task with id: 'id' was not found"
throw new EntityNotFoundException(taskId);
} else {
boolean isTaskClaimable = false;
if (taskInstance.getEndTime() == null) {
// Task is not yet finished, so potentially claimable. If user is part of a "candidateGroup", the task is accessible to the
// user regardless of not being involved/owner/assignee
isTaskClaimable = activitiProcessEngine.getTaskService().createTaskQuery().taskCandidateGroupIn(new ArrayList<String>(authorityService.getAuthoritiesForUser(AuthenticationUtil.getRunAsUser()))).taskId(taskId).count() == 1;
}
if (isTaskClaimable == false) {
throw new PermissionDeniedException();
}
}
}
return taskInstance;
}
use of org.alfresco.rest.framework.core.exceptions.PermissionDeniedException in project alfresco-remote-api by Alfresco.
the class WorkflowRestImpl method validateIfUserAllowedToWorkWithProcess.
/**
* Validates if the logged in user is allowed to get information about a specific process instance.
* If the user is not allowed an exception is thrown.
*
* @param processId identifier of the process instance
*/
protected List<HistoricVariableInstance> validateIfUserAllowedToWorkWithProcess(String processId) {
List<HistoricVariableInstance> variableInstances = activitiProcessEngine.getHistoryService().createHistoricVariableInstanceQuery().processInstanceId(processId).list();
Map<String, Object> variableMap = new HashMap<String, Object>();
if (variableInstances != null && variableInstances.size() > 0) {
for (HistoricVariableInstance variableInstance : variableInstances) {
variableMap.put(variableInstance.getVariableName(), variableInstance.getValue());
}
} else {
throw new EntityNotFoundException(processId);
}
if (tenantService.isEnabled()) {
String tenantDomain = (String) variableMap.get(ActivitiConstants.VAR_TENANT_DOMAIN);
if (TenantUtil.getCurrentDomain().equals(tenantDomain) == false) {
throw new PermissionDeniedException("Process is running in another tenant");
}
}
// MNT-17918 - required for initiator variable already updated as NodeRef type
Object initiator = variableMap.get(WorkflowConstants.PROP_INITIATOR);
String nodeId = ((initiator instanceof ActivitiScriptNode) ? ((ActivitiScriptNode) initiator).getNodeRef().getId() : ((NodeRef) initiator).getId());
if (initiator != null && AuthenticationUtil.getRunAsUser().equals(nodeId)) {
// user is allowed
return variableInstances;
}
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().processInstanceId(processId).taskInvolvedUser(AuthenticationUtil.getRunAsUser());
List<HistoricTaskInstance> taskList = query.list();
if (org.apache.commons.collections.CollectionUtils.isEmpty(taskList)) {
throw new PermissionDeniedException("user is not allowed to access information about process " + processId);
}
}
return variableInstances;
}
use of org.alfresco.rest.framework.core.exceptions.PermissionDeniedException in project alfresco-remote-api by Alfresco.
the class DeletedNodesImpl method restoreArchivedNode.
@Override
public Node restoreArchivedNode(String archivedId, NodeTargetAssoc nodeTargetAssoc) {
// First check the node is valid and has been archived.
NodeRef validatedNodeRef = nodes.validateNode(StoreRef.STORE_REF_ARCHIVE_SPACESSTORE, archivedId);
RestoreNodeReport restored = null;
if (nodeTargetAssoc != null) {
NodeRef targetNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, nodeTargetAssoc.getTargetParentId());
QName assocType = nodes.getAssocType(nodeTargetAssoc.getAssocType());
restored = nodeArchiveService.restoreArchivedNode(validatedNodeRef, targetNodeRef, assocType, null);
} else {
restored = nodeArchiveService.restoreArchivedNode(validatedNodeRef);
}
switch(restored.getStatus()) {
case SUCCESS:
return nodes.getFolderOrDocumentFullInfo(restored.getRestoredNodeRef(), null, null, null, null);
case FAILURE_PERMISSION:
throw new PermissionDeniedException();
case FAILURE_INTEGRITY:
throw new IntegrityException("Restore failed due to an integrity error", null);
case FAILURE_DUPLICATE_CHILD_NODE_NAME:
throw new ConstraintViolatedException("Name already exists in target");
case FAILURE_INVALID_ARCHIVE_NODE:
throw new EntityNotFoundException(archivedId);
case FAILURE_INVALID_PARENT:
throw new NotFoundException("Invalid parent id " + restored.getTargetParentNodeRef());
default:
throw new ApiException("Unable to restore node " + archivedId);
}
}
Aggregations