Broadleaf Feature - Catalog Access Policies

Broadleaf's new Catalog Access Policy module was built with the purpose of providing curated B2B user experiences. The Catalog Access Policy allows users to control what parts of the catalog can be seen and who can see it by using Broadleaf's powerful rules-based engine. As one of the principle engineers working on this project, I am very excited to share use cases for this module, and how you could use this feature within your eCommerce website.

Why Catalog Access Policies?

We discovered a demand, mostly in the B2B area of eCommerce, for the ability to control which parts of the catalog are visible for different accounts or users. For instance, we may have an account, X.Y.Z. Corporation, who only wants to purchase t-shirts, but our website contains t-shirts, hot sauces, gift cards, and other types of products. Rather than giving customers for X.Y.Z. Corporation access to the entire catalog, it might be best to only show them products that are t-shirts - decreasing the chances of purchasing the wrong type of product and removing the need to sift through a bunch of inapplicable products. In the past, this functionality required writing many lines of custom code and weeks of development to implement. The good news is, the new Catalog Access Policies capabilities were built with the B2B user in mind.

Now, once the module is installed, all one has to do is create a new policy and tie that policy to an account or segment of customers. It only takes the addition of one policy in order to ensure X.Y.Z. Corporation only sees t-shirts when shopping on our eCommerce website.

How Do I Create a Policy?

We've talked about why you would want a policy, now let's look at our use case we defined above and start digging in on how we can set up a policy to help X.Y.Z. Corporation limit its catalog and improve its user's experience.

We need to start by navigating to the Catalog Access Policy section in the Broadleaf Administrative Interface.

admin-section

Currently we don't have any policies defined, so our next step is to click "Add Catalog Access Policy" and create a new policy.

entity-form

There is an abundance of metadata one can define for a policy such as: name, description, start/end dates, etc. For this example, we are going to give it a name, "X.Y.Z. Corporation Policy", and then set up some rules.

There are two rule-based concepts that make a policy: rules that decide who this policy applies to and then rules that decide what products and categories the user can browse.

Let's start off by defining who our rule applies to. To do this, we want to create a new "Account Rule". I have created a rule that specifies this policy applies to accounts with the name "X.Y.Z. Corporation".

account-rule

Now that we have defined who our policy applies to, let's define some rules that govern which parts of the catalog the user can see. To define access rules, we need to go to the Rules tab.

rules-tab

We have both Product Attribute and Category rules that we can define. Product Attribute rules are based on Custom Fields defined on Products, while Category rules are rules based on Categories. For this example, we are going to define a rule for the "Product Domain" Custom Field in order to only show Products whose "Product Domain" is "T-Shirt".

product-domain-rule

This rule should do pretty well to ensure that we only see t-shirts, but to be safe, we should add a Category rule to include only the Merchandise category, since this is the only category that includes t-shirts.

category-rule

Now, we can save/approve our changes and go check them out on our site. Since this rule is targeting the "X.Y.Z. Corporation", we need to log into one of their accounts. I will log into Bill's account, bill@xyz.com.

example-gif

Bill can now only see the products that are important to his account. The example I gave here is a relatively simple one, but you can make these policies as complicated and verbose as you would like.

How Does This All Work?

The Catalog Access Policy module effects are wide-ranging, it touches search, url mapping, menus, checkout, and even the typeahead. It does this through the use of powerful MVEL expressions that are evaluated to determine whether the customer has access to a piece of the catalog.

One thing I didn't show - if you tried to manually visit a product page when logged into Bill's account, you would be presented with a 404. This is because we evaluate the policy's rules within our url mapping and if we find a certain product is not accessible, we don't allow the user to see the page. If you try to access a category page, you would see the same result. I won't go into the details of exactly how this is done behind the scenes, however, if you wanted to use a policy to lock down a page served by your custom controller, here is an example of how that would work:

// inject our service bean "blCatalogAccessPolicyService"

@Resource(name = "blCatalogAccessPolicyService")
protected CatalogAccessPolicyService policyService;



protected boolean isBlockedByPolicy(Customer customer, Product product) {

	// find the highest priority policy that applies to our customer

	CatalogAccessPolicy policy = policyService.findCatalogAccessPolicyForCustomer(customer);
	
	if (policy != null) {
		return policyService.validateProductForPolicy(policy, product);
	}
	
	return false;
}

The above use case is fairly simple and straightforward, but you may ask, how could it be so simple to apply this to a Solr query in custom search service? We already handle this out-of-box if you are using our SolrSearchService. However, if you wrote your own service or have a custom endpoint that uses Solr for searching products, you can filter your results using code similar to the following segment:

// inject our service bean "blCatalogAccessPolicyService"

@Resource(name = "blCatalogAccessPolicyService")
protected CatalogAccessPolicyService policyService;



protected void attachCatalogAccessFilters(SolrQuery solrQuery, Customer customer) {
	
	// find the highest priority policy that applies to our customer

	CatalogAccessPolicy policy = policyService.findCatalogAccessPolicyForCustomer(customer);
	
	if (policy != null) {
		// generate the filter queries for this policy

		List<String> filterQueries = policyService.createSolrFiltersForPolicy(policy);
		
		if (CollectionUtils.isNotEmpty(filterQueries)) {
		
		    // iterate over each filter query and add it to the SolrQuery

		    for (String filterQuery : filterQueries) {
		        solrQuery.addFilterQuery(filterQuery);
		    }
		}
	}
}

Behind the scenes createSolrFiltersForPolicy takes all of the rules you created and converts their MVEL expressions into the appropriate Solr filters. This allows a developer to very easily inject this functionality into your existing search services.

Final Thoughts

Broadeaf's new Catalog Access Policy module is a powerful tool for B2B eCommerce. I'm excited to see what people do with it and for feedback on how we can expand it further. If you found the concepts in this blog interesting, I am looking to release another blog in the next couple months that explores the power of using MVEL expressions and rule builders to create catered search experiences with Solr.