Closes #2635: Make owner-is-null=owner-is-null not valid, allow use case "owner-is-null=true"

This commit is contained in:
CRoberto1926 2024-07-25 13:12:09 +02:00 committed by Jörg Heffner
parent 3646bc08b1
commit 4ca0ae869f
6 changed files with 198 additions and 109 deletions

View File

@ -1,15 +1,14 @@
package pro.taskana.common.rest.util; package pro.taskana.common.rest.util;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import pro.taskana.common.api.exceptions.InvalidArgumentException;
public class QueryParamsValidator { public class QueryParamsValidator {
@ -35,21 +34,57 @@ public class QueryParamsValidator {
if (!providedParams.isEmpty()) { if (!providedParams.isEmpty()) {
throw new IllegalArgumentException("Unknown request parameters found: " + providedParams); throw new IllegalArgumentException("Unknown request parameters found: " + providedParams);
} }
checkExactParam(request, "owner-is-null");
} }
public static void checkExactParam(HttpServletRequest request, String queryParameter) { public static boolean hasQueryParameterValues(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(); Map<String, String[]> queryParametersMap = request.getParameterMap();
if (!hasExactParam) {
throw new InvalidArgumentException( if (queryParametersMap.isEmpty()) {
"It is prohibited to use the param " + queryParameter + " with values."); return false;
} }
String[] queryParameterValues = queryParametersMap.get(queryParameter);
if (queryParameterValues == null) {
return false;
} }
boolean hasQueryParameterNotEmptyValues =
Arrays.stream(queryParameterValues).anyMatch(value -> !value.isBlank());
/* Workaround to manage the case "query-param=".
It should be safe enough to use because we have checked all other possibilities before. */
boolean hasQueryParameterEmptyValues = request.getQueryString().contains(queryParameter + "=");
return hasQueryParameterNotEmptyValues || hasQueryParameterEmptyValues;
}
public static boolean hasQueryParameterValuesOrIsNotTrue(
HttpServletRequest request, String queryParameter) {
Map<String, String[]> queryParametersMap = request.getParameterMap();
if (queryParametersMap.isEmpty()) {
return false;
}
String[] queryParameterValues = queryParametersMap.get(queryParameter);
if (queryParameterValues == null) {
return false;
}
boolean hasQueryParameterProhibitedValues =
Arrays.stream(queryParameterValues)
.anyMatch(value -> !value.isBlank() && !Boolean.parseBoolean(value));
/* Workaround to manage the case "query-param=".
It should be safe enough to use because we have checked all other possibilities before. */
boolean hasQueryParameterEmptyValues =
Arrays.stream(queryParameterValues).allMatch(String::isBlank)
&& request.getQueryString().contains(queryParameter + "=");
return hasQueryParameterProhibitedValues || hasQueryParameterEmptyValues;
} }
} }

View File

