From 1528d87cbee6266239aeaf1f24bfce1d20f434c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A1lm=C3=A1n=20K=C3=A9pes?= <2853992+nyuuyn@users.noreply.github.com> Date: Mon, 14 Aug 2023 17:05:23 +0200 Subject: [PATCH] Closes #2188 - adds checking whether attachment has a proper taskId set when creating/updating a task. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kálmán Képes <2853992+nyuuyn@users.noreply.github.com> --- .../pro/taskana/task/rest/TaskController.java | 19 +++++ .../task/rest/TaskControllerIntTest.java | 80 ++++++++++++++++++- 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/task/rest/TaskController.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/task/rest/TaskController.java index 33908e5eb..a9c5833b9 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/task/rest/TaskController.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/task/rest/TaskController.java @@ -5,6 +5,7 @@ import static java.util.function.Predicate.not; import java.beans.ConstructorProperties; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.function.BiConsumer; @@ -105,6 +106,15 @@ public class TaskController { AttachmentPersistenceException, ObjectReferencePersistenceException, NotAuthorizedOnWorkbasketException { + + if (!taskRepresentationModel.getAttachments().stream() + .filter(att -> Objects.nonNull(att.getTaskId())) + .filter(att -> !att.getTaskId().equals(taskRepresentationModel.getTaskId())) + .collect(Collectors.toList()).isEmpty()) { + throw new InvalidArgumentException( + "An attachments' taskId must be empty or equal to the id of the task it belongs to"); + } + Task fromResource = taskRepresentationModelAssembler.toEntityModel(taskRepresentationModel); Task createdTask = taskService.createTask(fromResource); @@ -580,6 +590,15 @@ public class TaskController { + "object in the payload which should be updated. ID=('%s')", taskId, taskRepresentationModel.getTaskId())); } + + if (!taskRepresentationModel.getAttachments().stream() + .filter(att -> Objects.nonNull(att.getTaskId())) + .filter(att -> !att.getTaskId().equals(taskRepresentationModel.getTaskId())) + .collect(Collectors.toList()).isEmpty()) { + throw new InvalidArgumentException( + "An attachments' taskId must be empty or equal to the id of the task it belongs to"); + } + Task task = taskRepresentationModelAssembler.toEntityModel(taskRepresentationModel); task = taskService.updateTask(task); return ResponseEntity.ok(taskRepresentationModelAssembler.toModel(task)); diff --git a/rest/taskana-rest-spring/src/test/java/pro/taskana/task/rest/TaskControllerIntTest.java b/rest/taskana-rest-spring/src/test/java/pro/taskana/task/rest/TaskControllerIntTest.java index 1093cc9dd..00f245411 100644 --- a/rest/taskana-rest-spring/src/test/java/pro/taskana/task/rest/TaskControllerIntTest.java +++ b/rest/taskana-rest-spring/src/test/java/pro/taskana/task/rest/TaskControllerIntTest.java @@ -37,6 +37,7 @@ import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.client.HttpStatusCodeException; +import org.testcontainers.shaded.com.google.common.collect.Lists; import pro.taskana.TaskanaConfiguration; import pro.taskana.classification.rest.models.ClassificationSummaryRepresentationModel; import pro.taskana.common.internal.util.Pair; @@ -45,6 +46,7 @@ import pro.taskana.rest.test.RestHelper; import pro.taskana.rest.test.TaskanaSpringBootTest; import pro.taskana.sampledata.SampleDataGenerator; import pro.taskana.task.api.TaskState; +import pro.taskana.task.rest.models.AttachmentRepresentationModel; import pro.taskana.task.rest.models.IsReadRepresentationModel; import pro.taskana.task.rest.models.ObjectReferenceRepresentationModel; import pro.taskana.task.rest.models.TaskRepresentationModel; @@ -139,6 +141,31 @@ class TaskControllerIntTest { return taskRepresentationModel; } + private ObjectReferenceRepresentationModel getObjectReferenceResourceSample() { + ObjectReferenceRepresentationModel objectReference = new ObjectReferenceRepresentationModel(); + objectReference.setCompany("MyCompany1"); + objectReference.setSystem("MySystem1"); + objectReference.setSystemInstance("MyInstance1"); + objectReference.setType("MyType1"); + objectReference.setValue("00000001"); + return objectReference; + } + + private AttachmentRepresentationModel getAttachmentResourceSample() { + AttachmentRepresentationModel attachmentRepresentationModel = + new AttachmentRepresentationModel(); + attachmentRepresentationModel.setAttachmentId("A11010"); + attachmentRepresentationModel.setObjectReference(getObjectReferenceResourceSample()); + ClassificationSummaryRepresentationModel classificationSummaryRepresentationModel = + new ClassificationSummaryRepresentationModel(); + classificationSummaryRepresentationModel + .setClassificationId("CLI:100000000000000000000000000000000004"); + classificationSummaryRepresentationModel.setKey("L11010"); + attachmentRepresentationModel + .setClassificationSummary(classificationSummaryRepresentationModel); + return attachmentRepresentationModel; + } + private ObjectReferenceRepresentationModel getSampleSecondaryObjectReference(String suffix) { ObjectReferenceRepresentationModel objectReference = new ObjectReferenceRepresentationModel(); objectReference.setCompany("SecondaryCompany" + suffix); @@ -1518,6 +1545,27 @@ class TaskControllerIntTest { assertThat(responseDeleted.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); } + @Test + void should_CreateTaskWithError_When_SpecifyingAttachmentWrong() { + TaskRepresentationModel taskRepresentationModel = getTaskResourceSample(); + AttachmentRepresentationModel attachmentRepresentationModel = getAttachmentResourceSample(); + attachmentRepresentationModel.setTaskId(taskRepresentationModel.getTaskId() + "wrongId"); + taskRepresentationModel.setAttachments(Lists.newArrayList(attachmentRepresentationModel)); + + String url = restHelper.toUrl(RestEndpoints.URL_TASKS); + HttpEntity auth = + new HttpEntity<>( + taskRepresentationModel, RestHelper.generateHeadersForUser("teamlead-1")); + + ThrowingCallable httpCall = + () -> TEMPLATE.exchange(url, HttpMethod.POST, auth, TASK_MODEL_TYPE); + + assertThatThrownBy(httpCall) + .extracting(HttpStatusCodeException.class::cast) + .extracting(HttpStatusCodeException::getStatusCode) + .isEqualTo(HttpStatus.BAD_REQUEST); + } + @Test void should_CreateAndDeleteTaskWithSecondaryObjectReferences_When_SpecifyingObjectReferences() { TaskRepresentationModel taskRepresentationModel = getTaskResourceSample(); @@ -1605,7 +1653,7 @@ class TaskControllerIntTest { /** * TSK-926: If Planned and Due Date is provided to create a task and not matching to service - * level throw an exception One is calculated by other other date +- service level. + * level throw an exception One is calculated by other date +- service level. */ @Test void should_ThrowException_When_CreatingTaskWithPlannedAndDueDateNotMatchingServiceLevel() { @@ -1741,6 +1789,36 @@ class TaskControllerIntTest { assertThat(updatedTask).isNotNull(); assertThat(originalTask.getModified()).isBefore(updatedTask.getModified()); } + + @Test + void should_ThrowError_When_UpdatingTaskWithBadAttachment() { + String url = + restHelper.toUrl(RestEndpoints.URL_TASKS_ID, + "TKI:100000000000000000000000000000000000"); + HttpEntity httpEntityWithoutBody = + new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1")); + + ResponseEntity responseGet = + TEMPLATE.exchange(url, HttpMethod.GET, httpEntityWithoutBody, TASK_MODEL_TYPE); + + final TaskRepresentationModel originalTask = responseGet.getBody(); + + AttachmentRepresentationModel attachmentRepresentationModel = getAttachmentResourceSample(); + attachmentRepresentationModel.setTaskId(originalTask.getTaskId() + "wrongId"); + originalTask.setAttachments(Lists.newArrayList(attachmentRepresentationModel)); + + + HttpEntity httpEntity = + new HttpEntity<>(originalTask, RestHelper.generateHeadersForUser("teamlead-1")); + + ThrowingCallable httpCall = + () -> TEMPLATE.exchange(url, HttpMethod.PUT, httpEntity, TASK_MODEL_TYPE); + + assertThatThrownBy(httpCall) + .extracting(HttpStatusCodeException.class::cast) + .extracting(HttpStatusCodeException::getStatusCode) + .isEqualTo(HttpStatus.BAD_REQUEST); + } } @Nested