Commit 3423d9eb authored by Matija Obreza's avatar Matija Obreza
Browse files

Dataset files are stored in repository under **/dataset/{dataset.uuid}** folder

- Permissions on Dataset are required to add/remove files
- Renamed RepositoryFileController to DatasetFilesController
- New RepositoryController
parent f47fb68b
Pipeline #4094 passed with stage
in 1 minute and 30 seconds
......@@ -165,8 +165,8 @@ public interface DatasetService {
* @throws InvalidRepositoryPathException InvalidRepositoryPathException
* @throws InvalidRepositoryFileDataException InvalidRepositoryFileDataException
*/
@PreAuthorize("isAuthenticated()")
Dataset addDatasetFile(UUID datasetUuid, MultipartFile file) throws NotFoundElement, IOException, InvalidRepositoryPathException, InvalidRepositoryFileDataException;
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#dataset, 'write')")
Dataset addDatasetFile(Dataset dataset, MultipartFile file) throws NotFoundElement, IOException, InvalidRepositoryPathException, InvalidRepositoryFileDataException;
/**
* Removes the file of dataset.
......@@ -178,8 +178,8 @@ public interface DatasetService {
* @throws NoSuchRepositoryFileException NoSuchRepositoryFileException
* @throws IOException IOException
*/
@PreAuthorize("isAuthenticated()")
Dataset removeDatasetFile(UUID datasetUuid, UUID fileUuid) throws NotFoundElement, NoSuchRepositoryFileException, IOException;
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#dataset, 'write')")
Dataset removeDatasetFile(Dataset dataset, UUID fileUuid) throws NotFoundElement, NoSuchRepositoryFileException, IOException;
/**
* Load list of RepositoryFile by uuid of dataset.
......@@ -188,7 +188,7 @@ public interface DatasetService {
* @return loaded list of RepositoryFile
* @throws NotFoundElement the not found element
*/
List<RepositoryFile> listDatasetFiles(UUID datasetUuid) throws NotFoundElement;
List<RepositoryFile> listDatasetFiles(Dataset dataset) throws NotFoundElement;
/**
* Remove dataset.
......
......@@ -16,7 +16,7 @@
package org.genesys.catalog.service.impl;
import java.io.IOException;
import java.time.Instant;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
......@@ -24,7 +24,6 @@ import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.genesys.catalog.exceptions.InvalidApiUsageException;
import org.genesys.catalog.exceptions.NotFoundElement;
......@@ -78,8 +77,8 @@ public class DatasetServiceImpl implements DatasetService {
private Utils utils;
/** The file repository path. */
@Value("${file.repository.path}")
public String fileRepositoryPath;
@Value("${file.repository.datasets.folder}")
public String datasetRepositoryPath;
/**
* {@inheritDoc}
......@@ -278,10 +277,12 @@ public class DatasetServiceImpl implements DatasetService {
*/
@Transactional
@Override
public Dataset addDatasetFile(final UUID datasetUuid, final MultipartFile file) throws NotFoundElement, IOException, InvalidRepositoryPathException,
public Dataset addDatasetFile(Dataset dataset, final MultipartFile file) throws NotFoundElement, IOException, InvalidRepositoryPathException,
InvalidRepositoryFileDataException {
final Dataset dataset = loadDataset(datasetUuid);
final RepositoryFile repositoryFile = fileRepoService.addFile(fileRepositoryPath, buildFileName(file.getOriginalFilename()), file.getContentType(), file.getBytes(), null);
dataset = datasetRepository.findByUuidAndVersion(dataset.getUuid(), dataset.getVersion());
final RepositoryFile repositoryFile = fileRepoService.addFile(Paths.get(datasetRepositoryPath, dataset.getUuid().toString()).toAbsolutePath().toString(), file
.getOriginalFilename(), file.getContentType(), file.getBytes(), null);
dataset.getRepositoryFiles().add(repositoryFile);
return lazyLoad(datasetRepository.save(dataset));
}
......@@ -291,8 +292,9 @@ public class DatasetServiceImpl implements DatasetService {
*/
@Transactional
@Override
public Dataset removeDatasetFile(final UUID datasetUuid, final UUID fileUuid) throws NotFoundElement, NoSuchRepositoryFileException, IOException {
final Dataset dataset = loadDataset(datasetUuid);
public Dataset removeDatasetFile(Dataset dataset, final UUID fileUuid) throws NotFoundElement, NoSuchRepositoryFileException, IOException {
dataset = datasetRepository.findByUuidAndVersion(dataset.getUuid(), dataset.getVersion());
final RepositoryFile repositoryFile = fileRepoService.getFile(fileUuid);
dataset.getRepositoryFiles().remove(repositoryFile);
fileRepoService.removeFile(repositoryFile);
......@@ -303,8 +305,7 @@ public class DatasetServiceImpl implements DatasetService {
* {@inheritDoc}
*/
@Override
public List<RepositoryFile> listDatasetFiles(final UUID datasetUuid) throws NotFoundElement {
final Dataset dataset = loadDataset(datasetUuid);
public List<RepositoryFile> listDatasetFiles(final Dataset dataset) throws NotFoundElement {
return dataset.getRepositoryFiles();
}
......@@ -430,19 +431,4 @@ public class DatasetServiceImpl implements DatasetService {
target.getDescriptors().addAll(descriptors.stream().distinct().collect(Collectors.toList()));
}
/**
* Builds the file name.
*
* @param originName the origin name
* @return the string
*/
private String buildFileName(final String originName) {
final Instant instant = Instant.now();
final String[] s = originName.split("[.]");
final StringBuilder stringBuilder = new StringBuilder();
IntStream.range(0, s.length - 1).forEach(i -> stringBuilder.append(s[i]));
stringBuilder.append("_").append(instant).append(".").append(s[s.length - 1]);
return stringBuilder.toString();
}
}
......@@ -15,13 +15,7 @@
*/
package org.genesys.catalog.service;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat;
import java.io.File;
......@@ -35,8 +29,6 @@ import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import com.google.common.collect.Lists;
import org.genesys.blocks.model.filters.StringFilter;
import org.genesys.catalog.exceptions.InvalidApiUsageException;
import org.genesys.catalog.exceptions.NotFoundElement;
......@@ -59,6 +51,8 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.mock.web.MockMultipartFile;
import com.google.common.collect.Lists;
public class DatasetServiceTest extends AbstractDatasetServiceTest {
@Test
......@@ -260,7 +254,7 @@ public class DatasetServiceTest extends AbstractDatasetServiceTest {
Dataset savedDataset = buildAndSaveDataset(DATASET_TITLE_1, DATASET_DESCRIPTION_1, partner, false);
savedDataset = datasetService.updateDescriptors(savedDataset, Lists.newArrayList(descriptor3, descriptor1, descriptor2, descriptor3));
assertThat(savedDataset.getDescriptors(), hasSize(3));
}
......@@ -340,12 +334,11 @@ public class DatasetServiceTest extends AbstractDatasetServiceTest {
MockMultipartFile mockMultipartFile = new MockMultipartFile("file", file.getName(), "multipart/form-data", fileInputStream);
Dataset created = buildAndSaveDataset(DATASET_TITLE_1, DATASET_DESCRIPTION_1, partner, false);
Dataset dataset = datasetService.addDatasetFile(created.getUuid(), mockMultipartFile);
Dataset dataset = datasetService.addDatasetFile(created, mockMultipartFile);
File file2 = new File(getClass().getResource("/mcpd20177.csv").getPath());
FileInputStream fileInputStream2 = new FileInputStream(file2);
MockMultipartFile mockMultipartFile2 = new MockMultipartFile("file", file2.getName(), "multipart/form-data", fileInputStream2);
dataset = datasetService.addDatasetFile(created.getUuid(), mockMultipartFile2);
FileInputStream fileInputStream2 = new FileInputStream(file);
MockMultipartFile mockMultipartFile2 = new MockMultipartFile("file", "2" + file.getName(), "multipart/form-data", fileInputStream2);
dataset = datasetService.addDatasetFile(dataset, mockMultipartFile2);
assertThat(dataset.getRepositoryFiles(), is(notNullValue()));
}
......@@ -357,12 +350,12 @@ public class DatasetServiceTest extends AbstractDatasetServiceTest {
Dataset input = buildAndSaveDataset(DATASET_TITLE_1, DATASET_DESCRIPTION_1, partner, false);
Dataset dataset = datasetService.addDatasetFile(input.getUuid(), mockMultipartFile);
input = datasetService.addDatasetFile(input, mockMultipartFile);
datasetService.removeDatasetFile(input.getUuid(), dataset.getRepositoryFiles().get(0).getUuid());
Dataset dataset = datasetService.removeDatasetFile(input, input.getRepositoryFiles().get(0).getUuid());
assertThat(input.getRepositoryFiles().size(), is(0));
assertThat(repositoryFilePersistence.findByUuid(dataset.getRepositoryFiles().get(0).getUuid()), nullValue());
assertThat(dataset.getRepositoryFiles().size(), is(0));
assertThat(repositoryFilePersistence.findByUuid(input.getRepositoryFiles().get(0).getUuid()), nullValue());
}
@Test
......@@ -423,7 +416,8 @@ public class DatasetServiceTest extends AbstractDatasetServiceTest {
filter.accessionIdentifier.genus.clear();
filter.accessionIdentifier.genus("Manihot");
assertThat(datasetService.listDatasets(filter, new PageRequest(0, 3)).getContent(), hasSize(1));
assertThat(datasetService.listDatasets(filter, new PageRequest(0, 3)).getContent().stream().map(d -> d.getUuid()).collect(Collectors.toSet()), contains(dataset2.getUuid()));
assertThat(datasetService.listDatasets(filter, new PageRequest(0, 3)).getContent().stream().map(d -> d.getUuid()).collect(Collectors.toSet()), contains(dataset2
.getUuid()));
filter.accessionIdentifier.genus.clear();
filter.accessionIdentifier.genus("Manihot");
......@@ -444,7 +438,8 @@ public class DatasetServiceTest extends AbstractDatasetServiceTest {
filter.accessionIdentifier.acceNumb.eq = "A8"; // only in dataset1
assertThat(datasetService.listDatasets(filter, new PageRequest(0, 3)).getContent(), hasSize(1));
assertThat(datasetService.listDatasets(filter, new PageRequest(0, 3)).getContent().stream().map(d -> d.getUuid()).collect(Collectors.toSet()), contains(dataset1.getUuid()));
assertThat(datasetService.listDatasets(filter, new PageRequest(0, 3)).getContent().stream().map(d -> d.getUuid()).collect(Collectors.toSet()), contains(dataset1
.getUuid()));
filter.accessionIdentifier.acceNumb.eq = "A1"; // in both
assertThat(datasetService.listDatasets(filter, new PageRequest(0, 3)).getContent(), hasSize(2));
......@@ -452,9 +447,9 @@ public class DatasetServiceTest extends AbstractDatasetServiceTest {
filter.accessionIdentifier.acceNumb.eq = "A8"; // only in dataset1
filter.accessionIdentifier.genus("Musa");
assertThat(datasetService.listDatasets(filter, new PageRequest(0, 3)).getContent(), hasSize(1));
assertThat(datasetService.listDatasets(filter, new PageRequest(0, 3)).getContent().stream().map(d -> d.getUuid()).collect(Collectors.toSet()), contains(dataset1.getUuid()));
assertThat(datasetService.listDatasets(filter, new PageRequest(0, 3)).getContent().stream().map(d -> d.getUuid()).collect(Collectors.toSet()), contains(dataset1
.getUuid()));
}
@Test(expected = InvalidApiUsageException.class)
public void failUpdateDatasetOwner() throws Exception {
......
......@@ -40,35 +40,37 @@ import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
/**
* Manage dataset files
*
* @author Andrey Lugovskoy.
*/
@RestController
@RequestMapping(RepositoryFileController.API_BASE)
@RequestMapping(DatasetFilesController.API_BASE)
@PreAuthorize("isAuthenticated()")
public class RepositoryFileController {
public class DatasetFilesController {
protected static final String API_BASE = DatasetController.API_BASE + "/{UUID}/files";
private static final Logger LOG = LoggerFactory.getLogger(DatasetController.class);
private static final Logger LOG = LoggerFactory.getLogger(DatasetFilesController.class);
@Autowired
protected DatasetService datasetService;
@PostMapping(value = "/add")
public Dataset addFileToDataset(@RequestParam("file") final MultipartFile inputFile, @PathVariable("UUID") final UUID uuid) throws NotFoundElement,
public Dataset addFileToDataset(@RequestParam("file") final MultipartFile inputFile, @PathVariable("UUID") final UUID datasetUuid) throws NotFoundElement,
InvalidRepositoryFileDataException, InvalidRepositoryPathException, IOException {
LOG.info("Upload file to dataset by uuid {}", uuid);
return datasetService.addDatasetFile(uuid, inputFile);
LOG.info("Upload file to dataset by uuid {}", datasetUuid);
return datasetService.addDatasetFile(datasetService.loadDataset(datasetUuid), inputFile);
}
@DeleteMapping(value = "/delete/{fileUuid}")
public Dataset removeFileOfDataset(@PathVariable("UUID") final UUID datasetUuid, @PathVariable("fileUuid") final UUID fileUuid) throws NotFoundElement,
InvalidRepositoryFileDataException, InvalidRepositoryPathException, IOException, NoSuchRepositoryFileException {
return datasetService.removeDatasetFile(datasetUuid, fileUuid);
return datasetService.removeDatasetFile(datasetService.loadDataset(datasetUuid), fileUuid);
}
@GetMapping(value = "/list")
public List<RepositoryFile> getList(@PathVariable("UUID") final UUID datasetUuid) throws NotFoundElement {
return datasetService.listDatasetFiles(datasetUuid);
return datasetService.listDatasetFiles(datasetService.loadDataset(datasetUuid));
}
}
/*
* Copyright 2017 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.genesys.catalog.server.controller.api.v0;
import java.io.IOException;
import java.util.UUID;
import javax.servlet.http.HttpServletResponse;
import org.genesys.catalog.exceptions.InvalidApiUsageException;
import org.genesys.catalog.exceptions.NotFoundElement;
import org.genesys.filerepository.InvalidRepositoryFileDataException;
import org.genesys.filerepository.InvalidRepositoryPathException;
import org.genesys.filerepository.NoSuchRepositoryFileException;
import org.genesys.filerepository.model.RepositoryFile;
import org.genesys.filerepository.service.RepositoryService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
/**
* @author Matija Obreza
*/
@RestController
@RequestMapping(RepositoryController.API_BASE)
@PreAuthorize("isAuthenticated()")
public class RepositoryController {
protected static final String API_BASE = "/api/v0/repository";
private static final Logger LOG = LoggerFactory.getLogger(RepositoryController.class);
@Autowired
protected RepositoryService repositoryService;
@PostMapping(value = "/add")
public RepositoryFile addFile(@RequestParam("file") final MultipartFile inputFile, @RequestParam("metadata") RepositoryFile metadata) throws NotFoundElement,
InvalidRepositoryFileDataException, InvalidRepositoryPathException, IOException {
LOG.info("Uploading {} to repository", inputFile.getOriginalFilename());
return repositoryService.addFile(metadata.getPath(), inputFile.getOriginalFilename(), inputFile.getContentType(), inputFile.getBytes(), metadata);
}
@GetMapping(value = "/{fileUuid}")
public RepositoryFile getFile(@PathVariable("fileUuid") final UUID fileUuid) throws NoSuchRepositoryFileException, IOException {
return repositoryService.getFile(fileUuid);
}
@PostMapping(value = "/{fileUuid},{version}")
public RepositoryFile updateFile(@PathVariable("fileUuid") final UUID fileUuid, @PathVariable("version") final int version, final RepositoryFile metadata)
throws NoSuchRepositoryFileException, IOException {
if (metadata != null && metadata.getUuid().equals(fileUuid) && metadata.getVersion().equals(version)) {
return repositoryService.updateMetadata(repositoryService.getFile(fileUuid, version));
} else {
throw new InvalidApiUsageException("File uuid and version don't match");
}
}
@DeleteMapping(value = "/{fileUuid}")
public RepositoryFile removeFile(@PathVariable("fileUuid") final UUID fileUuid) throws NoSuchRepositoryFileException, IOException {
return repositoryService.removeFile(repositoryService.getFile(fileUuid));
}
@GetMapping(value = "/download/{fileUuid}")
public void downloadFile(@PathVariable("fileUuid") final UUID fileUuid, final HttpServletResponse response) throws NoSuchRepositoryFileException, IOException {
RepositoryFile repositoryFile = repositoryService.getFile(fileUuid);
response.setHeader(HttpHeaders.CACHE_CONTROL, "max-age=86400, s-maxage=86400, public, no-transform");
response.setHeader(HttpHeaders.PRAGMA, "");
response.setDateHeader(HttpHeaders.LAST_MODIFIED, repositoryFile.getLastModifiedDate().getTime());
response.setContentType(repositoryFile.getContentType());
response.addHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", repositoryFile.getOriginalFilename()));
byte[] data = repositoryService.getFileBytes(repositoryFile);
if (data != null) {
response.setContentLength(data.length);
response.getOutputStream().write(data);
}
response.flushBuffer();
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment