TSK-415 TaskQuery.count() does not filter out tasks in hidden workbaskets
This commit is contained in:
parent
ead7b9a3a0
commit
a321d275ed
|
@ -8,7 +8,7 @@ import pro.taskana.TaskState;
|
||||||
public class MinimalTaskSummary {
|
public class MinimalTaskSummary {
|
||||||
|
|
||||||
private String taskId;
|
private String taskId;
|
||||||
private String workbasketKey;
|
private String workbasketId;
|
||||||
private TaskState taskState;
|
private TaskState taskState;
|
||||||
|
|
||||||
MinimalTaskSummary() {
|
MinimalTaskSummary() {
|
||||||
|
@ -23,12 +23,12 @@ public class MinimalTaskSummary {
|
||||||
this.taskId = taskId;
|
this.taskId = taskId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getWorkbasketKey() {
|
public String getWorkbasketId() {
|
||||||
return workbasketKey;
|
return workbasketId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setWorkbasketKey(String workbasketKey) {
|
public void setWorkbasketId(String workbasketKey) {
|
||||||
this.workbasketKey = workbasketKey;
|
this.workbasketId = workbasketKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TaskState getTaskState() {
|
public TaskState getTaskState() {
|
||||||
|
@ -44,8 +44,8 @@ public class MinimalTaskSummary {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append("MinimalTaskSummary [taskId=");
|
builder.append("MinimalTaskSummary [taskId=");
|
||||||
builder.append(taskId);
|
builder.append(taskId);
|
||||||
builder.append(", workbasketKey=");
|
builder.append(", workbasketId=");
|
||||||
builder.append(workbasketKey);
|
builder.append(workbasketId);
|
||||||
builder.append(", taskState=");
|
builder.append(", taskState=");
|
||||||
builder.append(taskState);
|
builder.append(taskState);
|
||||||
builder.append("]");
|
builder.append("]");
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package pro.taskana.impl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class keeps a count of tasks that are contained in a workbasket.
|
||||||
|
*
|
||||||
|
* @author bbr
|
||||||
|
*/
|
||||||
|
public class TaskCountPerWorkbasket {
|
||||||
|
|
||||||
|
Integer taskCount;
|
||||||
|
String workbasketId;
|
||||||
|
|
||||||
|
public Integer getTaskCount() {
|
||||||
|
return taskCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTaskCount(Integer taskCount) {
|
||||||
|
this.taskCount = taskCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getWorkbasketId() {
|
||||||
|
return workbasketId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWorkbasketId(String workbasketId) {
|
||||||
|
this.workbasketId = workbasketId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -3,6 +3,8 @@ package pro.taskana.impl;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.ibatis.exceptions.PersistenceException;
|
import org.apache.ibatis.exceptions.PersistenceException;
|
||||||
import org.apache.ibatis.session.RowBounds;
|
import org.apache.ibatis.session.RowBounds;
|
||||||
|
@ -18,6 +20,7 @@ import pro.taskana.TaskanaEngine;
|
||||||
import pro.taskana.TaskanaRole;
|
import pro.taskana.TaskanaRole;
|
||||||
import pro.taskana.TimeInterval;
|
import pro.taskana.TimeInterval;
|
||||||
import pro.taskana.WorkbasketPermission;
|
import pro.taskana.WorkbasketPermission;
|
||||||
|
import pro.taskana.WorkbasketSummary;
|
||||||
import pro.taskana.exceptions.InvalidArgumentException;
|
import pro.taskana.exceptions.InvalidArgumentException;
|
||||||
import pro.taskana.exceptions.NotAuthorizedException;
|
import pro.taskana.exceptions.NotAuthorizedException;
|
||||||
import pro.taskana.exceptions.NotAuthorizedToQueryWorkbasketException;
|
import pro.taskana.exceptions.NotAuthorizedToQueryWorkbasketException;
|
||||||
|
@ -31,7 +34,7 @@ import pro.taskana.impl.util.LoggerUtils;
|
||||||
public class TaskQueryImpl implements TaskQuery {
|
public class TaskQueryImpl implements TaskQuery {
|
||||||
|
|
||||||
private static final String LINK_TO_MAPPER = "pro.taskana.mappings.QueryMapper.queryTaskSummaries";
|
private static final String LINK_TO_MAPPER = "pro.taskana.mappings.QueryMapper.queryTaskSummaries";
|
||||||
private static final String LINK_TO_COUNTER = "pro.taskana.mappings.QueryMapper.countQueryTasks";
|
private static final String LINK_TO_TASK_COUNT_PER_WORKBASKET = "pro.taskana.mappings.QueryMapper.queryTaskCountPerWorkbasket";
|
||||||
private static final String LINK_TO_VALUEMAPPER = "pro.taskana.mappings.QueryMapper.queryTaskColumnValues";
|
private static final String LINK_TO_VALUEMAPPER = "pro.taskana.mappings.QueryMapper.queryTaskColumnValues";
|
||||||
private static final String TIME_INTERVAL = "TimeInterval ";
|
private static final String TIME_INTERVAL = "TimeInterval ";
|
||||||
private static final String IS_INVALID = " is invalid.";
|
private static final String IS_INVALID = " is invalid.";
|
||||||
|
@ -804,14 +807,36 @@ public class TaskQueryImpl implements TaskQuery {
|
||||||
try {
|
try {
|
||||||
taskanaEngine.openConnection();
|
taskanaEngine.openConnection();
|
||||||
checkOpenPermissionForSpecifiedWorkbaskets();
|
checkOpenPermissionForSpecifiedWorkbaskets();
|
||||||
rowCount = taskanaEngine.getSqlSession().selectOne(LINK_TO_COUNTER, this);
|
List<TaskCountPerWorkbasket> taskCounts = taskanaEngine.getSqlSession()
|
||||||
return (rowCount == null) ? 0L : rowCount;
|
.selectList(LINK_TO_TASK_COUNT_PER_WORKBASKET, this);
|
||||||
|
return countTasksInAuthorizedWorkbaskets(taskCounts);
|
||||||
} finally {
|
} finally {
|
||||||
taskanaEngine.returnConnection();
|
taskanaEngine.returnConnection();
|
||||||
LOGGER.debug("exit from count(). Returning result {} ", rowCount);
|
LOGGER.debug("exit from count(). Returning result {} ", rowCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private long countTasksInAuthorizedWorkbaskets(List<TaskCountPerWorkbasket> taskCounts) {
|
||||||
|
Set<String> retrievedWorkbasketIds = taskCounts.stream().map(TaskCountPerWorkbasket::getWorkbasketId).collect(
|
||||||
|
Collectors.toSet());
|
||||||
|
// use WorkbasketQuery to filter for authorized WorkBaskets
|
||||||
|
WorkbasketQueryImpl query = (WorkbasketQueryImpl) taskanaEngine.getWorkbasketService().createWorkbasketQuery();
|
||||||
|
query.setUsedToAugmentTasks(true);
|
||||||
|
List<WorkbasketSummary> allowedWorkbaskets = query
|
||||||
|
.idIn(retrievedWorkbasketIds.toArray(new String[0]))
|
||||||
|
.list();
|
||||||
|
Set<String> authorizedWorkbasketIds = allowedWorkbaskets.stream().map(WorkbasketSummary::getId).collect(
|
||||||
|
Collectors.toSet());
|
||||||
|
|
||||||
|
long count = 0;
|
||||||
|
for (TaskCountPerWorkbasket taskCount : taskCounts) {
|
||||||
|
if (authorizedWorkbasketIds.contains(taskCount.getWorkbasketId())) {
|
||||||
|
count += taskCount.getTaskCount().intValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
private void checkOpenPermissionForSpecifiedWorkbaskets() {
|
private void checkOpenPermissionForSpecifiedWorkbaskets() {
|
||||||
if (taskanaEngine.isUserInRole(TaskanaRole.ADMIN)) {
|
if (taskanaEngine.isUserInRole(TaskanaRole.ADMIN)) {
|
||||||
LOGGER.debug("Skipping permissions check since user is in role ADMIN.");
|
LOGGER.debug("Skipping permissions check since user is in role ADMIN.");
|
||||||
|
|
|
@ -538,13 +538,13 @@ public class TaskServiceImpl implements TaskService {
|
||||||
List<MinimalTaskSummary> taskSummaries = taskMapper.findExistingTasks(taskIds);
|
List<MinimalTaskSummary> taskSummaries = taskMapper.findExistingTasks(taskIds);
|
||||||
|
|
||||||
// check source WB (read)+transfer
|
// check source WB (read)+transfer
|
||||||
Set<String> workbasketKeys = new HashSet<>();
|
Set<String> workbasketIds = new HashSet<>();
|
||||||
taskSummaries.stream().forEach(t -> workbasketKeys.add(t.getWorkbasketKey()));
|
taskSummaries.stream().forEach(t -> workbasketIds.add(t.getWorkbasketId()));
|
||||||
WorkbasketQueryImpl query = (WorkbasketQueryImpl) workbasketService.createWorkbasketQuery();
|
WorkbasketQueryImpl query = (WorkbasketQueryImpl) workbasketService.createWorkbasketQuery();
|
||||||
query.setUsedToAugmentTasks(true);
|
query.setUsedToAugmentTasks(true);
|
||||||
List<WorkbasketSummary> sourceWorkbaskets = query
|
List<WorkbasketSummary> sourceWorkbaskets = query
|
||||||
.callerHasPermission(WorkbasketPermission.TRANSFER)
|
.callerHasPermission(WorkbasketPermission.TRANSFER)
|
||||||
.keyIn(workbasketKeys.toArray(new String[0]))
|
.idIn(workbasketIds.toArray(new String[0]))
|
||||||
.list();
|
.list();
|
||||||
taskIdIterator = taskIds.iterator();
|
taskIdIterator = taskIds.iterator();
|
||||||
while (taskIdIterator.hasNext()) {
|
while (taskIdIterator.hasNext()) {
|
||||||
|
@ -558,7 +558,7 @@ public class TaskServiceImpl implements TaskService {
|
||||||
new TaskNotFoundException(currentTaskId, "Task with id " + currentTaskId + " was not found."));
|
new TaskNotFoundException(currentTaskId, "Task with id " + currentTaskId + " was not found."));
|
||||||
taskIdIterator.remove();
|
taskIdIterator.remove();
|
||||||
} else if (!sourceWorkbaskets.stream()
|
} else if (!sourceWorkbaskets.stream()
|
||||||
.anyMatch(wb -> taskSummary.getWorkbasketKey().equals(wb.getKey()))) {
|
.anyMatch(wb -> taskSummary.getWorkbasketId().equals(wb.getId()))) {
|
||||||
bulkLog.addError(currentTaskId,
|
bulkLog.addError(currentTaskId,
|
||||||
new NotAuthorizedException(
|
new NotAuthorizedException(
|
||||||
"The workbasket of this task got not TRANSFER permissions. TaskId=" + currentTaskId));
|
"The workbasket of this task got not TRANSFER permissions. TaskId=" + currentTaskId));
|
||||||
|
|
|
@ -10,6 +10,7 @@ import pro.taskana.impl.ClassificationQueryImpl;
|
||||||
import pro.taskana.impl.ClassificationSummaryImpl;
|
import pro.taskana.impl.ClassificationSummaryImpl;
|
||||||
import pro.taskana.impl.ObjectReference;
|
import pro.taskana.impl.ObjectReference;
|
||||||
import pro.taskana.impl.ObjectReferenceQueryImpl;
|
import pro.taskana.impl.ObjectReferenceQueryImpl;
|
||||||
|
import pro.taskana.impl.TaskCountPerWorkbasket;
|
||||||
import pro.taskana.impl.TaskQueryImpl;
|
import pro.taskana.impl.TaskQueryImpl;
|
||||||
import pro.taskana.impl.TaskSummaryImpl;
|
import pro.taskana.impl.TaskSummaryImpl;
|
||||||
import pro.taskana.impl.WorkbasketAccessItemImpl;
|
import pro.taskana.impl.WorkbasketAccessItemImpl;
|
||||||
|
@ -347,7 +348,7 @@ public interface QueryMapper {
|
||||||
@Result(property = "permCustom12", column = "PERM_CUSTOM_12")})
|
@Result(property = "permCustom12", column = "PERM_CUSTOM_12")})
|
||||||
List<WorkbasketAccessItemImpl> queryWorkbasketAccessItems(WorkbasketAccessItemQueryImpl accessItemQuery);
|
List<WorkbasketAccessItemImpl> queryWorkbasketAccessItems(WorkbasketAccessItemQueryImpl accessItemQuery);
|
||||||
|
|
||||||
@Select("<script>SELECT COUNT(ID) FROM TASK t "
|
@Select("<script> SELECT COUNT(t.ID) as TASK_COUNT , t.WORKBASKET_ID FROM TASK t "
|
||||||
+ "<where>"
|
+ "<where>"
|
||||||
+ "<if test='taskIds != null'>AND t.ID IN(<foreach item='item' collection='taskIds' separator=',' >#{item}</foreach>)</if> "
|
+ "<if test='taskIds != null'>AND t.ID IN(<foreach item='item' collection='taskIds' separator=',' >#{item}</foreach>)</if> "
|
||||||
+ "<if test='createdIn !=null'> AND ( <foreach item='item' collection='createdIn' separator=' OR ' > ( <if test='item.begin!=null'> t.CREATED >= #{item.begin} </if> <if test='item.begin!=null and item.end!=null'> AND </if><if test='item.end!=null'> t.CREATED <=#{item.end} </if>)</foreach>)</if> "
|
+ "<if test='createdIn !=null'> AND ( <foreach item='item' collection='createdIn' separator=' OR ' > ( <if test='item.begin!=null'> t.CREATED >= #{item.begin} </if> <if test='item.begin!=null and item.end!=null'> AND </if><if test='item.end!=null'> t.CREATED <=#{item.end} </if>)</foreach>)</if> "
|
||||||
|
@ -422,10 +423,13 @@ public interface QueryMapper {
|
||||||
+ "<if test='custom16In != null'>AND t.CUSTOM_10 IN(<foreach item='item' collection='custom16In' separator=',' >#{item}</foreach>)</if> "
|
+ "<if test='custom16In != null'>AND t.CUSTOM_10 IN(<foreach item='item' collection='custom16In' separator=',' >#{item}</foreach>)</if> "
|
||||||
+ "<if test='custom16Like != null'>AND (<foreach item='item' collection='custom16Like' separator=' OR '>UPPER(t.CUSTOM_10) LIKE #{item}</foreach>)</if> "
|
+ "<if test='custom16Like != null'>AND (<foreach item='item' collection='custom16Like' separator=' OR '>UPPER(t.CUSTOM_10) LIKE #{item}</foreach>)</if> "
|
||||||
+ "</where>"
|
+ "</where>"
|
||||||
+ "<if test='!orderBy.isEmpty()'>ORDER BY <foreach item='item' collection='orderBy' separator=',' >${item}</foreach></if> "
|
+ "GROUP BY WORKBASKET_ID "
|
||||||
+ "<if test=\"_databaseId == 'db2'\">with UR </if> "
|
+ "<if test=\"_databaseId == 'db2'\">with UR </if> "
|
||||||
+ "</script>")
|
+ "</script>")
|
||||||
Long countQueryTasks(TaskQueryImpl taskQuery);
|
@Results(value = {
|
||||||
|
@Result(property = "taskCount", column = "TASK_COUNT"),
|
||||||
|
@Result(property = "workbasketId", column = "WORKBASKET_ID")})
|
||||||
|
List<TaskCountPerWorkbasket> queryTaskCountPerWorkbasket(TaskQueryImpl taskQuery);
|
||||||
|
|
||||||
@Select("<script>SELECT COUNT(ID) FROM CLASSIFICATION "
|
@Select("<script>SELECT COUNT(ID) FROM CLASSIFICATION "
|
||||||
+ "<where>"
|
+ "<where>"
|
||||||
|
|
|
@ -236,13 +236,13 @@ public interface TaskMapper {
|
||||||
void updateCompleted(@Param("taskIds") List<String> taskIds,
|
void updateCompleted(@Param("taskIds") List<String> taskIds,
|
||||||
@Param("referencetask") TaskSummaryImpl referencetask);
|
@Param("referencetask") TaskSummaryImpl referencetask);
|
||||||
|
|
||||||
@Select("<script>SELECT ID, STATE, WORKBASKET_KEY FROM TASK "
|
@Select("<script>SELECT ID, STATE, WORKBASKET_ID FROM TASK "
|
||||||
+ "WHERE ID IN(<foreach item='item' collection='taskIds' separator=',' >#{item}</foreach>) "
|
+ "WHERE ID IN(<foreach item='item' collection='taskIds' separator=',' >#{item}</foreach>) "
|
||||||
+ "<if test=\"_databaseId == 'db2'\">with UR </if> "
|
+ "<if test=\"_databaseId == 'db2'\">with UR </if> "
|
||||||
+ "</script>")
|
+ "</script>")
|
||||||
@Results(value = {
|
@Results(value = {
|
||||||
@Result(property = "taskId", column = "ID"),
|
@Result(property = "taskId", column = "ID"),
|
||||||
@Result(property = "workbasketKey", column = "WORKBASKET_KEY"),
|
@Result(property = "workbasketId", column = "WORKBASKET_ID"),
|
||||||
@Result(property = "taskState", column = "STATE")})
|
@Result(property = "taskState", column = "STATE")})
|
||||||
List<MinimalTaskSummary> findExistingTasks(@Param("taskIds") List<String> taskIds);
|
List<MinimalTaskSummary> findExistingTasks(@Param("taskIds") List<String> taskIds);
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ import pro.taskana.AttachmentSummary;
|
||||||
import pro.taskana.BaseQuery.SortDirection;
|
import pro.taskana.BaseQuery.SortDirection;
|
||||||
import pro.taskana.KeyDomain;
|
import pro.taskana.KeyDomain;
|
||||||
import pro.taskana.Task;
|
import pro.taskana.Task;
|
||||||
|
import pro.taskana.TaskQuery;
|
||||||
import pro.taskana.TaskService;
|
import pro.taskana.TaskService;
|
||||||
import pro.taskana.TaskSummary;
|
import pro.taskana.TaskSummary;
|
||||||
import pro.taskana.exceptions.AttachmentPersistenceException;
|
import pro.taskana.exceptions.AttachmentPersistenceException;
|
||||||
|
@ -604,4 +605,21 @@ public class QueryTasksAccTest extends AbstractAccTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@WithAccessId(
|
||||||
|
userName = "user_1_1",
|
||||||
|
groupNames = {"group_1"})
|
||||||
|
@Test
|
||||||
|
public void testQueryAndCountMatch() {
|
||||||
|
TaskService taskService = taskanaEngine.getTaskService();
|
||||||
|
TaskQuery taskQuery = taskService.createTaskQuery();
|
||||||
|
List<TaskSummary> tasks = taskQuery
|
||||||
|
.nameIn("Task99", "Task01", "Widerruf")
|
||||||
|
.list();
|
||||||
|
long numberOfTasks = taskQuery
|
||||||
|
.nameIn("Task99", "Task01", "Widerruf")
|
||||||
|
.count();
|
||||||
|
Assert.assertEquals(numberOfTasks, tasks.size());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue