TSK-1038: added WAIAlreadyExistsException to missing operations with access Items

This commit is contained in:
Mustapha Zorgati 2020-01-26 17:14:20 +01:00
parent bb315ea236
commit 9b61abda37
7 changed files with 125 additions and 97 deletions

View File

@ -156,15 +156,26 @@ public interface WorkbasketService {
* Setting up the new WorkbasketAccessItems for a Workbasket. Already stored values will be
* completely replaced by the current ones.
*
* <p>Preconditions for each {@link WorkbasketAccessItem} in {@code wbAccessItems}:
*
* <ul>
* <li>{@link WorkbasketAccessItem#getWorkbasketId()} is not null
* <li>{@link WorkbasketAccessItem#getWorkbasketId()} is equal to {@code workbasketId}
* <li>{@link WorkbasketAccessItem#getAccessId()} is unique
* </ul>
*
* @param workbasketId ID of the access-target workbasket.
* @param wbAccessItems List of WorkbasketAccessItems which does replace all current stored ones.
* @throws InvalidArgumentException will be thrown when the parameter is NULL or member doesn´t
* match the preconditions
* @throws InvalidArgumentException will be thrown when the parameter {@code wbAccessItems} is
* NULL or member doesn't match the preconditions
* @throws NotAuthorizedException if the current user is not member of role BUSINESS_ADMIN or
* ADMIN
* @throws WorkbasketAccessItemAlreadyExistException if {@code wbAccessItems} contains multiple
* accessItems with the same accessId.
*/
void setWorkbasketAccessItems(String workbasketId, List<WorkbasketAccessItem> wbAccessItems)
throws InvalidArgumentException, NotAuthorizedException;
throws InvalidArgumentException, NotAuthorizedException,
WorkbasketAccessItemAlreadyExistException;
/**
* This method provides a query builder for querying the database.

View File

@ -5,14 +5,11 @@ import pro.taskana.WorkbasketAccessItem;
public class WorkbasketAccessItemAlreadyExistException extends TaskanaException {
private static final long serialVersionUID = 4716611657569005013L;
public WorkbasketAccessItemAlreadyExistException(WorkbasketAccessItem workbasketAccessItem) {
public WorkbasketAccessItemAlreadyExistException(WorkbasketAccessItem accessItem) {
super(
"WorkbasketAccessItem for accessId "
+ workbasketAccessItem.getAccessId()
+ " and WorkbasketId "
+ workbasketAccessItem.getWorkbasketId()
+ ", WorkbasketKey "
+ workbasketAccessItem.getWorkbasketKey()
+ " exists already.");
String.format(
"WorkbasketAccessItem for accessId '%s' "
+ "and WorkbasketId '%s', WorkbasketKey '%s' exists already.",
accessItem.getAccessId(), accessItem.getWorkbasketId(), accessItem.getWorkbasketKey()));
}
}

View File

@ -3,9 +3,10 @@ package pro.taskana.impl;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import org.apache.ibatis.exceptions.PersistenceException;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -199,15 +200,16 @@ public class WorkbasketServiceImpl implements WorkbasketService {
"WorkbasketAccessItem %s refers to a not existing workbasket",
workbasketAccessItem));
}
try {
workbasketAccessMapper.insert(accessItem);
LOGGER.debug(
"Method createWorkbasketAccessItem() created workbaskteAccessItem {}", accessItem);
} catch (PersistenceException e) {
LOGGER.warn(
"when trying to insert WorkbasketAccessItem {} caught exception {}", accessItem, e);
boolean accessIdAlreadyExists =
getWorkbasketAccessItems(workbasketAccessItem.getWorkbasketId()).stream()
.map(WorkbasketAccessItem::getAccessId)
.anyMatch(i -> i.equals(workbasketAccessItem.getAccessId()));
if (accessIdAlreadyExists) {
throw new WorkbasketAccessItemAlreadyExistException(accessItem);
}
workbasketAccessMapper.insert(accessItem);
LOGGER.debug(
"Method createWorkbasketAccessItem() created workbaskteAccessItem {}", accessItem);
return accessItem;
} finally {
taskanaEngine.returnConnection();
@ -394,51 +396,47 @@ public class WorkbasketServiceImpl implements WorkbasketService {
@Override
public void setWorkbasketAccessItems(
String workbasketId, List<WorkbasketAccessItem> wbAccessItems)
throws InvalidArgumentException, NotAuthorizedException {
throws InvalidArgumentException, NotAuthorizedException,
WorkbasketAccessItemAlreadyExistException {
LOGGER.debug(
"entry to setWorkbasketAccessItems(workbasketAccessItems = {})", wbAccessItems.toString());
taskanaEngine.getEngine().checkRoleMembership(TaskanaRole.BUSINESS_ADMIN, TaskanaRole.ADMIN);
List<WorkbasketAccessItemImpl> newItems = new ArrayList<>();
try {
taskanaEngine.openConnection();
// Check pre-conditions and set ID
if (!wbAccessItems.isEmpty()) {
for (WorkbasketAccessItem workbasketAccessItem : wbAccessItems) {
WorkbasketAccessItemImpl wbAccessItemImpl =
(WorkbasketAccessItemImpl) workbasketAccessItem;
if (wbAccessItemImpl.getWorkbasketId() == null) {
throw new InvalidArgumentException(
String.format(
"Checking the preconditions of the current WorkbasketAccessItem failed "
+ "- WBID is NULL. WorkbasketAccessItem=%s",
workbasketAccessItem));
} else if (!wbAccessItemImpl.getWorkbasketId().equals(workbasketId)) {
throw new InvalidArgumentException(
String.format(
"Checking the preconditions of the current WorkbasketAccessItem failed "
+ "- the WBID does not match. Target-WBID=''%s'' WorkbasketAccessItem=%s",
workbasketId, workbasketAccessItem));
}
if (wbAccessItemImpl.getId() == null || wbAccessItemImpl.getId().isEmpty()) {
wbAccessItemImpl.setId(
IdGenerator.generateWithPrefix(ID_PREFIX_WORKBASKET_AUTHORIZATION));
}
newItems.add(wbAccessItemImpl);
}
}
// delete all current ones
workbasketAccessMapper.deleteAllAccessItemsForWorkbasketId(workbasketId);
// add all
if (!newItems.isEmpty()) {
newItems.forEach(item -> workbasketAccessMapper.insert(item));
Set<String> ids = new HashSet<>();
for (WorkbasketAccessItem workbasketAccessItem : wbAccessItems) {
WorkbasketAccessItemImpl wbAccessItemImpl = (WorkbasketAccessItemImpl) workbasketAccessItem;
// Check pre-conditions and set ID
if (wbAccessItemImpl.getWorkbasketId() == null) {
throw new InvalidArgumentException(
String.format(
"Checking the preconditions of the current WorkbasketAccessItem failed "
+ "- WBID is NULL. WorkbasketAccessItem=%s",
workbasketAccessItem));
} else if (!wbAccessItemImpl.getWorkbasketId().equals(workbasketId)) {
throw new InvalidArgumentException(
String.format(
"Checking the preconditions of the current WorkbasketAccessItem failed "
+ "- the WBID does not match. Target-WBID=''%s'' WorkbasketAccessItem=%s",
workbasketId, workbasketAccessItem));
}
if (wbAccessItemImpl.getId() == null || wbAccessItemImpl.getId().isEmpty()) {
wbAccessItemImpl.setId(
IdGenerator.generateWithPrefix(ID_PREFIX_WORKBASKET_AUTHORIZATION));
}
if (ids.contains(wbAccessItemImpl.getAccessId())) {
throw new WorkbasketAccessItemAlreadyExistException(wbAccessItemImpl);
}
ids.add(wbAccessItemImpl.getAccessId());
workbasketAccessMapper.insert(wbAccessItemImpl);
}
} finally {
taskanaEngine.returnConnection();
LOGGER.debug(
"exit from setWorkbasketAccessItems(workbasketAccessItems = {})",
wbAccessItems.toString());
LOGGER.debug("exit from setWorkbasketAccessItems(workbasketAccessItems = {})", wbAccessItems);
}
}
@ -699,37 +697,6 @@ public class WorkbasketServiceImpl implements WorkbasketService {
}
}
private void validateWorkbasketId(String workbasketId) throws InvalidArgumentException {
if (workbasketId == null) {
throw new InvalidArgumentException(
"The WorkbasketId can´t be NULL");
}
if (workbasketId.isEmpty()) {
throw new InvalidArgumentException(
"The WorkbasketId can´t be EMPTY for deleteWorkbasket()");
}
}
private long getCountTasksByWorkbasketId(String workbasketId) {
return taskanaEngine
.getEngine()
.getTaskService()
.createTaskQuery()
.workbasketIdIn(workbasketId)
.count();
}
private long getCountTasksNotCompletedByWorkbasketId(String workbasketId) {
return taskanaEngine
.getEngine()
.getTaskService()
.createTaskQuery()
.workbasketIdIn(workbasketId)
.stateNotIn(TaskState.COMPLETED)
.count();
}
public BulkOperationResults<String, TaskanaException> deleteWorkbaskets(
List<String> workbasketsIds) throws NotAuthorizedException, InvalidArgumentException {
if (LOGGER.isDebugEnabled()) {
@ -854,6 +821,35 @@ public class WorkbasketServiceImpl implements WorkbasketService {
}
}
private void validateWorkbasketId(String workbasketId) throws InvalidArgumentException {
if (workbasketId == null) {
throw new InvalidArgumentException("The WorkbasketId can´t be NULL");
}
if (workbasketId.isEmpty()) {
throw new InvalidArgumentException("The WorkbasketId can´t be EMPTY for deleteWorkbasket()");
}
}
private long getCountTasksByWorkbasketId(String workbasketId) {
return taskanaEngine
.getEngine()
.getTaskService()
.createTaskQuery()
.workbasketIdIn(workbasketId)
.count();
}
private long getCountTasksNotCompletedByWorkbasketId(String workbasketId) {
return taskanaEngine
.getEngine()
.getTaskService()
.createTaskQuery()
.workbasketIdIn(workbasketId)
.stateNotIn(TaskState.COMPLETED)
.count();
}
private boolean skipAuthorizationCheck() {
// Skip permission check is security is not enabled

View File

@ -11,8 +11,6 @@ import org.junit.jupiter.api.extension.ExtendWith;
import pro.taskana.WorkbasketAccessItem;
import pro.taskana.WorkbasketService;
import pro.taskana.exceptions.InvalidArgumentException;
import pro.taskana.exceptions.NotAuthorizedException;
import pro.taskana.security.JaasExtension;
import pro.taskana.security.WithAccessId;
@ -28,8 +26,7 @@ public class UpdateWorkbasketAuthorizations2AccTest extends AbstractAccTest {
userName = "teamlead_1",
groupNames = {"group_1", "businessadmin"})
@Test
void testUpdatedAccessItemListToEmptyList()
throws InvalidArgumentException, NotAuthorizedException {
void testUpdatedAccessItemListToEmptyList() throws Exception {
WorkbasketService workbasketService = taskanaEngine.getWorkbasketService();
final String wbId = "WBI:100000000000000000000000000000000004";
List<WorkbasketAccessItem> accessItems = workbasketService.getWorkbasketAccessItems(wbId);

View File

@ -170,7 +170,7 @@ class UpdateWorkbasketAuthorizationsAccTest extends AbstractAccTest {
userName = "teamlead_1",
groupNames = {"group_1", "businessadmin"})
@Test
void testUpdatedAccessItemList() throws InvalidArgumentException, NotAuthorizedException {
void testUpdatedAccessItemList() throws Exception {
WorkbasketService workbasketService = taskanaEngine.getWorkbasketService();
final String wbId = "WBI:100000000000000000000000000000000004";
List<WorkbasketAccessItem> accessItems = workbasketService.getWorkbasketAccessItems(wbId);
@ -210,7 +210,7 @@ class UpdateWorkbasketAuthorizationsAccTest extends AbstractAccTest {
userName = "teamlead_1",
groupNames = {"group_1", "businessadmin"})
@Test
void testInsertAccessItemList() throws InvalidArgumentException, NotAuthorizedException {
void testInsertAccessItemList() throws Exception {
WorkbasketService workbasketService = taskanaEngine.getWorkbasketService();
final String wbId = "WBI:100000000000000000000000000000000004";
List<WorkbasketAccessItem> accessItems = workbasketService.getWorkbasketAccessItems(wbId);
@ -248,8 +248,7 @@ class UpdateWorkbasketAuthorizationsAccTest extends AbstractAccTest {
userName = "teamlead_1",
groupNames = {"group_1", "businessadmin"})
@Test
void testDeleteAccessItemForAccessItemId()
throws NotAuthorizedException, InvalidArgumentException {
void testDeleteAccessItemForAccessItemId() throws Exception {
WorkbasketService workbasketService = taskanaEngine.getWorkbasketService();
final String wbId = "WBI:100000000000000000000000000000000001";
@ -276,9 +275,7 @@ class UpdateWorkbasketAuthorizationsAccTest extends AbstractAccTest {
new ArrayList<>(workbasketService.getWorkbasketAccessItems(wbId));
// with DB2 V 11, the lists are sorted differently...
assertEquals(
new HashSet<WorkbasketAccessItem>(originalList),
new HashSet<WorkbasketAccessItem>(listEqualToOriginal));
assertEquals(new HashSet<>(originalList), new HashSet<>(listEqualToOriginal));
}
@WithAccessId(

View File

@ -1,5 +1,6 @@
package pro.taskana.impl;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.startsWith;
import static org.hamcrest.core.IsEqual.equalTo;
@ -15,6 +16,8 @@ import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -28,11 +31,13 @@ import pro.taskana.TaskQuery;
import pro.taskana.TaskService;
import pro.taskana.TaskanaEngine;
import pro.taskana.Workbasket;
import pro.taskana.WorkbasketAccessItem;
import pro.taskana.WorkbasketType;
import pro.taskana.configuration.TaskanaEngineConfiguration;
import pro.taskana.exceptions.DomainNotFoundException;
import pro.taskana.exceptions.InvalidWorkbasketException;
import pro.taskana.exceptions.NotAuthorizedException;
import pro.taskana.exceptions.WorkbasketAccessItemAlreadyExistException;
import pro.taskana.exceptions.WorkbasketAlreadyExistException;
import pro.taskana.exceptions.WorkbasketNotFoundException;
import pro.taskana.mappings.DistributionTargetMapper;
@ -172,6 +177,20 @@ class WorkbasketServiceImplTest {
taskanaEngineConfigurationMock);
}
@Test
void testSetWorkbasketAccessItemsWithMultipleAccessIds() throws Exception {
String wid = "workbasketId";
List<WorkbasketAccessItem> accessItems =
IntStream.rangeClosed(0, 10)
.mapToObj(i -> createWorkbasketAccessItem("id" + i, "access" + i, wid))
.collect(Collectors.toList());
accessItems.add(createWorkbasketAccessItem("id5", "access5", wid));
assertThatThrownBy(() -> workbasketServiceSpy.setWorkbasketAccessItems(wid, accessItems))
.isInstanceOf(WorkbasketAccessItemAlreadyExistException.class);
}
private WorkbasketImpl createTestWorkbasket(String id, String key) {
WorkbasketImpl workbasket = new WorkbasketImpl();
workbasket.setId(id);
@ -195,4 +214,13 @@ class WorkbasketServiceImplTest {
}
return distributionsTargets;
}
private WorkbasketAccessItem createWorkbasketAccessItem(
String id, String accessId, String workbasketId) {
WorkbasketAccessItemImpl workbasketAccessItem = new WorkbasketAccessItemImpl();
workbasketAccessItem.setId(id);
workbasketAccessItem.setAccessId(accessId);
workbasketAccessItem.setWorkbasketId(workbasketId);
return workbasketAccessItem;
}
}

View File

@ -32,6 +32,7 @@ import pro.taskana.exceptions.DomainNotFoundException;
import pro.taskana.exceptions.InvalidArgumentException;
import pro.taskana.exceptions.InvalidWorkbasketException;
import pro.taskana.exceptions.NotAuthorizedException;
import pro.taskana.exceptions.WorkbasketAccessItemAlreadyExistException;
import pro.taskana.exceptions.WorkbasketAlreadyExistException;
import pro.taskana.exceptions.WorkbasketInUseException;
import pro.taskana.exceptions.WorkbasketNotFoundException;
@ -142,7 +143,7 @@ public class WorkbasketController extends AbstractPagingController {
throws NotAuthorizedException, InvalidArgumentException, WorkbasketNotFoundException,
WorkbasketInUseException {
LOGGER.debug("Entry to markWorkbasketForDeletion(workbasketId= {})", workbasketId);
//http status code accepted because workbaskets will not be deleted immediately
// http status code accepted because workbaskets will not be deleted immediately
ResponseEntity<?> response =
ResponseEntity.accepted().body(workbasketService.deleteWorkbasket(workbasketId));
LOGGER.debug("Exit from markWorkbasketForDeletion(), returning {}", response);
@ -224,7 +225,8 @@ public class WorkbasketController extends AbstractPagingController {
public ResponseEntity<WorkbasketAccessItemListResource> setWorkbasketAccessItems(
@PathVariable(value = "workbasketId") String workbasketId,
@RequestBody List<WorkbasketAccessItemResource> workbasketAccessResourceItems)
throws NotAuthorizedException, InvalidArgumentException, WorkbasketNotFoundException {
throws NotAuthorizedException, InvalidArgumentException, WorkbasketNotFoundException,
WorkbasketAccessItemAlreadyExistException {
LOGGER.debug("Entry to setWorkbasketAccessItems(workbasketId= {})", workbasketId);
if (workbasketAccessResourceItems == null) {
throw new InvalidArgumentException("Can´t create something with NULL body-value.");