Closes #2338 - Add query of tasks without owner
This commit is contained in:
parent
cd9f160393
commit
7e2f933e38
|
@ -24,7 +24,7 @@ public class SqlProviderUtil {
|
|||
.append("</when>")
|
||||
.append("<otherwise>0=1</otherwise>")
|
||||
.append("</choose>");
|
||||
if (column.matches("t.CUSTOM_\\d+")) {
|
||||
if (column.matches("t.CUSTOM_\\d+") || column.matches("t.OWNER")) {
|
||||
sb.append("<if test='" + collection + "ContainsNull'> OR " + column + " IS NULL </if>");
|
||||
}
|
||||
return sb.append(")</if> ");
|
||||
|
|
|
@ -1814,6 +1814,7 @@ class TaskQueryImplAccTest {
|
|||
TaskSummary taskSummary1;
|
||||
TaskSummary taskSummary2;
|
||||
TaskSummary taskSummary3;
|
||||
TaskSummary taskSummary4;
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@BeforeAll
|
||||
|
@ -1822,6 +1823,7 @@ class TaskQueryImplAccTest {
|
|||
taskSummary1 = taskInWorkbasket(wb).owner("user-2-1").buildAndStoreAsSummary(taskService);
|
||||
taskSummary2 = taskInWorkbasket(wb).owner("user-1-2").buildAndStoreAsSummary(taskService);
|
||||
taskSummary3 = taskInWorkbasket(wb).owner("user-1-3").buildAndStoreAsSummary(taskService);
|
||||
taskSummary4 = taskInWorkbasket(wb).owner(null).buildAndStoreAsSummary(taskService);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
|
@ -1859,6 +1861,29 @@ class TaskQueryImplAccTest {
|
|||
|
||||
assertThat(list).containsExactly(taskSummary1);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_ReturnTaskWithOwnerNull_When_QueryingForOwnerIn() {
|
||||
String[] nullArray = {null};
|
||||
List<TaskSummary> list =
|
||||
taskService.createTaskQuery().workbasketIdIn(wb.getId()).ownerIn(nullArray).list();
|
||||
|
||||
assertThat(list).containsExactly(taskSummary4);
|
||||
}
|
||||
|
||||
@WithAccessId(user = "user-1-1")
|
||||
@Test
|
||||
void should_ReturnTaskWithOwnerNullAndUser11_When_QueryingForOwnerIn() {
|
||||
List<TaskSummary> list =
|
||||
taskService
|
||||
.createTaskQuery()
|
||||
.workbasketIdIn(wb.getId())
|
||||
.ownerIn("user-1-2", null)
|
||||
.list();
|
||||
|
||||
assertThat(list).containsExactlyInAnyOrder(taskSummary2, taskSummary4);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
|
|
@ -140,6 +140,7 @@ public class TaskQueryImpl implements TaskQuery {
|
|||
private String[] parentBusinessProcessIdLike;
|
||||
private String[] parentBusinessProcessIdNotLike;
|
||||
private String[] ownerIn;
|
||||
private boolean ownerInContainsNull;
|
||||
private String[] ownerNotIn;
|
||||
private String[] ownerLike;
|
||||
private String[] ownerNotLike;
|
||||
|
@ -865,7 +866,15 @@ public class TaskQueryImpl implements TaskQuery {
|
|||
|
||||
@Override
|
||||
public TaskQuery ownerIn(String... owners) {
|
||||
List<String> conditionList = new ArrayList<>(Arrays.asList(owners));
|
||||
boolean containsNull = conditionList.contains(null);
|
||||
if (containsNull) {
|
||||
conditionList.remove(null);
|
||||
ownerInContainsNull = true;
|
||||
this.ownerIn = conditionList.toArray(new String[owners.length - 1]);
|
||||
} else {
|
||||
this.ownerIn = owners;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,9 +4,12 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import pro.taskana.common.api.exceptions.InvalidArgumentException;
|
||||
|
||||
public class QueryParamsValidator {
|
||||
|
||||
|
@ -32,5 +35,21 @@ public class QueryParamsValidator {
|
|||
if (!providedParams.isEmpty()) {
|
||||
throw new IllegalArgumentException("Unknown request parameters found: " + providedParams);
|
||||
}
|
||||
checkExactParam(request, "owner-is-null");
|
||||
}
|
||||
|
||||
private static void checkExactParam(HttpServletRequest request, String queryParameter) {
|
||||
String queryString = request.getQueryString();
|
||||
boolean containParam = queryString != null && queryString.contains(queryParameter);
|
||||
if (containParam) {
|
||||
Pattern pattern = Pattern.compile("\\b" + queryParameter + "(&|$)");
|
||||
Matcher matcher = pattern.matcher(queryString);
|
||||
|
||||
boolean hasExactParam = matcher.find();
|
||||
if (!hasExactParam) {
|
||||
throw new InvalidArgumentException(
|
||||
"It is prohibited to use the param " + queryParameter + " with values.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,9 @@ package pro.taskana.task.rest;
|
|||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import java.beans.ConstructorProperties;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import pro.taskana.common.api.IntInterval;
|
||||
import pro.taskana.common.api.KeyDomain;
|
||||
|
@ -740,6 +742,13 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
|
|||
*/
|
||||
@JsonProperty("owner-not-like")
|
||||
private final String[] ownerNotLike;
|
||||
|
||||
/**
|
||||
* Filter by tasks that have no owner. The parameter should exactly be "owner-is-null" without
|
||||
* being followed by "=..."
|
||||
*/
|
||||
@JsonProperty("owner-is-null")
|
||||
private final String ownerNull;
|
||||
// endregion
|
||||
// region primaryObjectReference
|
||||
/**
|
||||
|
@ -1259,6 +1268,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
|
|||
"owner-not",
|
||||
"owner-like",
|
||||
"owner-not-like",
|
||||
"owner-is-null",
|
||||
"por",
|
||||
"por-company",
|
||||
"por-company-not",
|
||||
|
@ -1415,6 +1425,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
|
|||
String[] ownerNotIn,
|
||||
String[] ownerLike,
|
||||
String[] ownerNotLike,
|
||||
String ownerNull,
|
||||
ObjectReference[] primaryObjectReferenceIn,
|
||||
String[] porCompanyIn,
|
||||
String[] porCompanyNotIn,
|
||||
|
@ -1570,6 +1581,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
|
|||
this.ownerNotIn = ownerNotIn;
|
||||
this.ownerLike = ownerLike;
|
||||
this.ownerNotLike = ownerNotLike;
|
||||
this.ownerNull = ownerNull;
|
||||
this.primaryObjectReferenceIn = primaryObjectReferenceIn;
|
||||
this.porCompanyIn = porCompanyIn;
|
||||
this.porCompanyNotIn = porCompanyNotIn;
|
||||
|
@ -1845,7 +1857,8 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
|
|||
.map(this::wrapElementsInLikeStatement)
|
||||
.ifPresent(query::parentBusinessProcessIdNotLike);
|
||||
|
||||
Optional.ofNullable(ownerIn).ifPresent(query::ownerIn);
|
||||
String[] ownerInIncludingNull = addNullToOwnerIn();
|
||||
Optional.ofNullable(ownerInIncludingNull).ifPresent(query::ownerIn);
|
||||
Optional.ofNullable(ownerNotIn).ifPresent(query::ownerNotIn);
|
||||
Optional.ofNullable(ownerLike)
|
||||
.map(this::wrapElementsInLikeStatement)
|
||||
|
@ -2184,4 +2197,16 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
|
|||
"provided value of the property 'without-attachment' must be 'true'");
|
||||
}
|
||||
}
|
||||
|
||||
private String[] addNullToOwnerIn() {
|
||||
if (this.ownerNull == null) {
|
||||
return this.ownerIn;
|
||||
}
|
||||
if (this.ownerIn == null) {
|
||||
return new String[]{null};
|
||||
}
|
||||
List<String> ownerInAsList = new ArrayList(Arrays.asList(this.ownerIn));
|
||||
ownerInAsList.add(null);
|
||||
return ownerInAsList.toArray(new String[ownerInAsList.size()]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@ import org.junit.jupiter.api.TestFactory;
|
|||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle;
|
||||
import org.junit.jupiter.api.function.ThrowingConsumer;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
|
@ -37,6 +39,7 @@ import org.springframework.http.ResponseEntity;
|
|||
import org.springframework.web.client.HttpStatusCodeException;
|
||||
import pro.taskana.TaskanaConfiguration;
|
||||
import pro.taskana.classification.rest.models.ClassificationSummaryRepresentationModel;
|
||||
import pro.taskana.common.internal.util.Pair;
|
||||
import pro.taskana.common.rest.RestEndpoints;
|
||||
import pro.taskana.rest.test.RestHelper;
|
||||
import pro.taskana.rest.test.TaskanaSpringBootTest;
|
||||
|
@ -1165,6 +1168,46 @@ class TaskControllerIntTest {
|
|||
+ "&sort-by=POR_VALUE&order=DESCENDING");
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@CsvSource({
|
||||
"owner=user-1-1, 10",
|
||||
"owner-is-null, 65",
|
||||
"owner-is-null&owner=user-1-1, 75",
|
||||
"state=READY&owner-is-null&owner=user-1-1, 56",
|
||||
})
|
||||
void should_ReturnTasksWithVariousOwnerParameters_When_GettingTasks(
|
||||
String queryParams, int expectedSize) {
|
||||
String url = restHelper.toUrl(RestEndpoints.URL_TASKS) + "?" + queryParams;
|
||||
HttpEntity<Object> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("admin"));
|
||||
ResponseEntity<TaskSummaryPagedRepresentationModel> response =
|
||||
TEMPLATE.exchange(url, HttpMethod.GET, auth, TASK_SUMMARY_PAGE_MODEL_TYPE);
|
||||
|
||||
assertThat(response.getBody()).isNotNull();
|
||||
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull();
|
||||
assertThat((response.getBody()).getContent()).hasSize(expectedSize);
|
||||
}
|
||||
|
||||
@TestFactory
|
||||
Stream<DynamicTest> should_ThrowException_When_OwnerIsNullParamNotStrict() {
|
||||
List<Pair<String, String>> list =
|
||||
List.of(
|
||||
Pair.of("When owner-is-null=", "?owner-is-null="),
|
||||
Pair.of("When owner-is-null=anyValue", "?owner-is-null=anyValue1,anyValue2"));
|
||||
ThrowingConsumer<Pair<String, String>> testOwnerIsNull =
|
||||
t -> {
|
||||
String url = restHelper.toUrl(RestEndpoints.URL_TASKS) + t.getRight();
|
||||
HttpEntity<Object> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("admin"));
|
||||
|
||||
assertThatThrownBy(
|
||||
() ->
|
||||
TEMPLATE.exchange(url, HttpMethod.GET, auth, TASK_SUMMARY_PAGE_MODEL_TYPE))
|
||||
.isInstanceOf(HttpStatusCodeException.class)
|
||||
.hasMessageContaining(
|
||||
"It is prohibited to use the param owner-is-null with values.");
|
||||
};
|
||||
return DynamicTest.stream(list.iterator(), Pair::getLeft, testOwnerIsNull);
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_GetAllTasks_For_GettingLastTaskSummaryPageSortedByPorValue() {
|
||||
String url =
|
||||
|
|
Loading…
Reference in New Issue