Commit 457fbbe3 authored by Matija Obreza's avatar Matija Obreza

Merge branch '366-faoinstitute-partner-folders' into 'master'

Resolve "FaoInstitute/Partner folders"

Closes #366

See merge request genesys-pgr/genesys-server!272
parents 8311d114 c7f3c280
......@@ -27,6 +27,7 @@ import org.genesys2.server.exception.NotFoundElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.security.access.AccessDeniedException;
......@@ -132,7 +133,7 @@ public class ApiExceptionHandler {
* @return the api error
*/
@ResponseStatus(code = HttpStatus.BAD_REQUEST)
@ExceptionHandler({ InvalidApiUsageException.class, ConcurrencyFailureException.class, FileRepositoryException.class, NotUniqueUserException.class })
@ExceptionHandler({ InvalidApiUsageException.class, DataIntegrityViolationException.class, ConcurrencyFailureException.class, FileRepositoryException.class, NotUniqueUserException.class })
@ResponseBody
public ApiError<Exception> handleInvalidApiUsage(final Exception e, final HttpServletRequest request) {
LOG.warn("{} for {} {}", e.getMessage(), request.getMethod(), request.getRequestURL()); //, e);
......
......@@ -16,6 +16,7 @@
package org.genesys.catalog.service;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
import java.util.Set;
......@@ -424,4 +425,12 @@ public interface DatasetService {
*/
int clearAccessionRefs(Collection<Accession> accessions);
/**
* Get the repository path where dataset files are stored
*
* @param dataset
* @return the path to the repository folder
*/
Path getDatasetRepositoryFolder(Dataset dataset);
}
......@@ -20,6 +20,7 @@ import static org.genesys.catalog.model.dataset.QDatasetCreator.datasetCreator;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
......@@ -48,6 +49,7 @@ import org.genesys.catalog.persistence.dataset.DatasetRepository;
import org.genesys.catalog.persistence.dataset.DatasetVersionsRepository;
import org.genesys.catalog.service.DatasetService;
import org.genesys.catalog.service.DescriptorService;
import org.genesys.filerepository.FolderNotEmptyException;
import org.genesys.filerepository.InvalidRepositoryFileDataException;
import org.genesys.filerepository.InvalidRepositoryPathException;
import org.genesys.filerepository.NoSuchRepositoryFileException;
......@@ -60,6 +62,7 @@ import org.genesys2.server.model.UserRole;
import org.genesys2.server.model.genesys.Accession;
import org.genesys2.server.model.genesys.AccessionRef;
import org.genesys2.server.persistence.AccessionRepository;
import org.genesys2.server.security.AsAdminInvoker;
import org.genesys2.server.security.SecurityUtils;
import org.genesys2.server.service.DownloadService;
import org.genesys2.util.JPAUtils;
......@@ -119,6 +122,10 @@ public class DatasetServiceImpl implements DatasetService {
@Autowired
private SecurityUtils securityUtils;
/** Execute code as admin */
@Autowired
protected AsAdminInvoker asAdminInvoker;
/** The accessions repository. */
@Autowired
private AccessionRepository accessionRepository;
......@@ -145,7 +152,7 @@ public class DatasetServiceImpl implements DatasetService {
LOG.info("Create Dataset. Input data {}", source);
final DatasetVersions datasetVersions = new DatasetVersions();
datasetVersionsRepository.save(datasetVersions);
Dataset dataset = new Dataset();
dataset.setUuid(source.getUuid());
dataset.setVersions(datasetVersions);
......@@ -165,7 +172,22 @@ public class DatasetServiceImpl implements DatasetService {
copyDescriptors(dataset, source.getDescriptors());
dataset = datasetRepository.save(dataset);
try {
final Path datasetPath = Paths.get(datasetRepositoryPath, dataset.getUuid().toString());
final Partner partner = dataset.getOwner();
// Ensure folder ownership
asAdminInvoker.invoke(() -> {
// Ensure target folder exists for the Dataset
return repositoryService.ensureFolder(datasetPath, partner);
});
} catch (Exception e) {
LOG.warn("Could not update Folder properties: {}", e.getMessage());
}
datasetVersions.setCurrentVersion(dataset);
datasetVersionsRepository.save(datasetVersions);
......@@ -375,12 +397,20 @@ public class DatasetServiceImpl implements DatasetService {
InvalidRepositoryFileDataException {
dataset = datasetRepository.findByUuidAndVersion(dataset.getUuid(), dataset.getVersion());
final RepositoryFile repositoryFile = repositoryService.addFile(Paths.get(datasetRepositoryPath, dataset.getUuid().toString()).toAbsolutePath(), file
final RepositoryFile repositoryFile = repositoryService.addFile(getDatasetRepositoryFolder(dataset), file
.getOriginalFilename(), file.getContentType(), file.getBytes(), null);
dataset.getRepositoryFiles().add(repositoryFile);
return lazyLoad(datasetRepository.save(dataset));
}
@Override
public Path getDatasetRepositoryFolder(Dataset dataset) {
assert(dataset != null);
assert(dataset.getUuid() != null);
return Paths.get(datasetRepositoryPath, dataset.getUuid().toString()).toAbsolutePath();
}
@Override
@Transactional
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#dataset, 'write')")
......@@ -474,6 +504,13 @@ public class DatasetServiceImpl implements DatasetService {
}
datasetRepository.delete(loadedDataset);
try {
repositoryService.deleteFolder(getDatasetRepositoryFolder(dataset));
} catch (FolderNotEmptyException | InvalidRepositoryPathException e) {
LOG.warn("Could not delete folder {} from dataset {}: {}", getDatasetRepositoryFolder(dataset), dataset.getUuid(), e.getMessage());
}
return loadedDataset;
}
......@@ -538,7 +575,7 @@ public class DatasetServiceImpl implements DatasetService {
RepositoryFile metadata = new RepositoryFile();
metadata.setTitle("Dataset metadata");
metadata.setDescription("Auto-generated by Genesys");
final RepositoryFile addedFile = repositoryService.addFile(Paths.get(datasetRepositoryPath, loaded.getUuid().toString()).toAbsolutePath(),
final RepositoryFile addedFile = repositoryService.addFile(getDatasetRepositoryFolder(loaded),
fileName, contentType, bos.toByteArray(), metadata);
loaded.getRepositoryFiles().add(addedFile);
loaded = lazyLoad(datasetRepository.save(loaded));
......
......@@ -15,6 +15,10 @@
*/
package org.genesys2.spring.config;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import javax.transaction.Transactional;
import org.apache.commons.lang3.StringUtils;
......@@ -26,10 +30,17 @@ import org.genesys.blocks.security.UserException;
import org.genesys.blocks.security.model.BasicUser;
import org.genesys.blocks.security.service.CustomAclService;
import org.genesys.blocks.security.service.PasswordPolicy.PasswordPolicyException;
import org.genesys.catalog.model.dataset.Dataset;
import org.genesys.catalog.persistence.dataset.DatasetRepository;
import org.genesys.catalog.service.DatasetService;
import org.genesys.filerepository.model.ImageGallery;
import org.genesys.filerepository.model.RepositoryFolder;
import org.genesys.filerepository.service.ImageGalleryService;
import org.genesys.filerepository.service.RepositoryService;
import org.genesys2.server.model.UserRole;
import org.genesys2.server.model.impl.FaoInstitute;
import org.genesys2.server.model.impl.User;
import org.genesys2.server.persistence.FaoInstituteRepository;
import org.genesys2.server.persistence.UserRepository;
import org.genesys2.server.security.AsAdminInvoker;
import org.genesys2.server.service.ElasticsearchService;
......@@ -130,6 +141,18 @@ public class ApplicationStartup implements InitializingBean, ApplicationListener
LOG.error("Default admin account could not be created", e);
}
ensure1OAuthClient();
try {
ensureDatasetFolders();
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
try {
ensureInsituteFolders();
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
}
@Autowired
......@@ -212,4 +235,44 @@ public class ApplicationStartup implements InitializingBean, ApplicationListener
return true;
});
}
@Autowired
private DatasetService datasetService;
@Autowired
private DatasetRepository datasetRepository;
@Autowired
private RepositoryService repositoryService;
private void ensureDatasetFolders() throws Exception {
asAdminInvoker.invoke(() -> {
for (Dataset dataset : datasetRepository.findAll()) {
final Path datasetPath = datasetService.getDatasetRepositoryFolder(dataset);
LOG.warn("Ensuring inheritance for {}", datasetPath);
repositoryService.ensureFolder(datasetPath, dataset.getOwner());
}
return true;
});
}
@Autowired
private FaoInstituteRepository instituteRepository;
private void ensureInsituteFolders() throws Exception {
asAdminInvoker.invoke(() -> {
List<RepositoryFolder> wiewsFolders = repositoryService.getFolders(Paths.get("/wiews"));
for (RepositoryFolder instFolder: wiewsFolders) {
LOG.warn("Ensuring inheritance for {}", instFolder.getFolderPath());
FaoInstitute institute = instituteRepository.findByCode(instFolder.getName());
if (institute != null) {
repositoryService.ensureFolder(instFolder.getFolderPath(), institute);
} else {
LOG.error("No institute " + instFolder.getName() + " for path " + instFolder.getPath());
}
}
return true;
});
}
}
......@@ -76,30 +76,32 @@ public class ApplicationUpgrades implements InitializingBean {
return new RepositoryUpgrade20180920();
}
@Bean
protected RepositoryUpgrade20180920 afterRepositoryUpgrade20180920(RepositoryUpgrade20180920 repositoryUpgrade20180920) throws Exception {
asAdminInvoker.invoke(() -> {
repositoryUpgrade20180920.doUpgrade();
LOG.warn("Updating permissions on public folders");
for (RepositoryFolder repositoryFolder : repositoryService.getFolders(Paths.get("/"))) {
LOG.warn("Making {} publicly readable", repositoryFolder.getPath());
aclService.addCreatorPermissions(repositoryFolder);
aclService.makePubliclyReadable(repositoryFolder, true);
repositoryService.listPaths(repositoryFolder.getFolderPath()).forEach(subFolder -> {
aclService.addCreatorPermissions(subFolder);
try {
repositoryService.getFiles(subFolder.getFolderPath()).forEach(file -> {
aclService.addCreatorPermissions(file);
});
} catch (InvalidRepositoryPathException e) {
LOG.error("Error updating permissions: {}", e.getMessage());
}
});
}
// repositoryUpgrade20180920.doUpgrade();
//
// LOG.warn("Updating permissions on public folders");
//
// for (RepositoryFolder repositoryFolder : repositoryService.getFolders(Paths.get("/"))) {
// LOG.warn("Making {} publicly readable", repositoryFolder.getPath());
// aclService.createOrUpdatePermissions(repositoryFolder);
// aclService.makePubliclyReadable(repositoryFolder, true);
//
// repositoryService.listPaths(repositoryFolder.getFolderPath()).forEach(subFolder -> {
// aclService.createOrUpdatePermissions(subFolder);
// try {
// repositoryService.getFiles(subFolder.getFolderPath()).forEach(file -> {
// aclService.createOrUpdatePermissions(file);
// });
// } catch (InvalidRepositoryPathException e) {
// LOG.error("Error updating permissions: {}", e.getMessage());
// }
//
// });
// }
return true;
});
......
......@@ -4448,6 +4448,26 @@ databaseChangeLog:
tableName: subset
columnName: rights
- changeSet:
id: 1540821453000-5
author: mobreza
changes:
- addColumn:
tableName: repositoryfolder
columns:
- column:
name: parentOid_id
type: bigint
- addForeignKeyConstraint:
constraintName: FK_1l4ttk3kctjy2nedwwlh8xx8p
baseTableName: repositoryfolder
baseColumnNames: parentOid_id
referencedTableName: acl_object_identity
referencedColumnNames: id
# ENABLE AFTER SOME TIME
# - changeSet:
# id: 1537463144763-folder
......
......@@ -28,6 +28,7 @@ import org.junit.Test;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.transaction.annotation.Transactional;
@WithMockUser(username = "user", password = "user", roles = "ADMINISTRATOR")
public class DatasetPublishingTest extends AbstractDatasetServiceTest {
private Dataset savedDataset;
......
......@@ -6,6 +6,7 @@ import java.util.List;
import java.util.Set;
import org.genesys.blocks.util.CurrentApplicationContext;
import org.genesys2.server.security.AsAdminInvoker;
import org.genesys2.server.security.SecurityUtils;
import org.genesys2.spring.config.AuditConfig;
import org.genesys2.spring.config.CacheConfig;
......@@ -135,6 +136,11 @@ public final class ApplicationConfig {
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
@Bean
public AsAdminInvoker asAdminInvoker() {
return new AsAdminInvoker();
}
}
@Configuration
......
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