Search in sources :

Example 1 with UnsupportedResourceOperationException

use of org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException 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 2 with UnsupportedResourceOperationException

use of org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException in project alfresco-remote-api by Alfresco.

the class ResourceWebScriptGet method extractParams.

@Override
public Params extractParams(ResourceMetadata resourceMeta, WebScriptRequest req) {
    final Map<String, String> resourceVars = locator.parseTemplateVars(req.getServiceMatch().getTemplateVars());
    final String entityId = resourceVars.get(ResourceLocator.ENTITY_ID);
    final String resourceName = resourceVars.get(ResourceLocator.RELATIONSHIP_RESOURCE);
    final String relationshipId = resourceVars.get(ResourceLocator.RELATIONSHIP_ID);
    final String propertyName = resourceVars.get(ResourceLocator.PROPERTY);
    final String relationship2Id = resourceVars.get(ResourceLocator.RELATIONSHIP2_ID);
    final RecognizedParams params = getRecognizedParams(req);
    switch(resourceMeta.getType()) {
        case ENTITY:
            if (StringUtils.isNotBlank(entityId)) {
                return Params.valueOf(params, entityId, null, req);
            } else {
                // collection resource (top-level of entities)
                return Params.valueOf(params, null, null, req);
            }
        case RELATIONSHIP:
            if (StringUtils.isNotBlank(propertyName)) {
                if (StringUtils.isNotBlank(relationship2Id)) {
                    return Params.valueOf(false, entityId, relationshipId, relationship2Id, null, null, null, params, null, req);
                } else {
                    // collection resource (second level of relationship)
                    return Params.valueOf(true, entityId, relationshipId, null, null, null, null, params, null, req);
                }
            } else if (StringUtils.isNotBlank(relationshipId)) {
                return Params.valueOf(false, entityId, relationshipId, null, null, null, null, params, null, req);
            } else {
                // collection resource (first level of relationship)
                return Params.valueOf(true, entityId, null, null, null, null, null, params, null, req);
            }
        case PROPERTY:
            if (StringUtils.isNotBlank(entityId) && StringUtils.isNotBlank(resourceName)) {
                if (StringUtils.isNotBlank(propertyName)) {
                    return Params.valueOf(false, entityId, relationshipId, relationship2Id, null, null, propertyName, params, null, req);
                } else {
                    return Params.valueOf(entityId, null, null, null, resourceName, params, null, req);
                }
            }
        // Fall through to unsupported.
        default:
            throw new UnsupportedResourceOperationException("GET not supported for Actions");
    }
}
Also used : RecognizedParams(org.alfresco.rest.framework.resource.parameters.Params.RecognizedParams) UnsupportedResourceOperationException(org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException)

Example 3 with UnsupportedResourceOperationException

use of org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException in project alfresco-remote-api by Alfresco.

the class ResourceWebScriptPost method extractObjFromJson.

/**
 * If the @WebApiParam has been used and set allowMultiple to false then this will get a single entry.  It
 * should error if an array is passed in.
 * @param resourceMeta ResourceMetadata
 * @param req WebScriptRequest
 * @return Either an object
 */
private Object extractObjFromJson(ResourceMetadata resourceMeta, ResourceOperation operation, WebScriptRequest req) {
    if (operation == null) {
        return null;
    }
    Class<?> objType = resourceMeta.getObjectType(operation);
    boolean isTypeOperation = resourceMeta.getType().equals(ResourceMetadata.RESOURCE_TYPE.OPERATION);
    List<ResourceParameter> params = operation.getParameters();
    if (!params.isEmpty()) {
        for (ResourceParameter resourceParameter : params) {
            // POST to collection may or may not support List as json body, Operations don't support a List as json body
            boolean notMultiple = ((!resourceParameter.isAllowMultiple()) || isTypeOperation);
            if (ResourceParameter.KIND.HTTP_BODY_OBJECT.equals(resourceParameter.getParamType()) && notMultiple) {
                // Only allow 1 value.
                try {
                    Object jsonContent = null;
                    if (objType != null) {
                        // check if the body is optional and is not provided
                        if (!resourceParameter.isRequired() && Integer.valueOf(req.getHeader("content-length")) <= 0) {
                            // in some cases the body is optional and the json doesn't need to be extracted
                            return null;
                        } else {
                            jsonContent = extractJsonContent(req, assistant.getJsonHelper(), objType);
                        }
                    }
                    if (isTypeOperation) {
                        return jsonContent;
                    } else {
                        return Arrays.asList(jsonContent);
                    }
                } catch (InvalidArgumentException iae) {
                    if (iae.getMessage().contains("START_ARRAY") && iae.getMessage().contains("line: 1, column: 1")) {
                        throw new UnsupportedResourceOperationException("Only 1 entity is supported in the HTTP request body");
                    } else {
                        throw iae;
                    }
                }
            }
        }
    }
    if (objType == null) {
        return null;
    }
    if (isTypeOperation) {
        // Operations don't support a List as json body
        return extractJsonContent(req, assistant.getJsonHelper(), objType);
    } else {
        return extractJsonContentAsList(req, assistant.getJsonHelper(), objType);
    }
}
Also used : ResourceParameter(org.alfresco.rest.framework.core.ResourceParameter) InvalidArgumentException(org.alfresco.rest.framework.core.exceptions.InvalidArgumentException) UnsupportedResourceOperationException(org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException)

Example 4 with UnsupportedResourceOperationException

use of org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException in project alfresco-remote-api by Alfresco.

the class ParamsExtractorTests method testPostExtractor.

@SuppressWarnings("unchecked")
@Test
public void testPostExtractor() throws IOException {
    // Put together the stubs
    ResourceWebScriptPost extractor = new ResourceWebScriptPost();
    extractor.setAssistant(assistant);
    extractor.setLocator(locator);
    Map<String, String> templateVars = new HashMap<String, String>();
    Content content = mock(Content.class);
    when(content.getReader()).thenReturn(new StringReader(JsonJacksonTests.FARMER_JSON));
    WebScriptRequest request = mock(WebScriptRequest.class);
    when(request.getServiceMatch()).thenReturn(new Match(null, templateVars, null));
    when(request.getContent()).thenReturn(content);
    Params params = extractor.extractParams(mockEntity(), request);
    assertNotNull(params);
    assertNotNull(params.getFilter());
    assertTrue("Default filter is BeanPropertiesFilter.AllProperties", BeanPropertiesFilter.AllProperties.class.equals(params.getFilter().getClass()));
    Object passed = params.getPassedIn();
    assertNotNull(passed);
    assertTrue(List.class.isAssignableFrom(passed.getClass()));
    List<Object> passedObjs = (List<Object>) passed;
    assertTrue(passedObjs.size() == 1);
    assertTrue("A Farmer was passed in.", Farmer.class.equals(passedObjs.get(0).getClass()));
    // No entity id for POST
    templateVars.put(ResourceLocator.ENTITY_ID, "1234");
    try {
        params = extractor.extractParams(mockEntity(), request);
        fail("Should not get here. No entity id for POST");
    } catch (UnsupportedResourceOperationException uoe) {
        // Must throw this exception
        assertNotNull(uoe);
    }
    // reset the reader
    when(content.getReader()).thenReturn(new StringReader(JsonJacksonTests.FARMER_JSON));
    params = extractor.extractParams(mockRelationship(), request);
    assertNotNull(params);
    assertEquals("1234", params.getEntityId());
    passed = params.getPassedIn();
    assertNotNull(passed);
    passedObjs = (List<Object>) passed;
    assertTrue(passedObjs.size() == 1);
    assertTrue("A Farmer was passed in.", Farmer.class.equals(passedObjs.get(0).getClass()));
    try {
        // reset the reader
        when(content.getReader()).thenReturn(new StringReader(JsonJacksonTests.FARMER_JSON));
        templateVars.put(ResourceLocator.RELATIONSHIP_ID, "45678");
        params = extractor.extractParams(mockRelationship(), request);
        fail("Should not get here.");
    } catch (UnsupportedResourceOperationException iae) {
        // Must throw this exception
        assertNotNull("POSTING to a relationship collection by id is not correct.", iae);
    }
    templateVars.clear();
    // reset the reader
    when(content.getReader()).thenReturn(new StringReader(JsonJacksonTests.FARMER_JSON));
    templateVars.put(ResourceLocator.ENTITY_ID, "1234");
    templateVars.put(ResourceLocator.RELATIONSHIP_ID, "codfish");
    try {
        // POST does not support addressed parameters.
        params = extractor.extractParams(mockEntity(), request);
        fail("Should not get here.");
    } catch (UnsupportedResourceOperationException uoe) {
        // Must throw this exception
        assertNotNull(uoe);
    }
    testExtractOperationParams(templateVars, request, extractor);
    templateVars.clear();
    Method aMethod = ResourceInspector.findMethod(EntityResourceAction.Create.class, GrassEntityResource.class);
    ResourceOperation op = ResourceInspector.inspectOperation(GrassEntityResource.class, aMethod, HttpMethod.POST);
    List<ResourceMetadata> metainfo = ResourceInspector.inspect(GrassEntityResource.class);
    assertNotNull(op);
    assertTrue("Create method should have two params", op.getParameters().size() == 2);
    ResourceParameter singleParam = op.getParameters().get(0);
    assertTrue(ResourceParameter.KIND.HTTP_BODY_OBJECT.equals(singleParam.getParamType()));
    assertFalse("Create grass does not support multiple grass creations", singleParam.isAllowMultiple());
    assertFalse(singleParam.isRequired());
    // Test context when the request body is null and 'required' webApiParam is false
    when(request.getHeader("content-length")).thenReturn("0");
    params = extractor.extractParams(metainfo.get(0), request);
    assertNotNull(params);
    // Test context when the request body is provided and 'required' property is false
    when(content.getReader()).thenReturn(new StringReader(JsonJacksonTests.GRASS_JSON));
    params = extractor.extractParams(metainfo.get(0), request);
    assertNotNull(params);
}
Also used : WebScriptRequest(org.springframework.extensions.webscripts.WebScriptRequest) EntityResourceAction(org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction) HashMap(java.util.HashMap) UnsupportedResourceOperationException(org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException) Params(org.alfresco.rest.framework.resource.parameters.Params) Method(java.lang.reflect.Method) HttpMethod(org.springframework.http.HttpMethod) ResourceMetadata(org.alfresco.rest.framework.core.ResourceMetadata) Match(org.springframework.extensions.webscripts.Match) ResourceWebScriptPost(org.alfresco.rest.framework.webscripts.ResourceWebScriptPost) ResourceParameter(org.alfresco.rest.framework.core.ResourceParameter) Content(org.springframework.extensions.surf.util.Content) StringReader(java.io.StringReader) List(java.util.List) Farmer(org.alfresco.rest.framework.tests.api.mocks.Farmer) ResourceOperation(org.alfresco.rest.framework.core.ResourceOperation) Test(org.junit.Test)

