Skip to content

User-based content filtering

Fluxzero provides a flexible way to redact or tailor object content per user using the @FilterContent annotation.

This enables domain models or documents to define exactly what is visible to different users, based on roles, ownership, or context.


This response value shows internal notes only to an administrator:

public record OrderView(String orderId, String internalNotes) {
@FilterContent
OrderView filter(User user) {
return user != null && user.hasRole("admin") ? this : new OrderView(orderId, null);
}
}

To invoke filtering:

OrderView filtered = Fluxzero.filterContent(order, currentUser);

Filtering applies recursively to fields and nested objects. If a nested item is a list, map, or complex structure, it will also be filtered using its own @FilterContent method if present.

If a nested object returns null from filtering:

  • It is removed from a list
  • It is excluded from a map

Filtering methods can optionally accept both:

  • The current User
  • The root object being filtered

This is useful for making decisions based on global context.

@FilterContent
LineItem filter(User user, Order root) {
return root.isOwner(user) ? this : null;
}

For automatic handler-result filtering, a CompletableFuture is filtered after successful completion, using the original request context and viewer even when completion happens on another thread. Failed or cancelled futures propagate without running content filters. This applies equally to ordinary values and Graph results.

Developers can explicitly apply filtering by calling Fluxzero.filterContent(object, user) when they want precise control over when and how filtering occurs.

This is useful when you want to:

  • Filter only part of a response
  • Aggregate or transform data before filtering
  • Perform filtering outside of handler contexts

For example, you may want to manually filter a document before returning it from a method:

public Optional<Order> getFilteredOrder(User user, OrderId orderId) {
Optional<Order> order = Fluxzero.getDocument(orderId, "orders");
return Fluxzero.filterContent(order, user);
}

Filtering can be triggered automatically for request results when @FilterContent is also applied to the handler method, its class, or its package (or parent package).

This eliminates the need to call Fluxzero.filterContent(...) manually in many cases.

  • Method level: filters results of a specific handler method
  • Type level: filters results of all handler methods in a class
  • Package level: filters results of all handler methods in a package or subpackage

For example, you can annotate a query handler so that all results it returns are automatically filtered based on the current user.

public record GetOrder(OrderId orderId) implements Request<Order> {
@HandleQuery
@FilterContent
public Optional<Order> handle() {
return Fluxzero.getDocument(orderId, "orders");
}
}

Explicit filtering remains available for finer-grained control.



© 2026 Fluxzero