Support and Documentation

Deploying Access

Developers perform this task.

Overview of deploying Access

When you deploy the Access plugin, Brightspot reviews every request for content as indicated in the following diagram.

Access request flow
Figure 97. Access request flow

Referring to the previous diagram, Brightspot reviews every request as follows:

  • If the content is not restricted, retrieve and send it to the client.

  • If the content is restricted:

    1. Brightspot checks if the user associated with the request has the required credentials.

    2. If so, Brightspot retrieves the content and returns it to the client.

    3. If not, Brightspot returns substitute content (such as a pay wall) to the client.


Brightspot checks for access control at the content type requested by a client, and does not check access control at lower levels. If a client requests a parent item that is unrestricted, and that item contains a child item that is restricted, the client receives the restricted child item.

Create a form for assigning access control

In a typical scenario, administrators use a form in Brightspot to assign access control to various content types as described in Configuring content substitutions. You provide that form by declaring a class that implements the interface Access.

package access;

import com.psddev.access.Access;
import com.psddev.cms.db.Content;
import com.psddev.cms.db.ToolUi;
import com.psddev.dari.db.CompoundPredicate;
import com.psddev.dari.db.ObjectType;
import com.psddev.dari.db.Predicate;
import com.psddev.dari.db.PredicateParser;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class ContentAccess extends Content implements Access {

    private String accessLabel;

    @Where("groups = content.article.Article OR groups =")
    private Set<ObjectType> contentTypes;

    public Set<ObjectType> getTypes() {
        if (contentTypes == null) {
            contentTypes = new HashSet<>();
        return contentTypes;

    public Predicate itemsPredicate() {
        List<Predicate> predicateList = new ArrayList<>();

        if (!getTypes().isEmpty()) {
            predicateList.add(PredicateParser.Static.parse("_type = ?", getTypes()));

        return new CompoundPredicate(PredicateParser.AND_OPERATOR, predicateList);

In the previous snippet—

  • Line 16 declares this class implements the interface Access, which requires overriding the method itemsPredicate.

  • Line 18 provides a label for the access control rule that appears in Brightspot.

  • Line 21 uses the annotation @Where to determine which content types an administrator can select for access control. (For more information about this annotation, see @Recordable.Where.) If the content types listed in this annotation contain child content types that also require access control, include those child content types as well.

  • Line 22 displays a list containing the items satisfying the @Where annotation.

  • Lines 32–41 implement the method itemsPredicate, returning a list of conditions that indicate access control. At run time, Brightspot accumulates the conditions of all implemented itemsPredicate methods, and determines if the request satisfies one of those conditions. If so, the request is under access control, and Brightspot checks the visitor's credentials accordingly. (See the illustration Access request flow.)

The following illustration is an example of a class implementing Access in the content edit form.

Checking for access to requested content

Checking for access requires two steps:

  • Find the accesses assigned to the requested resource that were established by implementing Access as described in Create a form for assigning access control. This step is implementation dependent, and usually involves determining the content type requested from the incoming query string and then checking if the content type is under access control.

  • Determine if the user associated with the request has the required access. This step is also very much implementation dependent: some Brightspot projects have an API to the publisher's subscription system, and other projects have internal subscription tables.

For an overview of this process, see the diagram Access request flow.

You perform both of these steps by declaring a class that implements the interface AccessProvider.

package access;

import com.psddev.access.Access;
import com.psddev.access.AccessProvider;
import com.psddev.cms.db.PageFilter;
import com.psddev.cms.db.Site;
import com.psddev.dari.db.Predicate;
import com.psddev.dari.db.PredicateParser;

import javax.servlet.http.HttpServletRequest;

public class ContentAccessProvider implements AccessProvider {

    public boolean requiresAccess(HttpServletRequest request) {
        Site site = PageFilter.Static.getSite(request);
        Object mainObject = PageFilter.Static.getMainObject(request);

        if (mainObject == null) {
            return false;

        List<SubscriptionPlan> plans = site.getSubscriptionPlans();

        for (SubscriptionPlan plan : plans) {
            Set<Access> accesses = plan.getAccesses();

            for (Access access : accesses) {
                Predicate predicate = access.itemsPredicate();
                if (PredicateParser.Static.evaluate(mainObject, predicate)) {
                    return true;
        return false;

    public Collection<? extends Access> findAccesses(HttpServletRequest request) {
        Set<Access> accesses = new HashSet<>();

        ExampleUser user = ExampleAuthFilter.getUser(request);

        if (user != null) {
            for (ExampleSubscription subscription : user.getSubscriptions()) {

        return accesses;

In the previous snippet—

  • Line 12 indicates this class implements AccessProvider, so Brightspot runs this class each time a request arrives for content.

  • Lines 14–36 override the method requiresAccess and return a boolean true if the requested content type is under access control, false otherwise. The code within this method is usually implementation dependent. The following list describes a basic implementation.

    • Lines 16–17 extract the site and content type associated with the incoming request.

    • Line 19–21 is a null check that returns false if there is no content type associated with the request.

    • Line 23 retrieves all the subscription plans associated with the site.

    • Lines 25–34 examine each of the retrieved subscription plans. If any of them contain the requested content type, return true.

    • Line 35 returns false if the requested content type is not included in any subscription plan. As a result, Brightspot retrieves the requested content to the client.

  • Lines 38–51 override the method findAccesses and return a HashSet<Access> containing a set of accesses associated with the user who sent the request. Brightspot runs this method if requiresAccess returns true.

    • Line 42 retrieves the user associated with the incoming request.

    • Lines 45–47 retrieve all of the subscriptions associated with the user.

Brightspot denies access to an item when requiresAccess returns true and one of the following is also true:

  • findAccesses returns an empty set of accesses.

  • findAccesses returns a non-empty set of accesses, none of which match those associated with the requested content.