PL-7476 Paging does not work when using in-memory security constraints

This commit is contained in:
Andrey Subbotin 2016-07-13 11:56:25 +04:00
parent 11ff8d8a9a
commit 035dadd4bd
3 changed files with 40 additions and 21 deletions

View File

@ -55,9 +55,8 @@ public interface PersistenceSecurity extends Security {
/**
* Applies in-memory constraints to the entity
* @param entity -
* @return true, if entity should be filtered from client output
*/
boolean applyConstraints(Entity entity);
void applyConstraints(Entity entity);
/**
* Applies in-memory constraints to the entity fields
@ -71,6 +70,13 @@ public interface PersistenceSecurity extends Security {
*/
boolean filterByConstraints(Collection<Entity> entities);
/**
* Filter entities in collection by in-memory constraints
* @param entity - collection of entities that will be filtered
* @return true, if entity should be filtered from client output
*/
boolean filterByConstraints(Entity entity);
/**
* Reads security token and restores filtered data
* @param resultEntity -

View File

@ -98,6 +98,7 @@ public class DataManagerBean implements DataManager {
}
E result = null;
boolean needToApplyInMemoryConstraints = needToApplyInMemoryConstraints(context);
try (Transaction tx = persistence.createTransaction()) {
final EntityManager em = persistence.getEntityManager();
@ -119,7 +120,7 @@ public class DataManagerBean implements DataManager {
result = resultList.get(0);
}
if (result != null && needToApplyInMemoryConstraints(context) && security.applyConstraints(result)) {
if (result != null && needToApplyInMemoryConstraints && security.filterByConstraints(result)) {
result = null;
}
@ -130,7 +131,12 @@ public class DataManagerBean implements DataManager {
tx.commit();
}
attributeSecurity.afterLoad(result);
if (result != null) {
if (needToApplyInMemoryConstraints) {
security.applyConstraints(result);
}
attributeSecurity.afterLoad(result);
}
return result;
}
@ -174,10 +180,6 @@ public class DataManagerBean implements DataManager {
resultList = getResultList(context, query, ensureDistinct);
if (needToApplyInMemoryConstraints(context)) {
security.applyConstraints((Collection<Entity>) resultList);
}
// Fetch dynamic attributes
if (context.getView() != null
&& BaseGenericIdEntity.class.isAssignableFrom(context.getView().getEntityClass())
@ -188,6 +190,10 @@ public class DataManagerBean implements DataManager {
tx.commit();
}
if (needToApplyInMemoryConstraints(context)) {
security.applyConstraints((Collection<Entity>) resultList);
}
attributeSecurity.afterLoad(resultList);
return resultList;
@ -385,13 +391,16 @@ public class DataManagerBean implements DataManager {
if (isAuthorizationRequired() && userSessionSource.getUserSession().hasConstraints()) {
security.filterByConstraints(res);
security.applyConstraints(res);
}
}
tx.commit();
}
if (isAuthorizationRequired() && userSessionSource.getUserSession().hasConstraints()) {
security.applyConstraints(res);
}
for (Entity entity : res) {
if (!persisted.contains(entity)) {
View view = context.getViews().get(entity);

View File

@ -41,7 +41,6 @@ import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;
import static java.lang.String.format;
@ -130,19 +129,24 @@ public class PersistenceSecurityImpl extends SecurityImpl implements Persistence
return filtered;
}
@Override
public boolean filterByConstraints(Entity entity) {
return entity instanceof HasUuid && !isPermittedInMemory(entity);
}
@Override
public void applyConstraints(Collection<Entity> entities) {
Set<UUID> handled = new LinkedHashSet<>();
entities.stream().filter(entity -> entity instanceof HasUuid).forEach(entity -> {
internalApplyConstraints(entity, handled);
internalApplyConstraints(entity, handled, false);
});
}
@Override
public boolean applyConstraints(Entity entity) {
if (!(entity instanceof HasUuid))
return false;
return internalApplyConstraints(entity, new HashSet<>());
public void applyConstraints(Entity entity) {
if (entity instanceof HasUuid) {
internalApplyConstraints(entity, new HashSet<>(), false);
}
}
@Override
@ -211,13 +215,13 @@ public class PersistenceSecurityImpl extends SecurityImpl implements Persistence
}
} catch (JpqlSyntaxException e) {
log.error("Syntax errors found in constraint's JPQL expressions. Entity [{}]. Constraint ID [{}].",
entityName, constraint.getId(), e);
entityName, constraint.getId(), e);
throw new RowLevelSecurityException(
"Syntax errors found in constraint's JPQL expressions. Please see the logs.", entityName);
} catch (Exception e) {
log.error("An error occurred when applying security constraint. Entity [{}]. Constraint ID [{}].",
entityName, constraint.getId(), e);
entityName, constraint.getId(), e);
throw new RowLevelSecurityException(
"An error occurred when applying security constraint. Please see the logs.", entityName);
@ -228,7 +232,7 @@ public class PersistenceSecurityImpl extends SecurityImpl implements Persistence
Set<UUID> filtered = new LinkedHashSet<>();
for (Iterator<Entity> iterator = entities.iterator(); iterator.hasNext(); ) {
Entity next = iterator.next();
if (internalApplyConstraints(next, handled)) {
if (internalApplyConstraints(next, handled, true)) {
filtered.add(((HasUuid) next).getUuid());
//we ignore situations when the collection is immutable
iterator.remove();
@ -239,10 +243,10 @@ public class PersistenceSecurityImpl extends SecurityImpl implements Persistence
}
@SuppressWarnings("unchecked")
protected boolean internalApplyConstraints(Entity entity, Set<UUID> handled) {
protected boolean internalApplyConstraints(Entity entity, Set<UUID> handled, boolean checkPermitted) {
MetaClass metaClass = entity.getMetaClass();
if (!isPermittedInMemory(entity)) {
if (!isPermittedInMemory(entity) && checkPermitted) {
return true;
}
@ -262,7 +266,7 @@ public class PersistenceSecurityImpl extends SecurityImpl implements Persistence
}
} else if (value instanceof Entity && value instanceof HasUuid) {
Entity valueEntity = (Entity) value;
if (internalApplyConstraints(valueEntity, handled)) {
if (internalApplyConstraints(valueEntity, handled, true)) {
//we ignore the situation when the field is read-only
entity.setValue(property.getName(), null);
if (entity instanceof BaseGenericIdEntity) {