From 6997d640834819d21fe0325178d73bbf70de68fc Mon Sep 17 00:00:00 2001 From: Mustapha Zorgati <15628173+mustaphazorgati@users.noreply.github.com> Date: Thu, 11 Aug 2022 16:46:57 +0200 Subject: [PATCH] TSK-1943: added REST endpoint for force requesting changes on a Task --- .../pro/taskana/task/api/TaskService.java | 5 ++-- .../src/docs/asciidoc/rest-api.adoc | 1 + .../taskana/common/rest/RestEndpoints.java | 2 ++ .../pro/taskana/task/rest/TaskController.java | 21 ++++++++++++++ .../task/rest/TaskControllerIntTest.java | 29 +++++++++++++++++++ .../task/rest/TaskControllerRestDocTest.java | 11 +++++++ 6 files changed, 67 insertions(+), 2 deletions(-) diff --git a/lib/taskana-core/src/main/java/pro/taskana/task/api/TaskService.java b/lib/taskana-core/src/main/java/pro/taskana/task/api/TaskService.java index d9b67cca3..d181f3940 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/task/api/TaskService.java +++ b/lib/taskana-core/src/main/java/pro/taskana/task/api/TaskService.java @@ -159,9 +159,10 @@ public interface TaskService { * * @param taskId the {@linkplain Task#getId() id} of the specified {@linkplain Task} * @return the {@linkplain Task} after changes have been requested - * @throws InvalidTaskStateException cannot be thrown + * @throws InvalidTaskStateException if the {@linkplain Task#getState() state} of the {@linkplain + * Task} with taskId is one of the {@linkplain TaskState#END_STATES} * @throws TaskNotFoundException if the {@linkplain Task} with taskId wasn't found - * @throws InvalidOwnerException if the {@linkplain Task} is claimed by another user + * @throws InvalidOwnerException cannot be thrown * @throws NotAuthorizedException if the current user has no {@linkplain * WorkbasketPermission#READ} for the {@linkplain Workbasket} the {@linkplain Task} is in */ diff --git a/rest/taskana-rest-spring/src/docs/asciidoc/rest-api.adoc b/rest/taskana-rest-spring/src/docs/asciidoc/rest-api.adoc index b55c488fa..16dd780cd 100644 --- a/rest/taskana-rest-spring/src/docs/asciidoc/rest-api.adoc +++ b/rest/taskana-rest-spring/src/docs/asciidoc/rest-api.adoc @@ -106,6 +106,7 @@ include::{snippets}/TaskControllerRestDocTest/cancelClaimTaskDocTest/auto-sectio include::{snippets}/TaskControllerRestDocTest/forceCancelClaimTaskDocTest/auto-section.adoc[] include::{snippets}/TaskControllerRestDocTest/requestReviewTaskDocTest/auto-section.adoc[] include::{snippets}/TaskControllerRestDocTest/requestChangesTaskDocTest/auto-section.adoc[] +include::{snippets}/TaskControllerRestDocTest/forceRequestChangesTaskDocTest/auto-section.adoc[] include::{snippets}/TaskControllerRestDocTest/completeTaskDocTest/auto-section.adoc[] include::{snippets}/TaskControllerRestDocTest/cancelTaskDocTest/auto-section.adoc[] include::{snippets}/TaskControllerRestDocTest/transferTaskDocTest/auto-section.adoc[] diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/common/rest/RestEndpoints.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/common/rest/RestEndpoints.java index 090ef7c0f..191c676cd 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/common/rest/RestEndpoints.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/common/rest/RestEndpoints.java @@ -49,6 +49,8 @@ public final class RestEndpoints { public static final String URL_TASKS_ID_REQUEST_REVIEW = API_V1 + "tasks/{taskId}/request-review"; public static final String URL_TASKS_ID_REQUEST_CHANGES = API_V1 + "tasks/{taskId}/request-changes"; + public static final String URL_TASKS_ID_REQUEST_CHANGES_FORCE = + API_V1 + "tasks/{taskId}/request-changes/force"; public static final String URL_TASKS_ID_COMPLETE = API_V1 + "tasks/{taskId}/complete"; public static final String URL_TASKS_ID_CANCEL = API_V1 + "tasks/{taskId}/cancel"; public static final String URL_TASKS_ID_TRANSFER_WORKBASKET_ID = 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 0d208b6d5..01de9e924 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 @@ -245,6 +245,27 @@ public class TaskController { return ResponseEntity.ok(taskRepresentationModelAssembler.toModel(task)); } + /** + * This endpoint force requests changes on a Task. + * + * @param taskId the Id of the Task on which a review should be requested + * @return the change requested Task + * @throws InvalidTaskStateException if the Task with taskId is in an end state + * @throws TaskNotFoundException if the Task with taskId wasn't found + * @throws InvalidOwnerException cannot be thrown + * @throws NotAuthorizedException if the current user has no READ permissions for the Workbasket + * the Task is in + * @title Force request changes on a Task + */ + @PostMapping(path = RestEndpoints.URL_TASKS_ID_REQUEST_CHANGES_FORCE) + @Transactional(rollbackFor = Exception.class) + public ResponseEntity forceRequestChanges(@PathVariable String taskId) + throws InvalidTaskStateException, TaskNotFoundException, InvalidOwnerException, + NotAuthorizedException { + Task task = taskService.forceRequestChanges(taskId); + return ResponseEntity.ok(taskRepresentationModelAssembler.toModel(task)); + } + /** * This endpoint selects the first Task returned by the Task Query and claims it. * 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 8db0daa70..147670f62 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 @@ -1448,6 +1448,35 @@ class TaskControllerIntTest { assertThat(repModel.getState()).isEqualTo(TaskState.READY); } + @Test + void should_ForceRequestChanges_When_CurrentUserIsNotTheOwner() { + String url = + restHelper.toUrl(RestEndpoints.URL_TASKS_ID, "TKI:000000000000000000000000000000000100"); + HttpEntity auth = new HttpEntity<>(RestHelper.generateHeadersForUser("user-1-1")); + + // retrieve task from Rest Api + ResponseEntity getTaskResponse = + TEMPLATE.exchange(url, HttpMethod.GET, auth, TASK_MODEL_TYPE); + assertThat(getTaskResponse.getBody()).isNotNull(); + TaskRepresentationModel repModel = getTaskResponse.getBody(); + assertThat(repModel.getState()).isEqualTo(TaskState.CLAIMED); + assertThat(repModel.getOwner()).isEqualTo("user-1-2"); + + // request changes + String url2 = + restHelper.toUrl( + RestEndpoints.URL_TASKS_ID_REQUEST_CHANGES_FORCE, + "TKI:000000000000000000000000000000000100"); + ResponseEntity requestedChangesResponse = + TEMPLATE.exchange(url2, HttpMethod.POST, auth, TASK_MODEL_TYPE); + + assertThat(requestedChangesResponse.getBody()).isNotNull(); + assertThat(requestedChangesResponse.getStatusCode()).isEqualTo(HttpStatus.OK); + repModel = requestedChangesResponse.getBody(); + assertThat(repModel.getOwner()).isNull(); + assertThat(repModel.getState()).isEqualTo(TaskState.READY); + } + @Test void should_UpdateTaskOwnerOfReadyTask() { final String url = restHelper.toUrl("/api/v1/tasks/TKI:000000000000000000000000000000000025"); diff --git a/rest/taskana-rest-spring/src/test/java/pro/taskana/task/rest/TaskControllerRestDocTest.java b/rest/taskana-rest-spring/src/test/java/pro/taskana/task/rest/TaskControllerRestDocTest.java index 2bcd9d478..baf1f9e5a 100644 --- a/rest/taskana-rest-spring/src/test/java/pro/taskana/task/rest/TaskControllerRestDocTest.java +++ b/rest/taskana-rest-spring/src/test/java/pro/taskana/task/rest/TaskControllerRestDocTest.java @@ -102,6 +102,17 @@ class TaskControllerRestDocTest extends BaseRestDocTest { .andExpect(MockMvcResultMatchers.status().isOk()); } + @Test + void forceRequestChangesTaskDocTest() throws Exception { + mockMvc + .perform( + post( + RestEndpoints.URL_TASKS_ID_REQUEST_CHANGES_FORCE, + "TKI:000000000000000000000000000000000100") + .headers(RestHelper.generateHeadersForUser("user-1-1"))) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + @Test void selectAndClaimTaskDocTest() throws Exception { mockMvc