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;
}
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");
}
}
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);
}
}
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);
}
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
}
}
Aggregations