TSK-789: Workbasket export does not contain authorizations

This commit is contained in:
Jose Ignacio Recuerda Cambil 2019-02-20 17:59:17 +01:00 committed by Holger Hagen
parent efc121257d
commit bcf031c22d
6 changed files with 170 additions and 83 deletions

View File

@ -2,8 +2,14 @@ package pro.taskana.rest;
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -13,8 +19,10 @@ import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.io.FileSystemResource;
import org.springframework.hateoas.hal.Jackson2HalModule;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
@ -25,28 +33,27 @@ import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import pro.taskana.rest.resource.WorkbasketDefinition;
import pro.taskana.rest.resource.WorkbasketDefinitionResource;
/**
* Test workbasket definitions.
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = RestConfiguration.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@SpringBootTest(classes = RestConfiguration.class, webEnvironment = WebEnvironment.RANDOM_PORT)
public class WorkbasketDefinitionControllerIntTest {
private static final Logger LOGGER = LoggerFactory.getLogger(ClassificationController.class);
private String server = "http://127.0.0.1:";
RestTemplate template;
private RestTemplate template;
private HttpEntity<String> request;
private HttpHeaders headers = new HttpHeaders();
private ObjectMapper objMapper = new ObjectMapper();
@LocalServerPort
int port;
private int port;
@Before
public void before() {
@ -57,27 +64,73 @@ public class WorkbasketDefinitionControllerIntTest {
}
@Test
public void exportWorkbasketFromDomain() {
ResponseEntity<List<WorkbasketDefinition>> response = template.exchange(
this.server + this.port + "/v1/workbasket-definitions?domain=DOMAIN_A",
HttpMethod.GET, request, new ParameterizedTypeReference<List<WorkbasketDefinition>>() {
public void testExportWorkbasketFromDomain() {
ResponseEntity<List<WorkbasketDefinitionResource>> response = template.exchange(
server + port + "/v1/workbasket-definitions?domain=DOMAIN_A", HttpMethod.GET, request,
new ParameterizedTypeReference<List<WorkbasketDefinitionResource>>() {
});
assertNotNull(response.getBody());
assertEquals(HttpStatus.OK, response.getStatusCode());
assertThat(response.getBody().get(0), instanceOf(WorkbasketDefinition.class));
assertEquals(11, response.getBody().size());
assertThat(response.getBody().get(0), instanceOf(WorkbasketDefinitionResource.class));
boolean allAuthorizationsAreEmpty = true, allDistributionTargetsAreEmpty = true;
for (WorkbasketDefinitionResource workbasketDefinition : response.getBody()) {
if (allAuthorizationsAreEmpty && !workbasketDefinition.getAuthorizations().isEmpty()) {
allAuthorizationsAreEmpty = false;
}
if (allDistributionTargetsAreEmpty && !workbasketDefinition.getDistributionTargets().isEmpty()) {
allDistributionTargetsAreEmpty = false;
}
if (!allAuthorizationsAreEmpty && !allDistributionTargetsAreEmpty) {
break;
}
}
assertFalse(allDistributionTargetsAreEmpty);
assertFalse(allAuthorizationsAreEmpty);
}
@Test
public void exportWorkbasketFromWrongDomain() {
ResponseEntity<List<WorkbasketDefinition>> response = template.exchange(
this.server + this.port + "/v1/workbasket-definitions?domain=wrongDomain",
HttpMethod.GET, request, new ParameterizedTypeReference<List<WorkbasketDefinition>>() {
public void testExportWorkbasketsFromWrongDomain() {
ResponseEntity<List<WorkbasketDefinitionResource>> response = template.exchange(
server + port + "/v1/workbasket-definitions?domain=wrongDomain",
HttpMethod.GET, request, new ParameterizedTypeReference<List<WorkbasketDefinitionResource>>() {
});
assertEquals(0, response.getBody().size());
}
@Test
public void testImportWorkbasket() throws IOException {
ResponseEntity<List<WorkbasketDefinitionResource>> response = template.exchange(
server + port + "/v1/workbasket-definitions?domain=DOMAIN_A",
HttpMethod.GET, request, new ParameterizedTypeReference<List<WorkbasketDefinitionResource>>() {
});
List<String> list = new ArrayList<>();
list.add(objMapper.writeValueAsString(response.getBody().get(0)));
ResponseEntity<String> responseImport = importRequest(list);
assertEquals(HttpStatus.OK, responseImport.getStatusCode());
}
private ResponseEntity<String> importRequest(List<String> clList) throws IOException {
File tmpFile = File.createTempFile("test", ".tmp");
FileWriter writer = new FileWriter(tmpFile);
writer.write(clList.toString());
writer.close();
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
body.add("file", new FileSystemResource(tmpFile));
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
String serverUrl = server + port + "/v1/workbasket-definitions";
RestTemplate restTemplate = new RestTemplate();
return restTemplate.postForEntity(serverUrl, requestEntity, String.class);
}
/**
* Return a REST template which is capable of dealing with responses in HAL format.
*
@ -94,5 +147,4 @@ public class WorkbasketDefinitionControllerIntTest {
return new RestTemplate(Collections.<HttpMessageConverter<?>>singletonList(converter));
}
}

View File

@ -37,11 +37,11 @@ import pro.taskana.exceptions.InvalidWorkbasketException;
import pro.taskana.exceptions.NotAuthorizedException;
import pro.taskana.exceptions.WorkbasketAlreadyExistException;
import pro.taskana.exceptions.WorkbasketNotFoundException;
import pro.taskana.rest.resource.WorkbasketDefinition;
import pro.taskana.rest.resource.WorkbasketDefinitionAssembler;
import pro.taskana.rest.resource.WorkbasketDefinitionResource;
import pro.taskana.rest.resource.WorkbasketDefinitionResourceAssembler;
/**
* Controller for all {@link WorkbasketDefinition} related endpoints.
* Controller for all {@link WorkbasketDefinitionResource} related endpoints.
*/
@RestController
@RequestMapping(path = "/v1/workbasket-definitions", produces = {MediaType.APPLICATION_JSON_VALUE})
@ -53,21 +53,21 @@ public class WorkbasketDefinitionController {
private WorkbasketService workbasketService;
@Autowired
private WorkbasketDefinitionAssembler workbasketDefinitionAssembler;
private WorkbasketDefinitionResourceAssembler workbasketDefinitionAssembler;
@GetMapping
@Transactional(readOnly = true, rollbackFor = Exception.class)
public ResponseEntity<List<WorkbasketDefinition>> exportWorkbaskets(@RequestParam(required = false) String domain)
public ResponseEntity<List<WorkbasketDefinitionResource>> exportWorkbaskets(@RequestParam(required = false) String domain)
throws NotAuthorizedException, WorkbasketNotFoundException {
LOGGER.debug("Entry to exportWorkbaskets(domain= {})", domain);
WorkbasketQuery workbasketQuery = workbasketService.createWorkbasketQuery();
List<WorkbasketSummary> workbasketSummaryList = domain != null
? workbasketQuery.domainIn(domain).list()
: workbasketQuery.list();
List<WorkbasketDefinition> basketExports = new ArrayList<>();
List<WorkbasketDefinitionResource> basketExports = new ArrayList<>();
for (WorkbasketSummary summary : workbasketSummaryList) {
Workbasket workbasket = workbasketService.getWorkbasket(summary.getId());
basketExports.add(workbasketDefinitionAssembler.toDefinition(workbasket));
basketExports.add(workbasketDefinitionAssembler.toResource(workbasket));
}
if (LOGGER.isDebugEnabled()) {
@ -79,7 +79,7 @@ public class WorkbasketDefinitionController {
}
/**
* This method imports a <b>list of {@link WorkbasketDefinition}</b>. This does not exactly match the REST norm, but
* This method imports a <b>list of {@link WorkbasketDefinitionResource}</b>. This does not exactly match the REST norm, but
* we want to have an option to import all settings at once. When a logical equal (key and domain are equal)
* workbasket already exists an update will be executed. Otherwise a new workbasket will be created.
*
@ -96,8 +96,8 @@ public class WorkbasketDefinitionController {
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
List<WorkbasketDefinition> definitions = mapper.readValue(file.getInputStream(),
new TypeReference<List<WorkbasketDefinition>>() {
List<WorkbasketDefinitionResource> definitions = mapper.readValue(file.getInputStream(),
new TypeReference<List<WorkbasketDefinitionResource>>() {
});
@ -113,8 +113,8 @@ public class WorkbasketDefinitionController {
Map<String, String> idConversion = new HashMap<>();
// STEP 1: update or create workbaskets from the import
for (WorkbasketDefinition definition : definitions) {
Workbasket importedWb = workbasketDefinitionAssembler.toModel(definition.workbasket);
for (WorkbasketDefinitionResource definition : definitions) {
Workbasket importedWb = workbasketDefinitionAssembler.toModel(definition.getWorkbasket());
Workbasket workbasket;
if (systemIds.containsKey(logicalId(importedWb))) {
workbasket = workbasketService.updateWorkbasket(importedWb);
@ -127,7 +127,7 @@ public class WorkbasketDefinitionController {
for (WorkbasketAccessItem accessItem : workbasketService.getWorkbasketAccessItems(workbasket.getId())) {
workbasketService.deleteWorkbasketAccessItem(accessItem.getId());
}
for (WorkbasketAccessItem authorization : definition.authorizations) {
for (WorkbasketAccessItem authorization : definition.getAuthorizations()) {
workbasketService.createWorkbasketAccessItem(authorization);
}
idConversion.put(importedWb.getId(), workbasket.getId());
@ -135,9 +135,9 @@ public class WorkbasketDefinitionController {
// STEP 2: update distribution targets
// This can not be done in step 1 because the system IDs are only known after step 1
for (WorkbasketDefinition definition : definitions) {
for (WorkbasketDefinitionResource definition : definitions) {
List<String> distributionTargets = new ArrayList<>();
for (String oldId : definition.distributionTargets) {
for (String oldId : definition.getDistributionTargets()) {
if (idConversion.containsKey(oldId)) {
distributionTargets.add(idConversion.get(oldId));
} else {
@ -150,7 +150,7 @@ public class WorkbasketDefinitionController {
workbasketService.setDistributionTargets(
// no verification necessary since the workbasket was already imported in step 1.
idConversion.get(definition.workbasket.getWorkbasketId()), distributionTargets);
idConversion.get(definition.getWorkbasket().getWorkbasketId()), distributionTargets);
}
LOGGER.debug("Exit from importWorkbaskets(), returning {}", new ResponseEntity<>(HttpStatus.OK));
return new ResponseEntity<>(HttpStatus.OK);

View File

@ -1,39 +0,0 @@
package pro.taskana.rest.resource;
import java.util.List;
import java.util.Set;
import pro.taskana.WorkbasketAccessItem;
import pro.taskana.impl.util.LoggerUtils;
/**
* this class represents a workbasket including its distro targets and authorisations.
*/
public class WorkbasketDefinition {
public Set<String> distributionTargets;
public List<WorkbasketAccessItem> authorizations;
public WorkbasketResource workbasket;
public WorkbasketDefinition() {
// necessary for de-serializing
}
public WorkbasketDefinition(WorkbasketResource workbasket,
Set<String> distributionTargets,
List<WorkbasketAccessItem> authorizations) {
super();
this.workbasket = workbasket;
this.distributionTargets = distributionTargets;
this.authorizations = authorizations;
}
@Override
public String toString() {
return "WorkbasketDefinition ["
+ "distributionTargets= " + LoggerUtils.setToString(this.distributionTargets)
+ "authorizations= " + LoggerUtils.listToString(this.authorizations)
+ "workbasket= " + this.workbasket
+ "]";
}
}

View File

@ -0,0 +1,62 @@
package pro.taskana.rest.resource;
import java.util.List;
import java.util.Set;
import pro.taskana.impl.WorkbasketAccessItemImpl;
import pro.taskana.impl.util.LoggerUtils;
/**
* this class represents a workbasket including its distro targets and authorisations.
*/
public class WorkbasketDefinitionResource {
private Set<String> distributionTargets;
private List<WorkbasketAccessItemImpl> authorizations;
private WorkbasketResourceWithoutLinks workbasket;
public WorkbasketDefinitionResource() {
// necessary for de-serializing
}
public WorkbasketDefinitionResource(WorkbasketResourceWithoutLinks workbasket,
Set<String> distributionTargets, List<WorkbasketAccessItemImpl> authorizations) {
super();
this.workbasket = workbasket;
this.distributionTargets = distributionTargets;
this.authorizations = authorizations;
}
public Set<String> getDistributionTargets() {
return distributionTargets;
}
public void setDistributionTargets(Set<String> distributionTargets) {
this.distributionTargets = distributionTargets;
}
public List<WorkbasketAccessItemImpl> getAuthorizations() {
return authorizations;
}
public void setAuthorizations(List<WorkbasketAccessItemImpl> authorizations) {
this.authorizations = authorizations;
}
public WorkbasketResourceWithoutLinks getWorkbasket() {
return workbasket;
}
public void setWorkbasket(WorkbasketResourceWithoutLinks workbasket) {
this.workbasket = workbasket;
}
@Override
public String toString() {
return "WorkbasketDefinitionResource ["
+ "distributionTargets= " + LoggerUtils.setToString(this.distributionTargets)
+ "authorizations= " + LoggerUtils.listToString(this.authorizations)
+ "workbasket= " + this.workbasket
+ "]";
}
}

View File

@ -16,14 +16,15 @@ import pro.taskana.WorkbasketService;
import pro.taskana.WorkbasketSummary;
import pro.taskana.exceptions.NotAuthorizedException;
import pro.taskana.exceptions.WorkbasketNotFoundException;
import pro.taskana.impl.WorkbasketAccessItemImpl;
import pro.taskana.impl.WorkbasketImpl;
/**
* Transforms {@link Workbasket} into a {@link WorkbasketDefinition}
* Transforms {@link Workbasket} into a {@link WorkbasketDefinitionResource}
* containing all additional information about that workbasket.
*/
@Component
public class WorkbasketDefinitionAssembler {
public class WorkbasketDefinitionResourceAssembler {
@Autowired
private WorkbasketService workbasketService;
@ -33,31 +34,31 @@ public class WorkbasketDefinitionAssembler {
*
* @param workbasket
* {@link Workbasket} which will be converted
* @return a {@link WorkbasketDefinition}, containing the {@code basket}, its distribution targets and its
* @return a {@link WorkbasketDefinitionResource}, containing the {@code basket}, its distribution targets and its
* authorizations
* @throws NotAuthorizedException
* if the user is not authorized
* @throws WorkbasketNotFoundException
* if {@code basket} is an unknown workbasket
*/
public WorkbasketDefinition toDefinition(Workbasket workbasket)
public WorkbasketDefinitionResource toResource(Workbasket workbasket)
throws NotAuthorizedException, WorkbasketNotFoundException {
WorkbasketResource basket = new WorkbasketResource();
WorkbasketResourceWithoutLinks basket = new WorkbasketResourceWithoutLinks();
BeanUtils.copyProperties(workbasket, basket);
basket.setWorkbasketId(workbasket.getId());
basket.setModified(workbasket.getModified().toString());
basket.setCreated(workbasket.getCreated().toString());
List<WorkbasketAccessItem> authorizations = new ArrayList<>();
for (WorkbasketAccessItem accessItem : workbasketService.getWorkbasketAccessItems(basket.getKey())) {
authorizations.add(accessItem);
List<WorkbasketAccessItemImpl> authorizations = new ArrayList<>();
for (WorkbasketAccessItem accessItem : workbasketService.getWorkbasketAccessItems(basket.getWorkbasketId())) {
authorizations.add((WorkbasketAccessItemImpl) accessItem);
}
Set<String> distroTargets = workbasketService.getDistributionTargets(workbasket.getId())
.stream()
.map(WorkbasketSummary::getId)
.collect(Collectors.toSet());
return new WorkbasketDefinition(basket, distroTargets, authorizations);
return new WorkbasketDefinitionResource(basket, distroTargets, authorizations);
}
public Workbasket toModel(WorkbasketResource wbResource) {

View File

@ -0,0 +1,11 @@
package pro.taskana.rest.resource;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
/**
* Resource class for {@link pro.taskana.Workbasket} but without links property.
*/
@JsonIgnoreProperties(value = { "links" })
public class WorkbasketResourceWithoutLinks extends WorkbasketResource {
}