Commit a732d0e6 authored by Matija Obreza's avatar Matija Obreza
Browse files

Merge branch '22-acl-support' into 'master'

enabled ACL support on RepositoryFile

Closes #22

See merge request !20
parents 72794bf5 9425a0ed
......@@ -7,3 +7,4 @@ target
doc
data
effective.pom
.flattened-pom.xml
......@@ -119,6 +119,12 @@
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
......@@ -163,8 +169,8 @@
</dependency>
<dependency>
<groupId>org.genesys-pgr</groupId>
<artifactId>application-blocks-core</artifactId>
<version>1.4-SNAPSHOT</version>
<artifactId>application-blocks-security</artifactId>
<version>${application.blocks.version}</version>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
......
......@@ -30,8 +30,8 @@ import javax.persistence.OrderColumn;
import org.genesys.blocks.model.AuditedVersionedModel;
import org.genesys.blocks.model.Copyable;
import org.genesys.blocks.security.model.AclAwareModel;
// TODO: Auto-generated Javadoc
/**
* {@link ImageGallery} is a collection of ordered {@link RepositoryImage}
* instances.
......@@ -44,7 +44,7 @@ import org.genesys.blocks.model.Copyable;
* @author mobreza
*/
@Entity(name = "repositorygallery")
public class ImageGallery extends AuditedVersionedModel implements Copyable<ImageGallery> {
public class ImageGallery extends AuditedVersionedModel implements AclAwareModel, Copyable<ImageGallery> {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 6043583851401365284L;
......
......@@ -38,15 +38,14 @@ import javax.persistence.UniqueConstraint;
import org.apache.commons.lang3.StringUtils;
import org.genesys.blocks.model.AuditedVersionedModelWithoutId;
import org.genesys.blocks.model.Copyable;
import org.genesys.blocks.model.EntityId;
import org.genesys.blocks.model.InMemoryIdGenerator;
import org.genesys.blocks.security.model.AclAwareModel;
import org.genesys.filerepository.metadata.BaseMetadata;
import org.genesys.filerepository.service.BytesStorageService;
import org.hibernate.annotations.Type;
// TODO: Auto-generated Javadoc
/**
* The Class RepositoryFile.
* The RepositoryFile.
*/
@Entity
@Table(name = "repositoryfile",
......@@ -55,7 +54,7 @@ import org.hibernate.annotations.Type;
// unique
, uniqueConstraints = { @UniqueConstraint(columnNames = { "path", "originalFilename" }) })
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class RepositoryFile extends AuditedVersionedModelWithoutId implements EntityId, BaseMetadata, Copyable<RepositoryFile> {
public class RepositoryFile extends AuditedVersionedModelWithoutId implements AclAwareModel, BaseMetadata, Copyable<RepositoryFile> {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = -4816923593950502695L;
......
......@@ -31,6 +31,10 @@ import org.springframework.stereotype.Repository;
/**
* The Interface RepositoryFilePersistence.
*/
/**
* @author Matija Obreza
*
*/
@Repository
public interface RepositoryFilePersistence extends RepositoryPersistence<RepositoryFile> {
......@@ -42,6 +46,16 @@ public interface RepositoryFilePersistence extends RepositoryPersistence<Reposit
*/
RepositoryFile findByUuid(UUID uuid);
/**
* Find by uuid and version.
*
* @param uuid the file uuid
* @param version the version
* @return the repository file
*/
RepositoryFile findByUuidAndVersion(UUID uuid, int version);
/**
* Find by path.
*
......
......@@ -20,6 +20,7 @@ import java.util.List;
import java.util.UUID;
import org.genesys.filerepository.RepositoryPersistence;
import org.genesys.filerepository.model.RepositoryFile;
import org.genesys.filerepository.model.RepositoryImage;
import org.springframework.stereotype.Repository;
......@@ -38,6 +39,15 @@ public interface RepositoryImagePersistence extends RepositoryPersistence<Reposi
*/
RepositoryImage findByUuid(UUID uuid);
/**
* Find by uuid and version
*
* @param fileUuid
* @param version
* @return
*/
RepositoryImage findByUuidAndVersion(UUID fileUuid, int version);
/**
* Find by path.
*
......@@ -45,4 +55,5 @@ public interface RepositoryImagePersistence extends RepositoryPersistence<Reposi
* @return the list
*/
List<RepositoryImage> findByPath(String repositoryPath);
}
......@@ -20,6 +20,9 @@ import org.genesys.filerepository.InvalidRepositoryPathException;
import org.genesys.filerepository.model.ImageGallery;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PostFilter;
import org.springframework.security.access.prepost.PreAuthorize;
// TODO: Auto-generated Javadoc
/**
......@@ -40,6 +43,7 @@ public interface ImageGalleryService {
* @return the ImageGallery or <code>null</code> if no gallery exists at the
* specified path.
*/
@PostAuthorize("returnObject == null or hasRole('ADMINISTRATOR') or hasPermission(returnObject, 'read')")
ImageGallery loadImageGallery(String path);
/**
......@@ -51,6 +55,7 @@ public interface ImageGalleryService {
* @param description Image gallery description in English.
* @return the new ImageGallery or existing gallery at the specified path.
*/
@PreAuthorize("isAuthenticated()")
ImageGallery createImageGallery(String path, String title, String description);
/**
......@@ -59,6 +64,7 @@ public interface ImageGalleryService {
* @param imageGallery the image gallery
* @throws InvalidRepositoryPathException the invalid repository path exception
*/
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#imageGallery, 'delete')")
void removeGallery(ImageGallery imageGallery) throws InvalidRepositoryPathException;
/**
......@@ -69,6 +75,7 @@ public interface ImageGalleryService {
* @param description the description
* @return the image gallery
*/
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#imageGallery, 'write')")
ImageGallery updateImageGalery(ImageGallery imageGallery, String title, String description);
/**
......@@ -78,6 +85,7 @@ public interface ImageGalleryService {
* @param imageGallery the image gallery
* @return the image gallery
*/
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#imageGallery, 'write')")
ImageGallery saveImageOrder(ImageGallery imageGallery);
/**
......@@ -97,6 +105,7 @@ public interface ImageGalleryService {
* @param pageable the pageable
* @return paginated image gallery data
*/
@PostFilter("hasRole('ADMINISTRATOR') or hasPermission(returnObject, 'read')")
Page<ImageGallery> listImageGalleries(Pageable pageable);
/**
......@@ -106,6 +115,7 @@ public interface ImageGalleryService {
* @param pageable the pageable
* @return paginated image gallery data
*/
@PostFilter("hasRole('ADMINISTRATOR') or hasPermission(returnObject, 'read')")
Page<ImageGallery> listImageGalleries(String prefix, Pageable pageable);
}
......@@ -29,6 +29,8 @@ import org.genesys.filerepository.metadata.ImageMetadata;
import org.genesys.filerepository.model.RepositoryFile;
import org.genesys.filerepository.model.RepositoryImage;
import org.springframework.data.domain.Pageable;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreAuthorize;
// TODO: Auto-generated Javadoc
/**
......@@ -50,6 +52,7 @@ public interface RepositoryService {
* exception
* @throws IOException when things go wrong on bytes storage level
*/
@PreAuthorize("isAuthenticated()")
RepositoryFile addFile(String repositoryPath, String originalFilename, String contentType, byte[] bytes, RepositoryFile metaData) throws InvalidRepositoryPathException,
InvalidRepositoryFileDataException, IOException;
......@@ -67,6 +70,7 @@ public interface RepositoryService {
* exception
* @throws IOException when things go wrong on bytes storage level
*/
@PreAuthorize("isAuthenticated()")
RepositoryImage addImage(String repositoryPath, String originalFilename, String contentType, byte[] bytes, RepositoryImage metaData) throws InvalidRepositoryPathException,
InvalidRepositoryFileDataException, IOException;
......@@ -78,8 +82,21 @@ public interface RepositoryService {
* @throws NoSuchRepositoryFileException when file is not available in the
* repository
*/
@PostAuthorize("hasRole('ADMINISTRATOR') or hasPermission(returnObject, 'read')")
RepositoryFile getFile(UUID fileUuid) throws NoSuchRepositoryFileException;
/**
* Get repository file by its UUID and version
*
* @param fileUuid the file uuid
* @param version the record version
* @return the file
* @throws NoSuchRepositoryFileException when file is not available in the
* repository
*/
@PostAuthorize("hasRole('ADMINISTRATOR') or hasPermission(returnObject, 'read')")
<T extends RepositoryFile> T getFile(UUID fileUuid, int version) throws NoSuchRepositoryFileException;
/**
* Get repository file by its path and filename.
*
......@@ -88,6 +105,7 @@ public interface RepositoryService {
* @return the file
* @throws NoSuchRepositoryFileException the no such repository file exception
*/
@PostAuthorize("hasRole('ADMINISTRATOR') or hasPermission(returnObject, 'read')")
RepositoryFile getFile(String path, String filename) throws NoSuchRepositoryFileException;
/**
......@@ -107,6 +125,7 @@ public interface RepositoryService {
* @return the file bytes
* @throws IOException Signals that an I/O exception has occurred.
*/
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#repositoryFile, 'read')")
byte[] getFileBytes(RepositoryFile repositoryFile) throws IOException;
/**
......@@ -124,7 +143,7 @@ public interface RepositoryService {
* @return the files
*/
Stream<RepositoryFile> streamFiles(String repositoryPath);
/**
* Update file metadata. The update is based on the record UUID.
*
......@@ -135,7 +154,8 @@ public interface RepositoryService {
* @throws NoSuchRepositoryFileException when file is not available in the
* repository
*/
<T extends RepositoryFile> T updateMetadata(UUID uuid, T fileData) throws NoSuchRepositoryFileException;
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#fileData, 'write')")
<T extends RepositoryFile> T updateMetadata(T fileData) throws NoSuchRepositoryFileException;
/**
* Update file bytes.
......@@ -147,7 +167,8 @@ public interface RepositoryService {
* @throws NoSuchRepositoryFileException the no such repository file exception
* @throws IOException Signals that an I/O exception has occurred.
*/
RepositoryFile updateBytes(RepositoryFile fileData, String contentType, byte[] bytes) throws NoSuchRepositoryFileException, IOException;
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#fileData, 'write')")
<T extends RepositoryFile> T updateBytes(T fileData, String contentType, byte[] bytes) throws NoSuchRepositoryFileException, IOException;
/**
* Load image to validate data and contentType, update image bytes and generate
......@@ -160,6 +181,7 @@ public interface RepositoryService {
* @throws NoSuchRepositoryFileException the no such repository file exception
* @throws IOException Signals that an I/O exception has occurred.
*/
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#imageData, 'write')")
RepositoryImage updateImageBytes(RepositoryImage imageData, String contentType, byte[] bytes) throws NoSuchRepositoryFileException, IOException;
/**
......@@ -171,6 +193,7 @@ public interface RepositoryService {
* repository
* @throws IOException Signals that an I/O exception has occurred.
*/
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#repositoryFile, 'delete')")
RepositoryFile removeFile(RepositoryFile repositoryFile) throws NoSuchRepositoryFileException, IOException;
/**
......@@ -182,6 +205,7 @@ public interface RepositoryService {
* @throws NoSuchRepositoryFileException the no such repository file exception
* @throws InvalidRepositoryPathException when the new path is invalid
*/
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#repositoryFile, 'write')")
RepositoryFile moveFile(RepositoryFile repositoryFile, String newPath) throws NoSuchRepositoryFileException, InvalidRepositoryPathException;
/**
......@@ -194,6 +218,7 @@ public interface RepositoryService {
* @throws InvalidRepositoryFileDataException the invalid repository file data
* exception
*/
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#repositoryFile, 'write')")
RepositoryFile moveAndRenameFile(RepositoryFile repositoryFile, String fullPath) throws InvalidRepositoryPathException, InvalidRepositoryFileDataException;
/**
......@@ -234,7 +259,8 @@ public interface RepositoryService {
* @throws NoSuchRepositoryFileException when file is not available in the
* repository
*/
RepositoryImage updateImageMetadata(UUID uuid, RepositoryImage imageData) throws NoSuchRepositoryFileException;
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#imageData, 'write')")
RepositoryImage updateImageMetadata(RepositoryImage imageData) throws NoSuchRepositoryFileException;
/**
* Remove repository image.
......@@ -245,6 +271,7 @@ public interface RepositoryService {
* repository
* @throws IOException Signals that an I/O exception has occurred.
*/
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#repositoryImage, 'delete')")
RepositoryImage removeImage(RepositoryImage repositoryImage) throws NoSuchRepositoryFileException, IOException;
/**
......
......@@ -109,7 +109,7 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea
* org.genesys.filerepository.model.RepositoryFile)
*/
@Override
@Transactional(rollbackFor=Throwable.class)
@Transactional(rollbackFor = Throwable.class)
public RepositoryFile addFile(final String repositoryPath, final String originalFilename, String contentType, final byte[] bytes, final RepositoryFile metaData)
throws InvalidRepositoryPathException, InvalidRepositoryFileDataException, IOException {
......@@ -241,6 +241,7 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea
}
file = repositoryImagePersistence.findByUuid(fileUuid);
if (file == null) {
throw new NoSuchRepositoryFileException();
}
......@@ -248,6 +249,23 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea
return file;
}
@SuppressWarnings("unchecked")
@Override
public <T extends RepositoryFile> T getFile(UUID fileUuid, int version) throws NoSuchRepositoryFileException {
RepositoryFile file = repositoryFilePersistence.findByUuidAndVersion(fileUuid, version);
if (file != null) {
return (T) file;
}
file = repositoryImagePersistence.findByUuidAndVersion(fileUuid, version);
if (file == null) {
throw new NoSuchRepositoryFileException();
}
return (T) file;
}
/*
* (non-Javadoc)
* @see org.genesys.filerepository.service.RepositoryService#getFile(java.lang.
......@@ -303,7 +321,7 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea
return repositoryFiles;
}
@Override
public Stream<RepositoryFile> streamFiles(String repositoryPath) {
return repositoryFilePersistence.streamByBasePath(repositoryPath);
......@@ -317,13 +335,13 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea
@SuppressWarnings("unchecked")
@Override
@Transactional
public <T extends RepositoryFile> T updateMetadata(final UUID uuid, final T fileData) throws NoSuchRepositoryFileException {
RepositoryFile repositoryFile = repositoryFilePersistence.findByUuid(uuid);
public <T extends RepositoryFile> T updateMetadata(final T fileData) throws NoSuchRepositoryFileException {
RepositoryFile repositoryFile = repositoryFilePersistence.findByUuidAndVersion(fileData.getUuid(), fileData.getVersion());
if (repositoryFile == null) {
throw new NoSuchRepositoryFileException();
}
if (fileData instanceof RepositoryImage) {
return (T) updateImageMetadata(uuid, (RepositoryImage) fileData);
return (T) updateImageMetadata((RepositoryImage) fileData);
}
repositoryFile.apply(fileData);
......@@ -339,8 +357,9 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea
*/
@Override
@Transactional
public RepositoryImage updateImageMetadata(final UUID uuid, final RepositoryImage imageData) throws NoSuchRepositoryFileException {
final RepositoryImage repositoryImage = repositoryImagePersistence.findByUuid(uuid);
public RepositoryImage updateImageMetadata(final RepositoryImage imageData) throws NoSuchRepositoryFileException {
final RepositoryImage repositoryImage = repositoryImagePersistence.findByUuidAndVersion(imageData.getUuid(), imageData.getVersion());
if (repositoryImage == null) {
throw new NoSuchRepositoryFileException();
}
......@@ -356,29 +375,32 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea
* @see org.genesys.filerepository.service.RepositoryService#updateBytes(
* org.genesys.filerepository.model .RepositoryFile, java.lang.String, byte[])
*/
@SuppressWarnings("unchecked")
@Override
@Transactional
public RepositoryFile updateBytes(final RepositoryFile repositoryFile, String contentType, final byte[] bytes) throws NoSuchRepositoryFileException, IOException {
if (repositoryFile == null) {
public <T extends RepositoryFile> T updateBytes(final T repositoryFile, String contentType, final byte[] bytes) throws NoSuchRepositoryFileException, IOException {
T storedFile = getFile(repositoryFile.getUuid(), repositoryFile.getVersion());
if (storedFile == null) {
throw new NoSuchRepositoryFileException();
}
if (repositoryFile instanceof RepositoryImage) {
return updateImageBytes((RepositoryImage) repositoryFile, contentType, bytes);
if (storedFile instanceof RepositoryImage) {
return (T) updateImageBytes((RepositoryImage) repositoryFile, contentType, bytes);
}
contentType = updateContentTypeIfNecessary(contentType, bytes);
// Calculate SHA-1 and MD5 sums
LOG.debug("updateByes length={}", bytes.length);
repositoryFile.setSha1Sum(DigestUtils.sha1Hex(bytes));
repositoryFile.setMd5Sum(DigestUtils.md5Hex(bytes));
repositoryFile.setSize(bytes.length);
storedFile.setSha1Sum(DigestUtils.sha1Hex(bytes));
storedFile.setMd5Sum(DigestUtils.md5Hex(bytes));
storedFile.setSize(bytes.length);
LOG.debug("updateByes length={} repoFile.size={}", bytes.length, repositoryFile.getSize());
repositoryFile.setContentType(contentType);
bytesStorageService.upsert(repositoryFile.getStoragePath(), repositoryFile.getFilename(), bytes);
storedFile.setContentType(contentType);
bytesStorageService.upsert(storedFile.getStoragePath(), storedFile.getFilename(), bytes);
return repositoryFilePersistence.save(repositoryFile);
return repositoryFilePersistence.save(storedFile);
}
/*
......@@ -389,22 +411,24 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea
@Override
@Transactional
public RepositoryImage updateImageBytes(final RepositoryImage repositoryImage, String contentType, final byte[] bytes) throws NoSuchRepositoryFileException, IOException {
if (repositoryImage == null) {
RepositoryImage storedFile = getFile(repositoryImage.getUuid(), repositoryImage.getVersion());
if (storedFile == null) {
throw new NoSuchRepositoryFileException();
}
contentType = updateContentTypeIfNecessary(contentType, bytes);
// Calculate SHA-1 and MD5 sums
repositoryImage.setSha1Sum(DigestUtils.sha1Hex(bytes));
repositoryImage.setMd5Sum(DigestUtils.md5Hex(bytes));
repositoryImage.setSize(bytes.length);
storedFile.setSha1Sum(DigestUtils.sha1Hex(bytes));
storedFile.setMd5Sum(DigestUtils.md5Hex(bytes));
storedFile.setSize(bytes.length);
repositoryImage.setContentType(contentType);
storedFile.setContentType(contentType);
fillImageProperties(repositoryImage, bytes);
fillImageProperties(storedFile, bytes);
bytesStorageService.upsert(repositoryImage.getStoragePath(), repositoryImage.getFilename(), bytes);
bytesStorageService.upsert(storedFile.getStoragePath(), storedFile.getFilename(), bytes);
return repositoryImagePersistence.save(repositoryImage);
return repositoryImagePersistence.save(storedFile);
}
/**
......
......@@ -161,7 +161,7 @@ public class FileRepositoryExtensionTest {
FileRepositoryTestUtil.checkFile(repoFile, initialPath, initialOriginalFilename, initialExtension, initialContentType);
repoFile.setOriginalFilename(originalFilename);
repoFile = fileRepoService.updateMetadata(repoFile.getUuid(), repoFile);
repoFile = fileRepoService.updateMetadata(repoFile);
return FileRepositoryTestUtil.checkFile(repoFile, initialPath, originalFilename, expectedExtension, initialContentType);
......
......@@ -138,7 +138,7 @@ public class FileRepositoryUpdateTest {
final String originalFilename = "originalFilename2" + extension;
repositoryFile.setOriginalFilename(originalFilename);
repositoryFile = fileRepoService.updateMetadata(repositoryFile.getUuid(), repositoryFile);
repositoryFile = fileRepoService.updateMetadata(repositoryFile);
assertThat("Extension was not updated", repositoryFile.getExtension(), equalTo(extension));
}
......@@ -181,7 +181,7 @@ public class FileRepositoryUpdateTest {
repositoryFile.setSubject(subject);
repositoryFile.setTitle(title);
final RepositoryFile repoFile = fileRepoService.updateMetadata(repositoryFile.getUuid(), repositoryFile);
final RepositoryFile repoFile = fileRepoService.updateMetadata(repositoryFile);
// Entity test
assertThat("RepositoryFile cannot be null", repoFile, notNullValue());
......
......@@ -100,7 +100,7 @@ public class MetadataTest {
assertThat(meta.getHeight(), is(7));
repoImage1.setOriginalFilename("test.png");
repoImage1 = repositoryService.updateMetadata(repoImage1.getUuid(), repoImage1);
repoImage1 = repositoryService.updateMetadata(repoImage1);
metadata = bytesStorageService.get(repoImage1.getStoragePath(), repoImage1.getMetadataFilename());
meta = objectMapper.readValue(metadata, RepositoryImage.class);
assertThat(meta.getOriginalFilename(), is(repoImage1.getOriginalFilename()));
......
......@@ -78,7 +78,7 @@
<jdk.source>1.8</jdk.source>
<show.deprecations>false</show.deprecations>
<application.blocks.version>1.1-SNAPSHOT</application.blocks.version>
<application.blocks.version>1.4-SNAPSHOT</application.blocks.version>
<maven-gpg-plugin.version>1.5</maven-gpg-plugin.version>
<nexus-staging-maven-plugin.version>1.6.8</nexus-staging-maven-plugin.version>
......@@ -87,6 +87,7 @@
<org.hamcrest.version>1.3</org.hamcrest.version>
<commons.io.version>2.4</commons.io.version>
<spring.version>4.3.2.RELEASE</spring.version>
<spring.security.version>4.1.3.RELEASE</spring.security.version>
<spring.data.version>1.10.4.RELEASE</spring.data.version>
<querydsl.version>4.1.4</querydsl.version>
<hibernate.version>4.3.11.Final</hibernate.version>
......
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