use of com.yahoo.elide.core.security.permissions.expressions.Expression in project elide by yahoo.
the class PermissionExpressionBuilder method buildAnyFieldFilterExpression.
/**
* Build an expression representing any field on an entity.
*
* @param forType Resource class
* @param requestScope requestScope
* @return Expressions
*/
public FilterExpression buildAnyFieldFilterExpression(Type<?> forType, RequestScope requestScope, Set<String> requestedFields) {
Class<? extends Annotation> annotationClass = ReadPermission.class;
ParseTree classPermissions = entityDictionary.getPermissionsForClass(forType, annotationClass);
FilterExpression entityFilter = filterExpressionFromParseTree(classPermissions, forType, requestScope);
// case where the permissions does not have ANY filterExpressionCheck
if (entityFilter == FALSE_USER_CHECK_EXPRESSION || entityFilter == NO_EVALUATION_EXPRESSION || entityFilter == TRUE_USER_CHECK_EXPRESSION) {
entityFilter = null;
}
FilterExpression allFieldsFilterExpression = entityFilter;
List<String> fields = entityDictionary.getAllExposedFields(forType).stream().filter(field -> requestedFields == null || requestedFields.contains(field)).collect(Collectors.toList());
for (String field : fields) {
ParseTree fieldPermissions = entityDictionary.getPermissionsForField(forType, field, annotationClass);
FilterExpression fieldExpression = filterExpressionFromParseTree(fieldPermissions, forType, requestScope);
if (fieldExpression == null && entityFilter == null) {
// this field will be visible across all instances
return null;
}
if (fieldExpression == null || fieldExpression == FALSE_USER_CHECK_EXPRESSION) {
// In either case this field is not useful for filtering when loading records
continue;
}
if (fieldExpression == NO_EVALUATION_EXPRESSION || fieldExpression == TRUE_USER_CHECK_EXPRESSION) {
// When the expression is TRUE_USER_CHECK_EXPRESSION all records can be loaded
return null;
}
if (allFieldsFilterExpression != null) {
allFieldsFilterExpression = new OrFilterExpression(allFieldsFilterExpression, fieldExpression);
} else {
allFieldsFilterExpression = fieldExpression;
}
}
return allFieldsFilterExpression;
}
use of com.yahoo.elide.core.security.permissions.expressions.Expression in project elide by yahoo.
the class PermissionExpressionBuilder method buildAnyFieldExpression.
/**
* Build an expression representing any field on an entity.
*
* @param condition The condition which triggered this permission expression check
* @param checkFn check function
* @param scope RequestScope
* @param requestedFields The list of requested fields
* @return Expressions
*/
private Expression buildAnyFieldExpression(final PermissionCondition condition, final Function<Check, Expression> checkFn, final Set<String> requestedFields, final RequestScope scope) {
Type<?> resourceClass = condition.getEntityClass();
Class<? extends Annotation> annotationClass = condition.getPermission();
ParseTree classPermissions = entityDictionary.getPermissionsForClass(resourceClass, annotationClass);
Expression entityExpression = normalizedExpressionFromParseTree(classPermissions, checkFn);
OrExpression allFieldsExpression = new OrExpression(FAILURE, null);
List<String> fields = entityDictionary.getAllExposedFields(resourceClass);
boolean entityExpressionUsed = false;
boolean fieldExpressionUsed = false;
for (String field : fields) {
if (requestedFields != null && !requestedFields.contains(field)) {
continue;
}
ParseTree fieldPermissions = entityDictionary.getPermissionsForField(resourceClass, field, annotationClass);
Expression fieldExpression = normalizedExpressionFromParseTree(fieldPermissions, checkFn);
if (fieldExpression == null) {
if (entityExpressionUsed) {
continue;
}
if (entityExpression == null) {
// One field had no permissions set - so we allow the action.
return SUCCESSFUL_EXPRESSION;
}
fieldExpression = entityExpression;
entityExpressionUsed = true;
} else {
fieldExpressionUsed = true;
}
allFieldsExpression = new OrExpression(allFieldsExpression, fieldExpression);
}
if (!fieldExpressionUsed) {
// If there are no permissions, allow access...
if (entityExpression == null) {
return SUCCESSFUL_EXPRESSION;
}
return new AnyFieldExpression(condition, entityExpression);
}
return new AnyFieldExpression(condition, allFieldsExpression);
}
use of com.yahoo.elide.core.security.permissions.expressions.Expression in project elide by yahoo.
the class ActivePermissionExecutor method checkPermissions.
/**
* First attempts to check user permissions (by looking in the cache and if not present by executing user
* permissions). If user permissions don't short circuit the check, run the provided expression executor.
*
* @param <A> type parameter
* @param resourceClass Resource class
* @param annotationClass Annotation class
* @param fields Set of all field names that is being accessed
* @param expressionSupplier Builds a permission expression.
* @param expressionExecutor Evaluates the expression (post user check evaluation)
*/
protected <A extends Annotation> ExpressionResult checkPermissions(Type<?> resourceClass, Class<A> annotationClass, Set<String> fields, Supplier<Expression> expressionSupplier, Optional<Function<Expression, ExpressionResult>> expressionExecutor) {
// If the user check has already been evaluated before, return the result directly and save the building cost
ImmutableSet<String> immutableFields = fields == null ? null : ImmutableSet.copyOf(fields);
ExpressionResult expressionResult = userPermissionCheckCache.get(Triple.of(annotationClass, resourceClass, immutableFields));
if (expressionResult == PASS) {
return expressionResult;
}
Expression expression = expressionSupplier.get();
if (expressionResult == null) {
expressionResult = executeExpressions(expression, annotationClass, Expression.EvaluationMode.USER_CHECKS_ONLY);
userPermissionCheckCache.put(Triple.of(annotationClass, resourceClass, immutableFields), expressionResult);
if (expressionResult == PASS) {
return expressionResult;
}
}
return expressionExecutor.map(executor -> executor.apply(expression)).orElse(expressionResult);
}
use of com.yahoo.elide.core.security.permissions.expressions.Expression in project elide by yahoo.
the class ActivePermissionExecutor method executeCommitChecks.
/**
* Execute commmit checks.
*/
@Override
public void executeCommitChecks() {
commitCheckQueue.forEach((expr) -> {
Expression expression = expr.getExpression();
ExpressionResult result = expression.evaluate(Expression.EvaluationMode.ALL_CHECKS);
if (result == FAIL) {
ForbiddenAccessException e = new ForbiddenAccessException(expr.getAnnotationClass(), expression, Expression.EvaluationMode.ALL_CHECKS);
if (log.isTraceEnabled()) {
log.trace("{}", e.getLoggedMessage());
}
throw e;
}
});
commitCheckQueue.clear();
}
use of com.yahoo.elide.core.security.permissions.expressions.Expression in project elide by yahoo.
the class PermissionExpressionNormalizationVisitorTest method orExpressionTest.
@Test
public void orExpressionTest() {
ParseTree tree;
Expression normalizedExpression;
tree = EntityPermissions.parseExpression("not (sampleCommit or sampleOperation)");
normalizedExpression = tree.accept(permissionExpressionVisitor).accept(normalizationVisitor);
Assertions.assertEquals("(NOT ((sampleCommit \u001B[34mWAS UNEVALUATED\u001B[m))) AND " + "(NOT ((sampleOperation \u001B[34mWAS UNEVALUATED\u001B[m)))", normalizedExpression.toString());
tree = EntityPermissions.parseExpression("not (Prefab.Role.All or sampleCommit or initCheck)");
normalizedExpression = tree.accept(permissionExpressionVisitor).accept(normalizationVisitor);
Assertions.assertEquals("((NOT ((Prefab.Role.All \u001B[34mWAS UNEVALUATED\u001B[m))) AND " + "(NOT ((sampleCommit \u001B[34mWAS UNEVALUATED\u001B[m)))) AND " + "(NOT ((initCheck \u001B[34mWAS UNEVALUATED\u001B[m)))", normalizedExpression.toString());
tree = EntityPermissions.parseExpression("not (parentInitCheck or passingOp) or (FailOp or shouldCache)");
normalizedExpression = tree.accept(permissionExpressionVisitor).accept(normalizationVisitor);
Assertions.assertEquals("((NOT ((parentInitCheck \u001B[34mWAS UNEVALUATED\u001B[m))) AND (NOT ((passingOp \u001B[34mWAS UNEVALUATED\u001B[m)))) OR " + "(((FailOp \u001B[34mWAS UNEVALUATED\u001B[m)) OR ((shouldCache \u001B[34mWAS UNEVALUATED\u001B[m)))", normalizedExpression.toString());
tree = EntityPermissions.parseExpression("not (parentInitCheck or passingOp) or not (FailOp or shouldCache)");
normalizedExpression = tree.accept(permissionExpressionVisitor).accept(normalizationVisitor);
Assertions.assertEquals("((NOT ((parentInitCheck \u001B[34mWAS UNEVALUATED\u001B[m))) AND (NOT ((passingOp \u001B[34mWAS UNEVALUATED\u001B[m)))) OR " + "((NOT ((FailOp \u001B[34mWAS UNEVALUATED\u001B[m))) AND (NOT ((shouldCache \u001B[34mWAS UNEVALUATED\u001B[m))))", normalizedExpression.toString());
tree = EntityPermissions.parseExpression("not (not (parentInitCheck or passingOp) or not (FailOp or shouldCache))");
normalizedExpression = tree.accept(permissionExpressionVisitor).accept(normalizationVisitor);
Assertions.assertEquals("(((parentInitCheck \u001B[34mWAS UNEVALUATED\u001B[m)) OR ((passingOp \u001B[34mWAS UNEVALUATED\u001B[m))) AND " + "(((FailOp \u001B[34mWAS UNEVALUATED\u001B[m)) OR ((shouldCache \u001B[34mWAS UNEVALUATED\u001B[m)))", normalizedExpression.toString());
}
Aggregations