Search in sources :

Example 1 with PermissionDeniedException

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;
}
Also used : InvalidArgumentException(org.alfresco.rest.framework.core.exceptions.InvalidArgumentException) TaskQuery(org.activiti.engine.task.TaskQuery) ArrayList(java.util.ArrayList) PermissionDeniedException(org.alfresco.rest.framework.core.exceptions.PermissionDeniedException) EntityNotFoundException(org.alfresco.rest.framework.core.exceptions.EntityNotFoundException)

Example 2 with PermissionDeniedException

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;
}
Also used : Task(org.alfresco.rest.workflow.api.model.Task) TaskStateTransition(org.alfresco.rest.workflow.api.model.TaskStateTransition) UnsupportedResourceOperationException(org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException) HashMap(java.util.HashMap) TaskVariable(org.alfresco.rest.workflow.api.model.TaskVariable) EntityNotFoundException(org.alfresco.rest.framework.core.exceptions.EntityNotFoundException) IdentityLink(org.activiti.engine.task.IdentityLink) ConstraintViolatedException(org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException) PermissionDeniedException(org.alfresco.rest.framework.core.exceptions.PermissionDeniedException) EntityNotFoundException(org.alfresco.rest.framework.core.exceptions.EntityNotFoundException) UnsupportedResourceOperationException(org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException) ActivitiTaskAlreadyClaimedException(org.activiti.engine.ActivitiTaskAlreadyClaimedException) ConstraintViolatedException(org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException) InvalidQNameException(org.alfresco.service.namespace.InvalidQNameException) InvalidArgumentException(org.alfresco.rest.framework.core.exceptions.InvalidArgumentException) ActivitiTaskAlreadyClaimedException(org.activiti.engine.ActivitiTaskAlreadyClaimedException) InvalidArgumentException(org.alfresco.rest.framework.core.exceptions.InvalidArgumentException) TaskQuery(org.activiti.engine.task.TaskQuery) PermissionDeniedException(org.alfresco.rest.framework.core.exceptions.PermissionDeniedException) HashSet(java.util.HashSet)

Example 3 with PermissionDeniedException

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;
}
Also used : HistoricTaskInstance(org.activiti.engine.history.HistoricTaskInstance) PermissionDeniedException(org.alfresco.rest.framework.core.exceptions.PermissionDeniedException) EntityNotFoundException(org.alfresco.rest.framework.core.exceptions.EntityNotFoundException) HistoricTaskInstanceQuery(org.activiti.engine.history.HistoricTaskInstanceQuery)

Example 4 with PermissionDeniedException

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;
}
Also used : Task(org.activiti.engine.task.Task) HistoricTaskInstance(org.activiti.engine.history.HistoricTaskInstance) HashMap(java.util.HashMap) EntityNotFoundException(org.alfresco.rest.framework.core.exceptions.EntityNotFoundException) HistoricTaskInstanceQuery(org.activiti.engine.history.HistoricTaskInstanceQuery) NodeRef(org.alfresco.service.cmr.repository.NodeRef) ActivitiScriptNode(org.alfresco.repo.workflow.activiti.ActivitiScriptNode) HistoricVariableInstance(org.activiti.engine.history.HistoricVariableInstance) PermissionDeniedException(org.alfresco.rest.framework.core.exceptions.PermissionDeniedException)

Example 5 with PermissionDeniedException

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);
    }
}
Also used : RestoreNodeReport(org.alfresco.repo.node.archive.RestoreNodeReport) NodeRef(org.alfresco.service.cmr.repository.NodeRef) QName(org.alfresco.service.namespace.QName) IntegrityException(org.alfresco.repo.node.integrity.IntegrityException) EntityNotFoundException(org.alfresco.rest.framework.core.exceptions.EntityNotFoundException) NotFoundException(org.alfresco.rest.framework.core.exceptions.NotFoundException) PermissionDeniedException(org.alfresco.rest.framework.core.exceptions.PermissionDeniedException) EntityNotFoundException(org.alfresco.rest.framework.core.exceptions.EntityNotFoundException) ConstraintViolatedException(org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException) ApiException(org.alfresco.rest.framework.core.exceptions.ApiException)

Aggregations

PermissionDeniedException (org.alfresco.rest.framework.core.exceptions.PermissionDeniedException)27 EntityNotFoundException (org.alfresco.rest.framework.core.exceptions.EntityNotFoundException)16 InvalidArgumentException (org.alfresco.rest.framework.core.exceptions.InvalidArgumentException)14 NodeRef (org.alfresco.service.cmr.repository.NodeRef)13 ConstraintViolatedException (org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException)12 HashMap (java.util.HashMap)6 NotFoundException (org.alfresco.rest.framework.core.exceptions.NotFoundException)6 QName (org.alfresco.service.namespace.QName)6 Serializable (java.io.Serializable)5 ArrayList (java.util.ArrayList)5 IntegrityException (org.alfresco.repo.node.integrity.IntegrityException)5 UnknownAuthorityException (org.alfresco.repo.security.authority.UnknownAuthorityException)4 UnsupportedResourceOperationException (org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException)4 HashSet (java.util.HashSet)3 AuthenticationException (org.alfresco.repo.security.authentication.AuthenticationException)3 AccessDeniedException (org.alfresco.repo.security.permissions.AccessDeniedException)3 Collator (java.text.Collator)2 AbstractList (java.util.AbstractList)2 Arrays (java.util.Arrays)2 Collections (java.util.Collections)2