Commit 1af9af3d authored by Matija Obreza's avatar Matija Obreza
Browse files

Merge branch '171-acl-parent-object' into 'master'

Resolve "ACL parent object"

Closes #171

See merge request !164
parents ebe9ed81 78943178
Pipeline #5517 passed with stages
in 4 minutes and 42 seconds
......@@ -32,7 +32,6 @@ import javax.persistence.Lob;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.OrderColumn;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
......@@ -203,6 +202,14 @@ public class Dataset extends UuidModel implements Publishable, SelfCleaning, Pub
trimStringsToNull();
}
/**
* Owner is the ACL parent object for the dataset
*/
@Override
public AclAwareModel aclParentObject() {
return this.owner;
}
/**
* Gets the creators.
......
......@@ -244,6 +244,14 @@ public class Descriptor extends UuidModel implements SelfCleaning, Publishable,
trimStringsToNull();
}
/**
* Owner is the ACL parent object for the descriptor
*/
@Override
public AclAwareModel aclParentObject() {
return this.owner;
}
/**
* Instantiates a new descriptor.
*
......
......@@ -145,6 +145,14 @@ public class DescriptorList extends UuidModel implements Publishable, SelfCleani
trimStringsToNull();
}
/**
* Owner is the ACL parent object for the descriptor list
*/
@Override
public AclAwareModel aclParentObject() {
return this.owner;
}
/**
* Gets the publisher.
*
......
......@@ -41,6 +41,7 @@ import org.genesys.catalog.persistence.dataset.DatasetVersionsRepository;
import org.genesys.catalog.service.DatasetService;
import org.genesys.catalog.service.filters.DatasetFilter;
import org.genesys.catalog.util.Utils;
import org.genesys.common.model.Partner;
import org.genesys.filerepository.InvalidRepositoryFileDataException;
import org.genesys.filerepository.InvalidRepositoryPathException;
import org.genesys.filerepository.NoSuchRepositoryFileException;
......@@ -260,8 +261,8 @@ public class DatasetServiceImpl implements DatasetService {
if (utils.hasRole(UserRole.ADMINISTRATOR)) {
return datasetRepository.findAll(filter.buildQuery(), page);
} else {
final HashSet<Long> ids = new HashSet<>(utils.listObjectIdentityIdsForCurrentUser(Dataset.class, BasePermission.WRITE));
return datasetRepository.findAll(dataset.id.in(ids).and(filter.buildQuery()), page);
final HashSet<Long> partners = new HashSet<>(utils.listObjectIdentityIdsForCurrentUser(Partner.class, BasePermission.WRITE));
return datasetRepository.findAll(dataset.owner.id.in(partners).and(filter.buildQuery()), page);
}
}
......
......@@ -38,6 +38,7 @@ import org.genesys.catalog.service.DescriptorListService;
import org.genesys.catalog.service.DescriptorService;
import org.genesys.catalog.service.filters.DescriptorListFilter;
import org.genesys.catalog.util.Utils;
import org.genesys.common.model.Partner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -309,8 +310,8 @@ public class DescriptorListServiceImpl implements DescriptorListService {
if (utils.hasRole(UserRole.ADMINISTRATOR)) {
return descriptorListRepository.findAll(filter.buildQuery(), page);
} else {
final HashSet<Long> ids = new HashSet<>(utils.listObjectIdentityIdsForCurrentUser(DescriptorList.class, BasePermission.WRITE));
return descriptorListRepository.findAll(descriptorList.id.in(ids).and(filter.buildQuery()), page);
final HashSet<Long> partners = new HashSet<>(utils.listObjectIdentityIdsForCurrentUser(Partner.class, BasePermission.WRITE));
return descriptorListRepository.findAll(descriptorList.owner.id.in(partners).and(filter.buildQuery()), page);
}
}
......
......@@ -204,8 +204,8 @@ public class DescriptorServiceImpl implements DescriptorService {
if (utils.hasRole(UserRole.ADMINISTRATOR)) {
return descriptorRepository.findAll(filter.buildQuery(), page);
} else {
final HashSet<Long> ids = new HashSet<>(utils.listObjectIdentityIdsForCurrentUser(Descriptor.class, BasePermission.WRITE));
return descriptorRepository.findAll(descriptor.id.in(ids).and(filter.buildQuery()), page);
final HashSet<Long> partners = new HashSet<>(utils.listObjectIdentityIdsForCurrentUser(Partner.class, BasePermission.WRITE));
return descriptorRepository.findAll(descriptor.owner.id.in(partners).and(filter.buildQuery()), page);
}
}
......
......@@ -66,7 +66,7 @@ public class ElasticJPAListener {
*/
@AfterReturning(value = "execution(* org.springframework.data.jpa.repository.JpaRepository.save(..))", returning = "result")
public void afterPersist(final JoinPoint joinPoint, final Object result) {
LOG.warn("JPA afterPersist {} {}", joinPoint.toLongString(), joinPoint.getTarget());
LOG.debug("JPA afterPersist {} {}", joinPoint.toLongString(), joinPoint.getTarget());
try {
scheduleReindexing(result);
......@@ -85,7 +85,7 @@ public class ElasticJPAListener {
final Object[] args = joinPoint.getArgs();
try {
final Object removed = args[0];
LOG.warn("JPA afterRemove: {} {}", joinPoint.toLongString(), joinPoint.getTarget());
LOG.debug("JPA afterRemove: {} {}", joinPoint.toLongString(), joinPoint.getTarget());
scheduleReindexing(removed);
} catch (Throwable e) {
LOG.error(e.getMessage(), e);
......
......@@ -15,6 +15,9 @@
*/
package org.genesys.catalog.server.config;
import java.util.List;
import javax.persistence.EntityManager;
import javax.transaction.Transactional;
import org.apache.commons.lang3.StringUtils;
......@@ -23,7 +26,12 @@ import org.genesys.blocks.oauth.model.OAuthRole;
import org.genesys.blocks.oauth.persistence.OAuthClientRepository;
import org.genesys.blocks.security.NotUniqueUserException;
import org.genesys.blocks.security.UserException;
import org.genesys.blocks.security.model.AclEntry;
import org.genesys.blocks.security.model.AclObjectIdentity;
import org.genesys.blocks.security.model.BasicUser;
import org.genesys.blocks.security.model.QAclObjectIdentity;
import org.genesys.blocks.security.persistence.AclEntryPersistence;
import org.genesys.blocks.security.persistence.AclObjectIdentityPersistence;
import org.genesys.blocks.security.service.PasswordPolicy.PasswordPolicyException;
import org.genesys.catalog.model.dataset.Dataset;
import org.genesys.catalog.model.traits.Descriptor;
......@@ -32,6 +40,9 @@ import org.genesys.catalog.model.user.User;
import org.genesys.catalog.model.user.UserRole;
import org.genesys.catalog.model.vocab.ControlledVocabulary;
import org.genesys.catalog.model.vocab.VocabularyTerm;
import org.genesys.catalog.persistence.dataset.DatasetRepository;
import org.genesys.catalog.persistence.traits.DescriptorListRepository;
import org.genesys.catalog.persistence.traits.DescriptorRepository;
import org.genesys.catalog.persistence.user.UserRepository;
import org.genesys.catalog.server.service.ElasticsearchService;
import org.genesys.catalog.service.UserService;
......@@ -47,6 +58,7 @@ import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import com.google.common.collect.Sets;
import com.querydsl.core.BooleanBuilder;
/**
* Run things at startup and after application context is initialized.
......@@ -97,6 +109,8 @@ public class ApplicationStartup implements InitializingBean, ApplicationListener
}
startup();
cleanupAcl();
aclParentObject();
}
/**
......@@ -165,6 +179,100 @@ public class ApplicationStartup implements InitializingBean, ApplicationListener
LOG.info("Startup initializer done.");
}
@Autowired
private EntityManager entityManager;
@Autowired
private AclEntryPersistence aclEntryPersistence;
private void cleanupAcl() {
Iterable<AclObjectIdentity> OIDs = aclObjectIdentityPersistence.findAll();
for (AclObjectIdentity OID : OIDs) {
try {
Class<?> clazz = Class.forName(OID.getAclClass().getAclClass());
Object entity = entityManager.find(clazz, OID.getObjectIdIdentity());
if (entity == null) {
LOG.info("{} with ID={} no longer exists, clearing ACL", clazz.getName(), OID.getObjectIdIdentity());
final List<AclEntry> aclEntries = aclEntryPersistence.findByObjectIdentity(OID);
if (aclEntries != null) {
aclEntryPersistence.delete(aclEntries);
}
aclObjectIdentityPersistence.delete(OID);
}
} catch (ClassNotFoundException e) {
LOG.error(e.getMessage(), e);
}
}
}
@Autowired
private AclObjectIdentityPersistence aclObjectIdentityPersistence;
@Autowired
private DatasetRepository datasetRepository;
@Autowired
private DescriptorRepository descriptorRepository;
@Autowired
private DescriptorListRepository descriptorListRepository;
private void aclParentObject() {
Iterable<AclObjectIdentity> datasetOIDs = aclObjectIdentityPersistence.findAll(new BooleanBuilder().and(QAclObjectIdentity.aclObjectIdentity.aclClass.aclClass.eq(Dataset.class.getName())));
for (AclObjectIdentity datasetOID : datasetOIDs) {
Dataset dataset = datasetRepository.findOne(datasetOID.getObjectIdIdentity());
if (dataset == null) {
LOG.warn("No dataset with id {}", datasetOID.getObjectIdIdentity());
continue;
}
Partner owner = dataset.getOwner();
AclObjectIdentity ownerOID = aclObjectIdentityPersistence.findByObjectIdAndClassname(owner.getId(), Partner.class.getName());
if (ownerOID != null) {
if (datasetOID.getParentObject() == null || ! datasetOID.getParentObject().getId().equals(ownerOID.getId())) {
LOG.info("Setting parent object of dataset {} to {}", dataset.getTitle(), owner.getShortName());
datasetOID.setParentObject(ownerOID);
datasetOID.setEntriesInheriting(true);
}
}
}
aclObjectIdentityPersistence.save(datasetOIDs);
Iterable<AclObjectIdentity> descriptorOIDs = aclObjectIdentityPersistence.findAll(new BooleanBuilder().and(QAclObjectIdentity.aclObjectIdentity.aclClass.aclClass.eq(Descriptor.class.getName())));
for (AclObjectIdentity descriptorOID : descriptorOIDs) {
Descriptor descriptor = descriptorRepository.findOne(descriptorOID.getObjectIdIdentity());
if (descriptor == null) {
LOG.warn("No descriptor with id {}", descriptorOID.getObjectIdIdentity());
continue;
}
Partner owner = descriptor.getOwner();
AclObjectIdentity ownerOID = aclObjectIdentityPersistence.findByObjectIdAndClassname(owner.getId(), Partner.class.getName());
if (ownerOID != null) {
if (descriptorOID.getParentObject() == null || ! descriptorOID.getParentObject().getId().equals(ownerOID.getId())) {
LOG.info("Setting parent object of descriptor {} to {}", descriptor.getTitle(), owner.getShortName());
descriptorOID.setParentObject(ownerOID);
descriptorOID.setEntriesInheriting(true);
}
}
}
aclObjectIdentityPersistence.save(descriptorOIDs);
Iterable<AclObjectIdentity> descriptorListOIDs = aclObjectIdentityPersistence.findAll(new BooleanBuilder().and(QAclObjectIdentity.aclObjectIdentity.aclClass.aclClass.eq(DescriptorList.class.getName())));
for (AclObjectIdentity descriptorListOID : descriptorListOIDs) {
DescriptorList decriptorList = descriptorListRepository.findOne(descriptorListOID.getObjectIdIdentity());
if (decriptorList == null) {
LOG.warn("No descriptor list with id {}", descriptorListOID.getObjectIdIdentity());
continue;
}
Partner owner = decriptorList.getOwner();
AclObjectIdentity ownerOID = aclObjectIdentityPersistence.findByObjectIdAndClassname(owner.getId(), Partner.class.getName());
if (ownerOID != null) {
if (descriptorListOID.getParentObject() == null || ! descriptorListOID.getParentObject().getId().equals(ownerOID.getId())) {
LOG.info("Setting parent object of descriptor list {} to {}", decriptorList.getTitle(), owner.getShortName());
descriptorListOID.setParentObject(ownerOID);
descriptorListOID.setEntriesInheriting(true);
}
}
}
aclObjectIdentityPersistence.save(descriptorListOIDs);
}
private void reindexElasticsearch() {
elasticsearch.reindex(Crop.class);
elasticsearch.reindex(Partner.class);
......
......@@ -15,10 +15,10 @@
*/
package org.genesys.catalog.server.controller.api.v0;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.genesys.catalog.exceptions.InvalidApiUsageException;
import org.genesys.catalog.exceptions.NotFoundElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
......@@ -39,7 +39,7 @@ import org.springframework.web.context.request.WebRequest;
public class ApiExceptionHandler {
/** The log. */
protected final Log LOG = LogFactory.getLog(getClass());
protected final Logger LOG = LoggerFactory.getLogger(getClass());
// @ResponseStatus(code = HttpStatus.NOT_FOUND)
// @ExceptionHandler(NoSuchAccessionException.class)
......@@ -61,7 +61,7 @@ public class ApiExceptionHandler {
@ExceptionHandler({ AuthenticationCredentialsNotFoundException.class })
@ResponseBody
public ApiError<Exception> handleMissingCredentials(final Exception e, final WebRequest request) {
LOG.warn("Authentication is required.", e);
LOG.warn("Authentication is required: {}", request.getDescription(true));
return new ApiError<>(e);
}
......@@ -76,7 +76,7 @@ public class ApiExceptionHandler {
@ExceptionHandler({ AccessDeniedException.class })
@ResponseBody
public ApiError<Exception> handleAccessDenied(final Exception e, final WebRequest request) {
LOG.warn("Authentication is required.", e);
LOG.warn("Access denied: {}", request.getDescription(true));
return new ApiError<>(e);
}
......@@ -91,7 +91,7 @@ public class ApiExceptionHandler {
@ExceptionHandler(HttpMessageNotReadableException.class)
@ResponseBody
public ApiError<Exception> handleConverterError(final Exception e, final WebRequest request) {
LOG.warn("Invalid payload provided.", e);
LOG.warn("Invalid payload provided: {}", request.getDescription(true));
return new ApiError<>(e);
}
......@@ -106,7 +106,7 @@ public class ApiExceptionHandler {
@ExceptionHandler({ InvalidApiUsageException.class, ConcurrencyFailureException.class })
@ResponseBody
public ApiError<Exception> handleInvalidApiUsage(final Exception e, final WebRequest request) {
LOG.warn("Invalid payload provided.", e);
LOG.warn("API error: {} in {}", e.getMessage(), request.getDescription(true));
return new ApiError<>(e);
}
......@@ -121,7 +121,7 @@ public class ApiExceptionHandler {
@ExceptionHandler(NotFoundElement.class)
@ResponseBody
public ApiError<Exception> handleNotFound(final Exception e, final WebRequest request) {
LOG.warn("Element not found", e);
LOG.warn("Element not found: {}", request.getDescription(true));
return new ApiError<>(e);
}
......@@ -136,7 +136,7 @@ public class ApiExceptionHandler {
@ExceptionHandler(Throwable.class)
@ResponseBody
public ApiError<Exception> handleServerError(final Exception e, final WebRequest request) {
LOG.error("Wow! Such! Exception!", e);
LOG.error("Wow! Such! Exception! {}", request.getDescription(true), e);
return new ApiError<>(e);
}
}
......@@ -21,6 +21,7 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.genesys.blocks.model.JsonViews;
import org.genesys.blocks.oauth.model.OAuthClient;
import org.genesys.blocks.oauth.service.OAuthClientDetailsService;
import org.genesys.blocks.security.model.AclObjectIdentity;
......@@ -43,6 +44,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.annotation.JsonView;
/**
* The Class PermissionController.
*
......@@ -75,6 +78,7 @@ public class PermissionController {
*/
@Transactional
@PostMapping(value = "/permissions/{clazz}/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
@JsonView(JsonViews.Minimal.class)
public AclObjectIdentity addPermission(@PathVariable(value = "clazz") final String className, @PathVariable("id") final long id,
@RequestBody final SidPermissions sidPermissions) {
final AclObjectIdentity objectIdentity = aclService.ensureObjectIdentity(id, className);
......@@ -94,6 +98,7 @@ public class PermissionController {
*/
@Transactional(readOnly = true)
@GetMapping(value = "/permissions/{clazz}/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
@JsonView(JsonViews.Minimal.class)
public AclObjectIdentity permissions(@PathVariable(value = "clazz") final String className, @PathVariable("id") final long id) {
final AclObjectIdentity objectIdentity = aclService.getObjectIdentity(id, className);
return lazyLoadForJson(objectIdentity);
......@@ -121,6 +126,7 @@ public class PermissionController {
* @return the acl object identity
*/
@GetMapping(value = "/permissions/{aclObjectIdentityId}", produces = MediaType.APPLICATION_JSON_VALUE)
@JsonView(JsonViews.Minimal.class)
public AclObjectIdentity permissions(@PathVariable(value = "aclObjectIdentityId") final long id) {
final AclObjectIdentity objectIdentity = aclService.getObjectIdentity(id);
return lazyLoadForJson(objectIdentity);
......
Supports Markdown
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