use of com.yahoo.elide.core.security.permissions.ExpressionResult in project elide by yahoo.
the class VerifyFieldAccessFilterExpressionVisitor method visitPredicate.
/**
* Enforce ReadPermission on provided query filter.
*
* @return true if allowed, false if rejected
*/
@Override
public Boolean visitPredicate(FilterPredicate filterPredicate) {
RequestScope requestScope = resource.getRequestScope();
Set<PersistentResource> val = Collections.singleton(resource);
PermissionExecutor permissionExecutor = requestScope.getPermissionExecutor();
ExpressionResult result = permissionExecutor.evaluateFilterJoinUserChecks(resource, filterPredicate);
if (result == ExpressionResult.UNEVALUATED) {
result = evaluateUserChecks(filterPredicate, permissionExecutor);
}
if (result == ExpressionResult.PASS) {
return true;
}
if (result == ExpressionResult.FAIL) {
return false;
}
for (PathElement element : filterPredicate.getPath().getPathElements()) {
String fieldName = element.getFieldName();
if ("this".equals(fieldName)) {
continue;
}
try {
val = val.stream().filter(Objects::nonNull).flatMap(x -> getValueChecked(x, fieldName, requestScope).toList(LinkedHashSet::new).blockingGet().stream()).filter(Objects::nonNull).collect(Collectors.toSet());
} catch (ForbiddenAccessException e) {
result = permissionExecutor.handleFilterJoinReject(filterPredicate, element, e);
if (result == ExpressionResult.DEFERRED) {
continue;
}
// pass or fail
return result == ExpressionResult.PASS;
}
}
return true;
}
use of com.yahoo.elide.core.security.permissions.ExpressionResult in project elide by yahoo.
the class AbstractPermissionExecutor method executeExpressions.
/**
* Execute expressions.
*
* @param expression The expression to evaluate.
* @param annotationClass The permission associated with the expression.
* @param mode The evaluation mode of the expression.
*/
protected ExpressionResult executeExpressions(final Expression expression, final Class<? extends Annotation> annotationClass, Expression.EvaluationMode mode) {
ExpressionResult result = expression.evaluate(mode);
// Record the check
if (log.isTraceEnabled()) {
String checkKey = expression.toString();
Long checkOccurrences = checkStats.getOrDefault(checkKey, 0L) + 1;
checkStats.put(checkKey, checkOccurrences);
}
if (result == DEFERRED) {
/*
* Checking user checks only are an optimization step. We don't need to defer these checks because
* INLINE_ONLY checks will be evaluated later. Also, the user checks don't have
* the correct context to evaluate as COMMIT checks later.
*/
if (mode == Expression.EvaluationMode.USER_CHECKS_ONLY) {
return DEFERRED;
}
if (isInlineOnlyCheck(annotationClass)) {
// Force evaluation of checks that can only be executed inline.
result = expression.evaluate(Expression.EvaluationMode.ALL_CHECKS);
if (result == FAIL) {
ForbiddenAccessException e = new ForbiddenAccessException(annotationClass, expression, Expression.EvaluationMode.ALL_CHECKS);
if (log.isTraceEnabled()) {
log.trace("{}", e.getLoggedMessage());
}
throw e;
}
return result;
}
commitCheckQueue.add(new AbstractPermissionExecutor.QueuedCheck(expression, annotationClass));
return DEFERRED;
}
if (result == FAIL) {
ForbiddenAccessException e = new ForbiddenAccessException(annotationClass, expression, mode);
if (log.isTraceEnabled()) {
log.trace("{}", e.getLoggedMessage());
}
throw e;
}
return result;
}
use of com.yahoo.elide.core.security.permissions.ExpressionResult 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.ExpressionResult 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.ExpressionResult in project elide by yahoo.
the class PermissionExecutorTest method testUserCheckOnFieldSuccess.
@Test
public void testUserCheckOnFieldSuccess() {
OpenBean openBean = new OpenBean();
openBean.id = 1L;
PersistentResource resource = newResource(OpenBean.class, false);
RequestScope requestScope = resource.getRequestScope();
ExpressionResult result = requestScope.getPermissionExecutor().checkUserPermissions(ClassType.of(OpenBean.class), ReadPermission.class, "open");
assertEquals(ExpressionResult.PASS, result);
}
Aggregations