@ -120,7 +120,8 @@ public class TaskController {
if (!taskRepresentationModel.getAttachments().stream() if (!taskRepresentationModel.getAttachments().stream()
.filter(att -> Objects.nonNull(att.getTaskId())) .filter(att -> Objects.nonNull(att.getTaskId()))
.filter(att -> !att.getTaskId().equals(taskRepresentationModel.getTaskId())) .filter(att -> !att.getTaskId().equals(taskRepresentationModel.getTaskId()))
.collect(Collectors.toList()).isEmpty()) { .collect(Collectors.toList())
.isEmpty()) {
throw new InvalidArgumentException( throw new InvalidArgumentException(
"An attachments' taskId must be empty or equal to the id of the task it belongs to"); "An attachments' taskId must be empty or equal to the id of the task it belongs to");
} }
@ -148,6 +149,7 @@ public class TaskController {
* @param sortParameter the sort parameters * @param sortParameter the sort parameters
* @param pagingParameter the paging parameters * @param pagingParameter the paging parameters
* @return the Tasks with the given filter, sort and paging options. * @return the Tasks with the given filter, sort and paging options.
* @throws InvalidArgumentException if the query parameter "owner-is-null" has values
*/ */
@GetMapping(path = RestEndpoints.URL_TASKS) @GetMapping(path = RestEndpoints.URL_TASKS)
@Transactional(readOnly = true, rollbackFor = Exception.class) @Transactional(readOnly = true, rollbackFor = Exception.class)
@ -167,6 +169,12 @@ public class TaskController {
TaskQueryGroupByParameter.class, TaskQueryGroupByParameter.class,
QuerySortParameter.class, QuerySortParameter.class,
QueryPagingParameter.class); QueryPagingParameter.class);
if (QueryParamsValidator.hasQueryParameterValuesOrIsNotTrue(request, "owner-is-null")) {
throw new InvalidArgumentException(
"It is prohibited to use the param owner-is-null with values.");
}
TaskQuery query = taskService.createTaskQuery(); TaskQuery query = taskService.createTaskQuery();
filterParameter.apply(query); filterParameter.apply(query);
@ -655,7 +663,8 @@ public class TaskController {
if (!taskRepresentationModel.getAttachments().stream() if (!taskRepresentationModel.getAttachments().stream()
.filter(att -> Objects.nonNull(att.getTaskId())) .filter(att -> Objects.nonNull(att.getTaskId()))
.filter(att -> !att.getTaskId().equals(taskRepresentationModel.getTaskId())) .filter(att -> !att.getTaskId().equals(taskRepresentationModel.getTaskId()))
.collect(Collectors.toList()).isEmpty()) { .collect(Collectors.toList())
.isEmpty()) {
throw new InvalidArgumentException( throw new InvalidArgumentException(
"An attachments' taskId must be empty or equal to the id of the task it belongs to"); "An attachments' taskId must be empty or equal to the id of the task it belongs to");
} }

View File

@ -28,6 +28,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
/** Filter by what the task id shouldn't be. This is an exact match. */ /** Filter by what the task id shouldn't be. This is an exact match. */
@JsonProperty("task-id-not") @JsonProperty("task-id-not")
private final String[] taskIdNotIn; private final String[] taskIdNotIn;
// endregion // endregion
// region externalId // region externalId
/** Filter by the external id of the Task. This is an exact match. */ /** Filter by the external id of the Task. This is an exact match. */
@ -37,6 +38,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
/** Filter by what the external id of the Task shouldn't be. This is an exact match. */ /** Filter by what the external id of the Task shouldn't be. This is an exact match. */
@JsonProperty("external-id-not") @JsonProperty("external-id-not")
private final String[] externalIdNotIn; private final String[] externalIdNotIn;
// endregion // endregion
// region received // region received
/** /**
@ -101,6 +103,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("received-until-not") @JsonProperty("received-until-not")
private final Instant receivedUntilNot; private final Instant receivedUntilNot;
// endregion // endregion
// region created // region created
/** /**
@ -164,6 +167,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("created-until-not") @JsonProperty("created-until-not")
private final Instant createdUntilNot; private final Instant createdUntilNot;
// endregion // endregion
// region claimed // region claimed
/** /**
@ -183,6 +187,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("claimed-not") @JsonProperty("claimed-not")
private final Instant[] claimedNotWithin; private final Instant[] claimedNotWithin;
// endregion // endregion
// region modified // region modified
/** /**
@ -202,6 +207,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("modified-not") @JsonProperty("modified-not")
private final Instant[] modifiedNotWithin; private final Instant[] modifiedNotWithin;
// endregion // endregion
// region planned // region planned
/** /**
@ -265,6 +271,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("planned-until-not") @JsonProperty("planned-until-not")
private final Instant plannedUntilNot; private final Instant plannedUntilNot;
// endregion // endregion
// region due // region due
/** /**
@ -328,6 +335,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("due-until-not") @JsonProperty("due-until-not")
private final Instant dueUntilNot; private final Instant dueUntilNot;
// endregion // endregion
// region completed // region completed
/** /**
@ -392,6 +400,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("completed-until-not") @JsonProperty("completed-until-not")
private final Instant completedUntilNot; private final Instant completedUntilNot;
// endregion // endregion
// region name // region name
/** Filter by the name of the Task. This is an exact match. */ /** Filter by the name of the Task. This is an exact match. */
@ -417,6 +426,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("name-not-like") @JsonProperty("name-not-like")
private final String[] nameNotLike; private final String[] nameNotLike;
// endregion // endregion
// region creator // region creator
/** Filter by creator of the Task. This is an exact match. */ /** Filter by creator of the Task. This is an exact match. */
@ -442,6 +452,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("creator-not-like") @JsonProperty("creator-not-like")
private final String[] creatorNotLike; private final String[] creatorNotLike;
// endregion // endregion
// region note // region note
/** /**
@ -459,6 +470,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("note-not-like") @JsonProperty("note-not-like")
private final String[] noteNotLike; private final String[] noteNotLike;
// endregion // endregion
// region description // region description
/** /**
@ -476,6 +488,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("description-not-like") @JsonProperty("description-not-like")
private final String[] descriptionNotLike; private final String[] descriptionNotLike;
// endregion // endregion
// region priority // region priority
/** Filter by the priority of the Task. This is an exact match. */ /** Filter by the priority of the Task. This is an exact match. */
@ -509,6 +522,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
/** Filter by excluding priority up to the given value (inclusive). */ /** Filter by excluding priority up to the given value (inclusive). */
@JsonProperty("priority-not-until") @JsonProperty("priority-not-until")
private final Integer priorityNotUntil; private final Integer priorityNotUntil;
// endregion // endregion
// region state // region state
/** Filter by the Task state. This is an exact match. */ /** Filter by the Task state. This is an exact match. */
@ -518,6 +532,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
/** Filter by what the Task state shouldn't be. This is an exact match. */ /** Filter by what the Task state shouldn't be. This is an exact match. */
@JsonProperty("state-not") @JsonProperty("state-not")
private final TaskState[] stateNotIn; private final TaskState[] stateNotIn;
// endregion // endregion
// region comments // region comments
/** Filter by the has comments flag of the Task. This is an exact match. */ /** Filter by the has comments flag of the Task. This is an exact match. */
@ -532,6 +547,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
/** Filter by what the classification id of the Task shouldn't be. This is an exact match. */ /** Filter by what the classification id of the Task shouldn't be. This is an exact match. */
@JsonProperty("classification-id-not") @JsonProperty("classification-id-not")
private final String[] classificationIdNotIn; private final String[] classificationIdNotIn;
// endregion // endregion
// region classificationKey // region classificationKey
/** Filter by the classification key of the Task. This is an exact match. */ /** Filter by the classification key of the Task. This is an exact match. */
@ -557,6 +573,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("classification-key-not-like") @JsonProperty("classification-key-not-like")
private final String[] classificationKeyNotLike; private final String[] classificationKeyNotLike;
// endregion // endregion
// region classificationParentKey // region classificationParentKey
/** /**
@ -588,6 +605,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("classification-parent-key-not-like") @JsonProperty("classification-parent-key-not-like")
private final String[] classificationParentKeyNotLike; private final String[] classificationParentKeyNotLike;
// endregion // endregion
// region classificationCategory // region classificationCategory
/** Filter by the classification category of the Task. This is an exact match. */ /** Filter by the classification category of the Task. This is an exact match. */
@ -615,6 +633,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("classification-category-not-like") @JsonProperty("classification-category-not-like")
private final String[] classificationCategoryNotLike; private final String[] classificationCategoryNotLike;
// endregion // endregion
// region classificationName // region classificationName
/** Filter by the classification name of the Task. This is an exact match. */ /** Filter by the classification name of the Task. This is an exact match. */
@ -640,6 +659,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("classification-name-not-like") @JsonProperty("classification-name-not-like")
private final String[] classificationNameNotLike; private final String[] classificationNameNotLike;
// endregion // endregion
// region workbasketId // region workbasketId
/** Filter by workbasket id of the Task. This is an exact match. */ /** Filter by workbasket id of the Task. This is an exact match. */
@ -649,6 +669,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
/** Filter by what the workbasket id of the Task shouldn't be. This is an exact match. */ /** Filter by what the workbasket id of the Task shouldn't be. This is an exact match. */
@JsonProperty("workbasket-id-not") @JsonProperty("workbasket-id-not")
private final String[] workbasketIdNotIn; private final String[] workbasketIdNotIn;
// endregion // endregion
// region workbasketKeyDomain // region workbasketKeyDomain
/** /**
@ -668,6 +689,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
/** Filter by domain of the Task. This is an exact match. */ /** Filter by domain of the Task. This is an exact match. */
@JsonProperty("domain") @JsonProperty("domain")
private final String domain; private final String domain;
// endregion // endregion
// region businessProcessId // region businessProcessId
/** Filter by the business process id of the Task. This is an exact match. */ /** Filter by the business process id of the Task. This is an exact match. */
@ -754,6 +776,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("owner-is-null") @JsonProperty("owner-is-null")
private final String ownerNull; private final String ownerNull;
// endregion // endregion
// region primaryObjectReference // region primaryObjectReference
/** /**
@ -764,6 +787,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("por") @JsonProperty("por")
private final ObjectReference[] primaryObjectReferenceIn; private final ObjectReference[] primaryObjectReferenceIn;
// endregion // endregion
// region primaryObjectReferenceCompany // region primaryObjectReferenceCompany
/** Filter by the company of the primary object reference of the Task. This is an exact match. */ /** Filter by the company of the primary object reference of the Task. This is an exact match. */
@ -792,6 +816,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("por-company-not-like") @JsonProperty("por-company-not-like")
private final String[] porCompanyNotLike; private final String[] porCompanyNotLike;
// endregion // endregion
// region primaryObjectReferenceSystem // region primaryObjectReferenceSystem
/** Filter by the system of the primary object reference of the Task. This is an exact match. */ /** Filter by the system of the primary object reference of the Task. This is an exact match. */
@ -820,6 +845,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("por-system-not-like") @JsonProperty("por-system-not-like")
private final String[] porSystemNotLike; private final String[] porSystemNotLike;
// endregion // endregion
// region primaryObjectReferenceSystemInstance // region primaryObjectReferenceSystemInstance
/** /**
@ -851,6 +877,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("por-instance-not-like") @JsonProperty("por-instance-not-like")
private final String[] porInstanceNotLike; private final String[] porInstanceNotLike;
// endregion // endregion
// region primaryObjectReferenceSystemType // region primaryObjectReferenceSystemType
/** Filter by the type of the primary object reference of the Task. This is an exact match. */ /** Filter by the type of the primary object reference of the Task. This is an exact match. */
@ -879,6 +906,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("por-type-not-like") @JsonProperty("por-type-not-like")
private final String[] porTypeNotLike; private final String[] porTypeNotLike;
// endregion // endregion
// region primaryObjectReferenceSystemValue // region primaryObjectReferenceSystemValue
/** Filter by the value of the primary object reference of the Task. This is an exact match. */ /** Filter by the value of the primary object reference of the Task. This is an exact match. */
@ -907,6 +935,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("por-value-not-like") @JsonProperty("por-value-not-like")
private final String[] porValueNotLike; private final String[] porValueNotLike;
// endregion // endregion
// region secondaryObjectReference // region secondaryObjectReference
/** /**
@ -917,6 +946,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("sor") @JsonProperty("sor")
private final ObjectReference[] secondaryObjectReferenceIn; private final ObjectReference[] secondaryObjectReferenceIn;
// endregion // endregion
// region secondaryObjectReferenceCompany // region secondaryObjectReferenceCompany
/** /**
@ -997,11 +1027,13 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
/** Filter by the is read flag of the Task. This is an exact match. */ /** Filter by the is read flag of the Task. This is an exact match. */
@JsonProperty("is-read") @JsonProperty("is-read")
private final Boolean isRead; private final Boolean isRead;
// endregion // endregion
// region transferred // region transferred
/** Filter by the is transferred flag of the Task. This is an exact match. */ /** Filter by the is transferred flag of the Task. This is an exact match. */
@JsonProperty("is-transferred") @JsonProperty("is-transferred")
private final Boolean isTransferred; private final Boolean isTransferred;
// endregion // endregion
// region attachmentClassificationId // region attachmentClassificationId
/** Filter by the attachment classification id of the Task. This is an exact match. */ /** Filter by the attachment classification id of the Task. This is an exact match. */
@ -1014,6 +1046,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("attachment-classification-id-not") @JsonProperty("attachment-classification-id-not")
private final String[] attachmentClassificationIdNotIn; private final String[] attachmentClassificationIdNotIn;
// endregion // endregion
// region attachmentClassificationKey // region attachmentClassificationKey
/** Filter by the attachment classification key of the Task. This is an exact match. */ /** Filter by the attachment classification key of the Task. This is an exact match. */
@ -1042,6 +1075,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("attachment-classification-key-not-like") @JsonProperty("attachment-classification-key-not-like")
private final String[] attachmentClassificationKeyNotLike; private final String[] attachmentClassificationKeyNotLike;
// endregion // endregion
// region attachmentClassificationName // region attachmentClassificationName
/** Filter by the attachment classification name of the Task. This is an exact match. */ /** Filter by the attachment classification name of the Task. This is an exact match. */
@ -1070,6 +1104,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("attachment-classification-name-not-like") @JsonProperty("attachment-classification-name-not-like")
private final String[] attachmentClassificationNameNotLike; private final String[] attachmentClassificationNameNotLike;
// endregion // endregion
// region attachmentChannel // region attachmentChannel
/** Filter by the attachment channel of the Task. This is an exact match. */ /** Filter by the attachment channel of the Task. This is an exact match. */
@ -1095,6 +1130,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("attachment-channel-not-like") @JsonProperty("attachment-channel-not-like")
private final String[] attachmentChannelNotLike; private final String[] attachmentChannelNotLike;
// endregion // endregion
// region attachmentReferenceValue // region attachmentReferenceValue
/** Filter by the attachment reference of the Task. This is an exact match. */ /** Filter by the attachment reference of the Task. This is an exact match. */
@ -1120,6 +1156,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("attachment-reference-not-like") @JsonProperty("attachment-reference-not-like")
private final String[] attachmentReferenceNotLike; private final String[] attachmentReferenceNotLike;
// endregion // endregion
// region attachmentReceived // region attachmentReceived
/** /**
@ -1139,6 +1176,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("attachment-received-not") @JsonProperty("attachment-received-not")
private final Instant[] attachmentReceivedNotWithin; private final Instant[] attachmentReceivedNotWithin;
// endregion // endregion
// region withoutAttachment // region withoutAttachment
/** /**
@ -1147,6 +1185,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("without-attachment") @JsonProperty("without-attachment")
private final Boolean withoutAttachment; private final Boolean withoutAttachment;
// endregion // endregion
// region callbackState // region callbackState
/** Filter by the callback state of the Task. This is an exact match. */ /** Filter by the callback state of the Task. This is an exact match. */
@ -1156,6 +1195,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
/** Filter by what the callback state of the Task shouldn't be. This is an exact match. */ /** Filter by what the callback state of the Task shouldn't be. This is an exact match. */
@JsonProperty("callback-state-not") @JsonProperty("callback-state-not")
private final CallbackState[] callbackStateNotIn; private final CallbackState[] callbackStateNotIn;
// endregion // endregion
// region wildcardSearchValue // region wildcardSearchValue
/** /**
@ -1173,6 +1213,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
*/ */
@JsonProperty("wildcard-search-value") @JsonProperty("wildcard-search-value")
private final String wildcardSearchValue; private final String wildcardSearchValue;
// endregion // endregion
// region constructor // region constructor
@ -2213,7 +2254,7 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
return this.ownerIn; return this.ownerIn;
} }
if (this.ownerIn == null) { if (this.ownerIn == null) {
return new String[]{null}; return new String[] {null};
} }
List<String> ownerInAsList = new ArrayList<>(Arrays.asList(this.ownerIn)); List<String> ownerInAsList = new ArrayList<>(Arrays.asList(this.ownerIn));
ownerInAsList.add(null); ownerInAsList.add(null);

