Channel Filtering
Default filtering
HST supports pluggable filtering on the channels that are visible below the [view] button for a document or in the Experience manager for a logged in CMS user. By default, the ContentReadChannelFilter andPrivilegeBasedChannelFilter are always present and are always applied, also seeAccess Channels. It filters out all channels that the current CMS user is not allowed to see in theChannel Manager. For example, if there are three channels with the content roots
/content: /documents: /intranet: /extranet: /management:
and the logged-in CMS user has read access to the content of 'intranet' and 'extranet', then he won't see the Channel that has 'management' as content root in the Experience manager application.
Customize filtering
Channel filtering can be customized by adding extra channel filters to the built in channel filters. To add a custom channel filter you need to:
- Create a filter that implements java.util.function.BiPredicate<Session,Channel>
- Add a Spring bean for your custom filter to customChannelFilters
Built-in Channel Filters
As examples, we show the default ContentReadChannelFilter and PrivilegeBasedChannelFilter since they serve as good examples. The providedSession in the#test method is theSession of the currently logged-in CMS user.
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; } }}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 of adding a custom filter
Assume (contrived example) you want to add a channel filter such that a channel is only shown in the Experience manager application,if the CMS user his locale is the same as the locale of the channel, you can achieve that through the following steps:
Create 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; } }}Add the ChannelLocaleBasedFilter to the customFilters
Below
site/components/src/main/resources/META-INF/hst-assembly/overrides, add the following bean to an XML Spring configuration file (for example tocustom-channel-filters.xml):
<!-- Custom channel filters be added here. --><bean> <property name="sourceList"> <list> <bean/> </list> </property></bean>
Access the HstRequestContext in a Channel Filter
In a Channel Filter#test method you can access theHstRequestContext via
HstRequestContext hstRequestContext = RequestContextProvider.get();
If using it, always make sure to do a null check on thehstRequestContext object since the Channel Filters can also be applied to background threads which do not have anHstRequestContext. ThehstRequestContext is the request context for the CMS request. When getting the JCR Session via the request context, you'll get the JCR Session for the currently logged-in CMS user.