Example 5 with UnsupportedResourceOperationException

use of org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException in project alfresco-remote-api by Alfresco.

the class SerializeTests method testInvokeVersions.

@Test
public void testInvokeVersions() throws IOException {
    final Map<String, Object> respons = new HashMap<String, Object>();
    ResourceWithMetadata entityResource = locator.locateEntityResource(api, "goat", HttpMethod.GET);
    assertNotNull(entityResource);
    EntityResourceAction.ReadById<?> getter = (ReadById<?>) entityResource.getResource();
    Object readById = getter.readById("1234A3", NOT_USED);
    assertTrue("Version 1 must be a goat.", Goat.class.equals(readById.getClass()));
    String out = writeResponse(readById);
    assertNotNull(out);
    Api v3 = Api.valueOf(api.getName(), api.getScope().toString(), "3");
    entityResource = locator.locateEntityResource(v3, "goat", HttpMethod.GET);
    assertNotNull(entityResource);
    getter = (ReadById<?>) entityResource.getResource();
    Object readByIdForNewVersion = getter.readById("1234A3", NOT_USED);
    assertTrue("Version 3 must be a slim goat.", SlimGoat.class.equals(readByIdForNewVersion.getClass()));
    respons.put("v3Goat", readByIdForNewVersion);
    out = writeResponse(readByIdForNewVersion);
    entityResource = locator.locateEntityResource(api, "grass", HttpMethod.GET);
    // ok for version 1
    assertNotNull(entityResource);
    try {
        entityResource = locator.locateEntityResource(v3, "grass", HttpMethod.GET);
        fail("Should throw an UnsupportedResourceOperationException");
    } catch (UnsupportedResourceOperationException error) {
    // this is correct
    }
}
Also used : EntityResourceAction(org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction) ReadById(org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction.ReadById) HashMap(java.util.HashMap) UnsupportedResourceOperationException(org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException) SlimGoat(org.alfresco.rest.framework.tests.api.mocks3.SlimGoat) JSONObject(org.json.JSONObject) Goat(org.alfresco.rest.framework.tests.api.mocks.Goat) SlimGoat(org.alfresco.rest.framework.tests.api.mocks3.SlimGoat) Api(org.alfresco.rest.framework.Api) ResourceWithMetadata(org.alfresco.rest.framework.core.ResourceWithMetadata) Test(org.junit.Test)

Aggregations

UnsupportedResourceOperationException (org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException)18 HashMap (java.util.HashMap)8 Test (org.junit.Test)8 ResourceWithMetadata (org.alfresco.rest.framework.core.ResourceWithMetadata)4 InvalidArgumentException (org.alfresco.rest.framework.core.exceptions.InvalidArgumentException)4 AbstractList (java.util.AbstractList)3 Api (org.alfresco.rest.framework.Api)3 ResourceOperation (org.alfresco.rest.framework.core.ResourceOperation)3 EntityResourceAction (org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction)3 Params (org.alfresco.rest.framework.resource.parameters.Params)3 RecognizedParams (org.alfresco.rest.framework.resource.parameters.Params.RecognizedParams)3 Match (org.springframework.extensions.webscripts.Match)3 WebScriptRequest (org.springframework.extensions.webscripts.WebScriptRequest)3 StringReader (java.io.StringReader)2 AuthorityInfo (org.alfresco.repo.security.authority.AuthorityInfo)2 GroupMember (org.alfresco.rest.api.model.GroupMember)2 ResourceParameter (org.alfresco.rest.framework.core.ResourceParameter)2 ConstraintViolatedException (org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException)2 DeletedResourceException (org.alfresco.rest.framework.core.exceptions.DeletedResourceException)2 EntityNotFoundException (org.alfresco.rest.framework.core.exceptions.EntityNotFoundException)2