View File

@ -41,7 +41,8 @@ public class UserController {
private final CurrentUserContext currentUserContext; private final CurrentUserContext currentUserContext;
@Autowired @Autowired
UserController(UserService userService, UserController(
UserService userService,
UserRepresentationModelAssembler userAssembler, UserRepresentationModelAssembler userAssembler,
CurrentUserContext currentUserContext) { CurrentUserContext currentUserContext) {
this.userService = userService; this.userService = userService;
@ -68,8 +69,8 @@ public class UserController {
/** /**
* This endpoint retrieves multiple Users. If a userId can't be found in the database it will be * This endpoint retrieves multiple Users. If a userId can't be found in the database it will be
* ignored. If none of the given userIds is valid, the returned list will be empty. * ignored. If none of the given userIds is valid, the returned list will be empty. If currentUser
* If currentUser is set, the current User from the context will be retrieved as well * is set, the current User from the context will be retrieved as well
* *
* @title Get multiple Users * @title Get multiple Users
* @param request the HttpServletRequest of the request itself * @param request the HttpServletRequest of the request itself
@ -93,7 +94,10 @@ public class UserController {
} }
if (currentUser != null) { if (currentUser != null) {
QueryParamsValidator.checkExactParam(request, "current-user"); if (QueryParamsValidator.hasQueryParameterValues(request, "current-user")) {
throw new InvalidArgumentException(
"It is prohibited to use the param current-user with values.");
}
users.add(userService.getUser(this.currentUserContext.getUserid())); users.add(userService.getUser(this.currentUserContext.getUserid()));
} }

View File

@ -153,11 +153,11 @@ class TaskControllerIntTest {
attachmentRepresentationModel.setObjectReference(getObjectReferenceResourceSample()); attachmentRepresentationModel.setObjectReference(getObjectReferenceResourceSample());
ClassificationSummaryRepresentationModel classificationSummaryRepresentationModel = ClassificationSummaryRepresentationModel classificationSummaryRepresentationModel =
new ClassificationSummaryRepresentationModel(); new ClassificationSummaryRepresentationModel();
classificationSummaryRepresentationModel classificationSummaryRepresentationModel.setClassificationId(
.setClassificationId("CLI:100000000000000000000000000000000004"); "CLI:100000000000000000000000000000000004");
classificationSummaryRepresentationModel.setKey("L11010"); classificationSummaryRepresentationModel.setKey("L11010");
attachmentRepresentationModel attachmentRepresentationModel.setClassificationSummary(
.setClassificationSummary(classificationSummaryRepresentationModel); classificationSummaryRepresentationModel);
return attachmentRepresentationModel; return attachmentRepresentationModel;
} }
@ -1194,8 +1194,11 @@ class TaskControllerIntTest {
@CsvSource({ @CsvSource({
"owner=user-1-1, 10", "owner=user-1-1, 10",
"owner-is-null, 65", "owner-is-null, 65",
"owner-is-null=true, 65",
"owner-is-null&owner=user-1-1, 75", "owner-is-null&owner=user-1-1, 75",
"owner-is-null=TRUE&owner=user-1-1, 75",
"state=READY&owner-is-null&owner=user-1-1, 56", "state=READY&owner-is-null&owner=user-1-1, 56",
"state=READY&owner-is-null=TrUe&owner=user-1-1, 56",
}) })
void should_ReturnTasksWithVariousOwnerParameters_When_GettingTasks( void should_ReturnTasksWithVariousOwnerParameters_When_GettingTasks(
String queryParams, int expectedSize) { String queryParams, int expectedSize) {
@ -1214,7 +1217,9 @@ class TaskControllerIntTest {
List<Pair<String, String>> list = List<Pair<String, String>> list =
List.of( List.of(
Pair.of("When owner-is-null=", "?owner-is-null="), Pair.of("When owner-is-null=", "?owner-is-null="),
Pair.of("When owner-is-null=anyValue", "?owner-is-null=anyValue1,anyValue2")); Pair.of("When owner-is-null=owner-is-null", "?owner-is-null=owner-is-null"),
Pair.of(
"When owner-is-null=anyValue1,anyValue2", "?owner-is-null=anyValue1,anyValue2"));
ThrowingConsumer<Pair<String, String>> testOwnerIsNull = ThrowingConsumer<Pair<String, String>> testOwnerIsNull =
t -> { t -> {
String url = restHelper.toUrl(RestEndpoints.URL_TASKS) + t.getRight(); String url = restHelper.toUrl(RestEndpoints.URL_TASKS) + t.getRight();
@ -1382,9 +1387,7 @@ class TaskControllerIntTest {
@Test @Test
void should_GetAllTasksWithComments_When_FilteringByHasCommentsIsSetToTrue() { void should_GetAllTasksWithComments_When_FilteringByHasCommentsIsSetToTrue() {
String url = String url = restHelper.toUrl(RestEndpoints.URL_TASKS) + "?has-comments=true";
restHelper.toUrl(RestEndpoints.URL_TASKS)
+ "?has-comments=true";
HttpEntity<String> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1")); HttpEntity<String> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));
ResponseEntity<TaskSummaryPagedRepresentationModel> response = ResponseEntity<TaskSummaryPagedRepresentationModel> response =
@ -1393,7 +1396,8 @@ class TaskControllerIntTest {
assertThat(response.getBody()).isNotNull(); assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getContent()) assertThat(response.getBody().getContent())
.extracting(TaskSummaryRepresentationModel::getTaskId) .extracting(TaskSummaryRepresentationModel::getTaskId)
.containsExactlyInAnyOrder("TKI:000000000000000000000000000000000000", .containsExactlyInAnyOrder(
"TKI:000000000000000000000000000000000000",
"TKI:000000000000000000000000000000000001", "TKI:000000000000000000000000000000000001",
"TKI:000000000000000000000000000000000002", "TKI:000000000000000000000000000000000002",
"TKI:000000000000000000000000000000000004", "TKI:000000000000000000000000000000000004",
@ -1404,9 +1408,7 @@ class TaskControllerIntTest {
@Test @Test
void should_GetAllTasksWithoutComments_When_FilteringByHasCommentsIsSetToFalse() { void should_GetAllTasksWithoutComments_When_FilteringByHasCommentsIsSetToFalse() {
String url = String url = restHelper.toUrl(RestEndpoints.URL_TASKS) + "?has-comments=false";
restHelper.toUrl(RestEndpoints.URL_TASKS)
+ "?has-comments=false";
HttpEntity<String> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1")); HttpEntity<String> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));
ResponseEntity<TaskSummaryPagedRepresentationModel> response = ResponseEntity<TaskSummaryPagedRepresentationModel> response =
@ -1415,7 +1417,8 @@ class TaskControllerIntTest {
assertThat(response.getBody()).isNotNull(); assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getContent()) assertThat(response.getBody().getContent())
.extracting(TaskSummaryRepresentationModel::getTaskId) .extracting(TaskSummaryRepresentationModel::getTaskId)
.doesNotContain("TKI:000000000000000000000000000000000000", .doesNotContain(
"TKI:000000000000000000000000000000000000",
"TKI:000000000000000000000000000000000001", "TKI:000000000000000000000000000000000001",
"TKI:000000000000000000000000000000000002", "TKI:000000000000000000000000000000000002",
"TKI:000000000000000000000000000000000004", "TKI:000000000000000000000000000000000004",
@ -1826,8 +1829,7 @@ class TaskControllerIntTest {
@Test @Test
void should_ThrowError_When_UpdatingTaskWithBadAttachment() { void should_ThrowError_When_UpdatingTaskWithBadAttachment() {
String url = String url =
restHelper.toUrl(RestEndpoints.URL_TASKS_ID, restHelper.toUrl(RestEndpoints.URL_TASKS_ID, "TKI:100000000000000000000000000000000000");
"TKI:100000000000000000000000000000000000");
HttpEntity<Object> httpEntityWithoutBody = HttpEntity<Object> httpEntityWithoutBody =
new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1")); new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));
@ -1840,7 +1842,6 @@ class TaskControllerIntTest {
attachmentRepresentationModel.setTaskId(originalTask.getTaskId() + "wrongId"); attachmentRepresentationModel.setTaskId(originalTask.getTaskId() + "wrongId");
originalTask.setAttachments(Lists.newArrayList(attachmentRepresentationModel)); originalTask.setAttachments(Lists.newArrayList(attachmentRepresentationModel));
HttpEntity<TaskRepresentationModel> httpEntity = HttpEntity<TaskRepresentationModel> httpEntity =
new HttpEntity<>(originalTask, RestHelper.generateHeadersForUser("teamlead-1")); new HttpEntity<>(originalTask, RestHelper.generateHeadersForUser("teamlead-1"));
@ -2048,8 +2049,7 @@ class TaskControllerIntTest {
} }
@TestFactory @TestFactory
Stream<DynamicTest> Stream<DynamicTest> should_ReturnFailedTasks_When_TransferringTasks() {
should_ReturnFailedTasks_When_TransferringTasks() {
Iterator<Pair<Boolean, String>> iterator = Iterator<Pair<Boolean, String>> iterator =
Arrays.asList(Pair.of(true, "user-1-1"), Pair.of(false, "user-1-2")).iterator(); Arrays.asList(Pair.of(true, "user-1-1"), Pair.of(false, "user-1-2")).iterator();

View File

@ -31,7 +31,7 @@ class UserControllerIntTest {
} }
@Test @Test
void should_ReturnExistingUser() throws Exception { void should_ReturnExistingUser() {
String url = restHelper.toUrl(RestEndpoints.URL_USERS_ID, "TEAMLEAD-1"); String url = restHelper.toUrl(RestEndpoints.URL_USERS_ID, "TEAMLEAD-1");
HttpEntity<?> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1")); HttpEntity<?> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));
@ -45,7 +45,7 @@ class UserControllerIntTest {
} }
@Test @Test
void should_ReturnExistingUsers() throws Exception { void should_ReturnExistingUsers() {
String url = restHelper.toUrl(RestEndpoints.URL_USERS) + "?user-id=user-1-1&user-id=USER-1-2"; String url = restHelper.toUrl(RestEndpoints.URL_USERS) + "?user-id=user-1-1&user-id=USER-1-2";
HttpEntity<?> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1")); HttpEntity<?> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));
@ -134,8 +134,9 @@ class UserControllerIntTest {
} }
@Test @Test
void should_ReturnExistingUsersAndCurrentUser() throws Exception { void should_ReturnExistingUsersAndCurrentUser() {
String url = restHelper.toUrl(RestEndpoints.URL_USERS) String url =
restHelper.toUrl(RestEndpoints.URL_USERS)
+ "?user-id=user-1-1&user-id=USER-1-2&current-user"; + "?user-id=user-1-1&user-id=USER-1-2&current-user";
HttpEntity<?> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1")); HttpEntity<?> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));
@ -154,7 +155,7 @@ class UserControllerIntTest {
} }
@Test @Test
void should_ReturnExistingUsers_When_ParameterContainsDuplicateAndInvalidIds() throws Exception { void should_ReturnExistingUsers_When_ParameterContainsDuplicateAndInvalidIds() {
// also testing different query parameter format // also testing different query parameter format
String url = String url =
restHelper.toUrl(RestEndpoints.URL_USERS) restHelper.toUrl(RestEndpoints.URL_USERS)
@ -182,8 +183,7 @@ class UserControllerIntTest {
} }
@Test @Test
void should_CreateValidUser_When_CallingCreateEndpointWithAllAttributesExceptDomains() void should_CreateValidUser_When_CallingCreateEndpoint() {
throws Exception {
UserRepresentationModel newUser = new UserRepresentationModel(); UserRepresentationModel newUser = new UserRepresentationModel();
newUser.setUserId("12345"); newUser.setUserId("12345");
newUser.setGroups(Set.of("group1", "group2")); newUser.setGroups(Set.of("group1", "group2"));
@ -262,7 +262,7 @@ class UserControllerIntTest {
} }
@Test @Test
void should_UpdateExistingUser_When_CallingUpdateEndpoint() throws Exception { void should_UpdateExistingUser_When_CallingUpdateEndpoint() {
String url = restHelper.toUrl(RestEndpoints.URL_USERS_ID, "teamlead-1"); String url = restHelper.toUrl(RestEndpoints.URL_USERS_ID, "teamlead-1");
HttpEntity<?> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1")); HttpEntity<?> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));