Channel Filtering

Overview

Channel filtering controls which channels are visible to CMS users in the Experience manager and under the [view] button for a document. Bloomreach Content uses a pluggable filtering system to determine channel visibility based on user permissions and other criteria.

Default Channel Filters

By default, two channel filters are always active:

  • ContentReadChannelFilter
  • PrivilegeBasedChannelFilter

These filters ensure that users only see channels they are authorized to access. For details on channel access, see Access Channels.

For example, consider the following content structure:

/content:
  /documents:
    /intranet:
    /extranet:
    /management:

If a CMS user has read access to intranet and extranet, but not to management, only the corresponding channels for intranet and extranet are visible in the Experience manager. The channel for management is hidden.

Customizing Channel Filtering

You can extend channel filtering by adding custom filters in addition to the built-in filters. To add a custom channel filter:

  1. Implement a filter as a java.util.function.BiPredicate<Session, Channel>.
  2. Register your filter as a Spring bean in the customChannelFilters list.

Built-in Channel Filter Examples

The following examples show the default channel filters. Each filter implements the BiPredicate<Session, Channel> interface. The Session parameter represents the currently logged-in CMS user.

ContentReadChannelFilter

This filter checks if the user has read access to the channel's content root.

public class ContentReadChannelFilter implements BiPredicate<Session, Channel> { private static final Logger log = LoggerFactory.getLogger(ContentReadChannelFilter.class); @Override public boolean test(final Session userSession, final Channel channel) { try { if (userSession.nodeExists(channel.getContentRoot())) { log.debug("Predicate passed for channel '{}' because user '{}' has read access on '{}'", new String[]{channel.toString(), userSession.getUserID(), channel.getContentRoot()}); return true; } log.info("Skipping channel '{}' for user '{}' because she has no read access on '{}'", new String[]{channel.toString(), userSession.getUserID(), channel.getContentRoot()}); return false; } catch (RepositoryException e) { log.warn("Exception while trying to check channel content root '{}'. Skip that channel:", channel.getContentRoot(), e); return false; } } }

PrivilegeBasedChannelFilter

This filter checks if the user has the hippo:channel-viewer privilege for the channel.

public class PrivilegeBasedChannelFilter implements BiPredicate<Session, Channel> { private static final Logger log = LoggerFactory.getLogger(ContentReadChannelFilter.class); @Override public boolean test(final Session userSession, final Channel channel) { try { final Privilege privilege = userSession.getAccessControlManager().privilegeFromName("hippo:channel-viewer"); return userSession.getAccessControlManager().hasPrivileges(channel.getHstConfigPath(), new Privilege[]{privilege}); } catch (RepositoryException e) { log.warn("Exception while checking privilege 'hippo:channel-viewer' for channel '{}'. Skip that channel:", channel.getHstConfigPath(), e); return false; } } }

Example: Adding a Custom Channel Filter

Suppose you want to display a channel in the Experience manager only if the CMS user's locale matches the channel's locale. You can implement this requirement with a custom filter.

Step 1: Implement ChannelLocaleBasedFilter

public class ChannelLocaleBasedFilter implements BiPredicate<Session, Channel> { private static final Logger log = LoggerFactory.getLogger(ChannelNodeBasedFilter.class); @Override public boolean test(final Session cmsSession, final Channel channel) { try { if (channel.getLocale() == null) { // no specific locale return true; } final HstRequestContext requestContext = RequestContextProvider.get(); if (requestContext == null { // invoked by background thread, no filtering return true; } final HttpSession session = requestContext.getServletRequest().getSession(); final CmsSessionContext cmsSessionContext = CmsSessionContext.getContext(session); final Locale userLocale = cmsSessionContext.getLocale(); if (userLocale.getLanguage().equals(new Locale(channel.getLocale()).getLanguage())) { // matching locale return true; } else { return false; } } catch (Exception e) { log.warn("Exception while trying to check channel content root '{}'. Skip that channel:", channel.getContentRoot(), e); return false; } } }

Step 2: Register the Custom Filter

Add your filter as a Spring bean in a configuration file, for example, custom-channel-filters.xml under

site/components/src/main/resources/META-INF/hst-assembly/overrides

Example Spring configuration:

<!-- Custom channel filters can be added here. --> <bean id="customChannelFilters" class="org.springframework.beans.factory.config.ListFactoryBean"> <property name="sourceList"> <list> <bean id="channelNodeBasedFilter" class="org.example.filter.ChannelLocaleBasedFilter"/> </list> </property> </bean>

Step 3: Accessing HstRequestContext in a Channel Filter

Within a channel filter's test method, you can access the HstRequestContext as follows:

HstRequestContext hstRequestContext = RequestContextProvider.get();

Always check for null before using the hstRequestContext, because channel filters may be invoked by background threads where no request context is available. The hstRequestContext provides access to the CMS request context and the JCR session for the current CMS user.

Share Feedback
Page: /build/experience-pages-channels/channel-filtering
Section: Build
Category *