Commit e2b2fa91 authored by Matija Obreza's avatar Matija Obreza

RepositoryFolder: inherit permissions from alternative ACL OID

- Allows folders to inherit permissions from other business entities
parent d514b734
Pipeline #7345 passed with stage
in 3 minutes and 15 seconds
......@@ -139,6 +139,13 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-acl</artifactId>
<version>${spring.security.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
......
......@@ -35,6 +35,7 @@ import javax.persistence.Transient;
import org.genesys.blocks.model.JsonViews;
import org.genesys.blocks.model.UuidModel;
import org.genesys.blocks.security.model.AclAwareModel;
import org.genesys.blocks.security.model.AclObjectIdentity;
import org.genesys.filerepository.InvalidRepositoryPathException;
import org.genesys.filerepository.service.impl.PathValidator;
import org.hibernate.annotations.Type;
......@@ -115,6 +116,11 @@ public class RepositoryFolder extends UuidModel implements AclAwareModel {
@Transient
private Path folderPath;
/** The parent ACL OID */
@JsonIgnore
@ManyToOne(cascade = {}, fetch = FetchType.LAZY)
private AclObjectIdentity parentOid;
/**
* Pre persist.
*/
......@@ -135,6 +141,11 @@ public class RepositoryFolder extends UuidModel implements AclAwareModel {
public AclAwareModel aclParentObject() {
return this.parent;
}
@Override
public AclObjectIdentity aclParentObjectIdentity() {
return this.parentOid;
}
/**
* Gets the parent.
......@@ -154,6 +165,24 @@ public class RepositoryFolder extends UuidModel implements AclAwareModel {
this.parent = parent;
}
/**
* Sets the ACL parent object identity of the folder.
*
* @param parentOid the new parent OID
*/
public void setParentOid(AclObjectIdentity parentOid) {
this.parentOid = parentOid;
}
/**
* Gets the ACL parent object identity of the folder.
*
* @return the parent OID
*/
public AclObjectIdentity getParentOid() {
return parentOid;
}
/**
* Gets the children.
*
......
......@@ -22,6 +22,7 @@ import java.util.List;
import java.util.UUID;
import java.util.stream.Stream;
import org.genesys.blocks.security.model.AclAwareModel;
import org.genesys.filerepository.FolderNotEmptyException;
import org.genesys.filerepository.InvalidRepositoryFileDataException;
import org.genesys.filerepository.InvalidRepositoryPathException;
......@@ -302,6 +303,16 @@ public interface RepositoryService {
*/
RepositoryFolder ensureFolder(Path path) throws InvalidRepositoryPathException;
/**
* Ensure folder exists with specified ACL parent object
*
* @param path the folder path in repository
* @param aclParentObject business entity "owning" the folder
* @return
* @throws InvalidRepositoryPathException
*/
RepositoryFolder ensureFolder(Path path, AclAwareModel aclParentObject) throws InvalidRepositoryPathException;
/**
* Delete an empty folder (no children, no files).
*
......
......@@ -34,6 +34,8 @@ import javax.imageio.ImageIO;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.tika.Tika;
import org.genesys.blocks.security.SecurityContextUtil;
import org.genesys.blocks.security.model.AclAwareModel;
import org.genesys.blocks.security.service.CustomAclService;
import org.genesys.filerepository.FolderNotEmptyException;
import org.genesys.filerepository.InvalidRepositoryFileDataException;
import org.genesys.filerepository.InvalidRepositoryPathException;
......@@ -96,6 +98,10 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea
@Autowired
private BytesStorageService bytesStorageService;
/** The ACL service */
@Autowired
private CustomAclService aclService;
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
......@@ -805,6 +811,51 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea
return folderRepository.findByPath(nPath.toString());
}
@Override
@Transactional
@PreAuthorize("hasRole('ADMINISTRATOR')")
public RepositoryFolder ensureFolder(Path folderPath, AclAwareModel parentEntity) throws InvalidRepositoryPathException {
assert(folderPath != null);
assert(parentEntity != null);
PathValidator.checkValidPath(folderPath);
folderPath = folderPath.normalize().toAbsolutePath();
PathValidator.checkValidPath(folderPath.toString());
if ("/".equals(folderPath.toString())) {
// Root folder
if (! SecurityContextUtil.hasRole("ADMINISTRATOR")) {
// Only administrator can create folders on root
throw new AccessDeniedException("No WRITE permission on /");
}
return null;
} else {
PathValidator.checkValidFolderName(folderPath.getFileName().toString());
}
RepositoryFolder folder = folderRepository.findByPath(folderPath.toString());
if (folder == null) {
// Create new folder
folder = new RepositoryFolder();
folder.setName(folderPath.getFileName().toString());
// This checks permissions on parent, but we're running as ADMIN
folder.setParent(ensureFolder(folderPath.getParent()));
folder.setParentOid(aclService.getObjectIdentity(parentEntity));
if (folder.getParentOid() == null) {
throw new RuntimeException("Parent entity does not have an ACL OID: " + parentEntity);
}
folder = folderRepository.save(folder);
} else {
// Update parent OID
folder.setParentOid(aclService.getObjectIdentity(parentEntity));
folder = folderRepository.save(folder);
}
return folder;
}
/*
* (non-Javadoc)
......
......@@ -49,7 +49,7 @@ import com.querydsl.jpa.impl.JPAQueryFactory;
@PropertySources({ @PropertySource("classpath:/spring/spring.properties"), @PropertySource("classpath:/application.properties") })
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = { "org.genesys.blocks.model",
"org.genesys.filerepository.persistence" }, entityManagerFactoryRef = "entityManagerFactory", transactionManagerRef = "transactionManager")
"org.genesys.filerepository.persistence", "org.genesys.blocks.security.persistence" }, entityManagerFactoryRef = "entityManagerFactory", transactionManagerRef = "transactionManager")
public class DatabaseConfig {
/** The env. */
......@@ -108,7 +108,7 @@ public class DatabaseConfig {
bean.setDataSource(dataSource());
bean.setPersistenceUnitName("spring-jpa");
bean.setPackagesToScan("org.genesys.filerepository.model");
bean.setPackagesToScan("org.genesys.filerepository.model", "org.genesys.blocks.security.model");
bean.setPersistenceProvider(new HibernatePersistenceProvider());
final HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
......
......@@ -19,6 +19,8 @@ package org.genesys.filerepository.config;
import java.io.File;
import org.apache.commons.io.FileUtils;
import org.genesys.blocks.security.service.CustomAclService;
import org.genesys.blocks.security.service.impl.CustomAclServiceImpl;
import org.genesys.filerepository.service.BytesStorageService;
import org.genesys.filerepository.service.ImageGalleryService;
import org.genesys.filerepository.service.RepositoryService;
......@@ -166,4 +168,8 @@ public class ServiceBeanConfig implements InitializingBean, DisposableBean {
return new ThumbnailGenerator1();
}
@Bean
public CustomAclService aclService() {
return new CustomAclServiceImpl();
}
}
......@@ -29,3 +29,4 @@ log4j.category.org.genesys.filerepository=info
# Internal Hibernate logging is at ERROR
log4j.category.org.hibernate.engine.jdbc=fatal
log4j.category.org.genesys.blocks.security.SecurityContextUtil=error
......@@ -65,6 +65,13 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-acl</artifactId>
<version>${spring.security.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
......@@ -73,6 +80,12 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.genesys-pgr</groupId>
<artifactId>application-blocks-security</artifactId>
<version>1.5-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.genesys-pgr</groupId>
<artifactId>file-repository-core</artifactId>
......
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