<access_control_voter>

Abstract

Learn to configure the <access_control_voter> element for Pull Reports™ Ad Hoc report and data service software.


Table of Contents

Catalog Configuration Java API reference:  AccessControlVoter

The <access_control_voter> element specifies the fully qualified name of a Java AccessControlVoter to control access to the parent element.

Usage

Using <access_control_voter> to control column access

The following AccessControlVoter permits access if the user has the ADMIN role. The fulfillment of the isUserInRole method is not a feature of Pull Reports™, and must be provided by the installation WAR or Servlet Container.

package com.pullreports.examples.accesscontrol;

import javax.servlet.http.HttpServletRequest;
import com.pullreports.model.AccessControlVoter;

public class AdminAccessControlVoter implements AccessControlVoter{

    @Override
    public boolean vote(HttpServletRequest request) {
        return request.isUserInRole("ADMIN");
    }
}
Example 1. Via an XML Catalog file

The following XML Catalog file applies the AdminAccessControlVoter to the salary <column>. Only users with the ADMIN role will see the salary column within the Pull ReportsAd Hoc Report Creator and be able to include the salary column in report exports. Users without the ADMIN role will receive a 403, FORBIDDEN HTTP response when requesting the salary column via the Pull Reports REST API.

<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="http://www.pullreports.com/catalog-1.5.0" id="employee" name="Employee Reports">
    <report id="employee" name="Employees">
        <table id="employee" name='company.employee' displayName="Employee"> 
            <column id="name" name="employee_name" displayName="Employee Name"/>
            <column id="salary" name="salary" displayName="Salary" paramType="java.lang.Double">
                <access_control_voter voter="com.pullreports.examples.accesscontrol.AdminAccessControlVoter"/>
            </column>
        </table>
    </report>
</catalog>
                

Example 2. Via the Catalog Configuration Java API

The following example is an identical Catalog Configuration Java API configuration.

package com.pullreports.examples.accesscontrol;

import java.util.List;

import javax.servlet.ServletContext;

import com.pullreports.model.CatalogId;
import com.pullreports.model.ColumnId;
import com.pullreports.model.ParamType;
import com.pullreports.model.ReportId;
import com.pullreports.model.TableId;
import com.pullreports.model.config.CatalogConfiguration;
import com.pullreports.model.config.CatalogConfigurationFactory;
import com.pullreports.model.config.ColumnConfiguration;
import com.pullreports.model.config.ColumnConfiguration.ColumnConfigurationBuilder;
import com.pullreports.model.config.ReportConfiguration;
import com.pullreports.model.config.ReportConfiguration.ReportConfigurationBuilder;
import com.pullreports.model.config.TableConfiguration.TableConfigurationBuilder;
import java.util.Arrays;

public class AccessControlVoterColumnExampleCatalogConfigurationFactory 
implements CatalogConfigurationFactory {

    @Override
    public CatalogConfiguration makeCatalog(ServletContext servletContext) {

        ReportConfigurationBuilder employeeReportBuilder = makeEmployeeReportConfigurationBuilder();
        
        List<ReportConfiguration> reportConfigurations = 
                Arrays.asList(new ReportConfiguration[]{employeeReportBuilder.build()});

        return new CatalogConfiguration(new CatalogId("employee"),"Employee",reportConfigurations);
    }

    protected ReportConfigurationBuilder makeEmployeeReportConfigurationBuilder(){

        TableConfigurationBuilder employeeTableBuilder = makeEmployeeTableConfigurationBuilder();

        return new ReportConfigurationBuilder(
            new ReportId("employee"),"Employee",employeeTableBuilder.build());
    }

    protected TableConfigurationBuilder makeEmployeeTableConfigurationBuilder(){

        ColumnConfigurationBuilder nameColumnBuilder = new ColumnConfigurationBuilder(
            new ColumnId("name"),"employee_name")
            .setDisplayName("Employee Name");

        ColumnConfigurationBuilder salaryColumnBuilder = new ColumnConfigurationBuilder(
            new ColumnId("salary"),"salary")
            .setDisplayName("Salary")
            .setParamType(ParamType.DOUBLE)
            .setAccessControlVoter(new AdminAccessControlVoter());
        
        List<ColumnConfiguration> columnConfigurations = Arrays.asList(
            new ColumnConfiguration[]{
                nameColumnBuilder.build(),salaryColumnBuilder.build()
        });

        return new TableConfigurationBuilder(
                new TableId("employee"),"Employee",columnConfigurations)
                .setName("company.employee");
    }
}
                

Using <access_control_voter> to control report access

Building from the previous example, the following AccessControlVoter limits access to users with the USER or ADMIN role.

package com.pullreports.examples.accesscontrol;

import javax.servlet.http.HttpServletRequest;

public class AdminOrUserAccessControlVoter extends AdminAccessControlVoter {

    @Override
    public boolean vote(HttpServletRequest request) {
        return request.isUserInRole("USER") || super.vote(request);
    }
}
Example 3. Via an XML Catalog file

Apply the AdminOrUserAccessControlVoter to the employee <report> with an <access_control_voter> nested within the <report> element. Now the employee report will only be available to users with the ADMIN or USER role, but only users with the ADMIN role may access the salary column.

<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="http://www.pullreports.com/catalog-1.5.0" id="employee" name="Employee Reports">
    <report id="employee" name="Employees">
        <access_control_voter voter="com.pullreports.examples.accesscontrol.AdminOrUserAccessControlVoter"/>
        <table id="employee" name='company.employee' displayName="Employee"> 
            <column id="name" name="employee_name" displayName="Employee Name"/>
            <column id="salary" name="salary" displayName="Salary" paramType="java.lang.Double">
                <access_control_voter voter="com.pullreports.examples.accesscontrol.AdminAccessControlVoter"/>
            </column>
        </table>
    </report>
</catalog>

Example 4. Via the Catalog Configuration Java API

The following example is an identical Catalog Configuration Java API configuration.

package com.pullreports.examples.accesscontrol;

import java.util.List;

import javax.servlet.ServletContext;

import com.pullreports.model.CatalogId;
import com.pullreports.model.config.CatalogConfiguration;
import com.pullreports.model.config.ReportConfiguration;
import com.pullreports.model.config.ReportConfiguration.ReportConfigurationBuilder;
import java.util.Arrays;

public class AccessControlVoterReportExampleCatalogConfigurationFactory 
extends AccessControlVoterColumnExampleCatalogConfigurationFactory {

    @Override
    public CatalogConfiguration makeCatalog(ServletContext servletContext) {

        ReportConfigurationBuilder employeeReportBuilder = makeEmployeeReportConfigurationBuilder();
        employeeReportBuilder.setAccessControlVoter(new AdminOrUserAccessControlVoter());
        
        List<ReportConfiguration> reportConfigurations = 
                Arrays.asList(new ReportConfiguration[]{employeeReportBuilder.build()});

        return new CatalogConfiguration(new CatalogId("employee"),"Employee",reportConfigurations);
    }
}
                

Using <access_control_voter> to control relationship access

The following AccessControlVoter limits access to users with the ADMIN role within the month of October.

package com.pullreports.examples.accesscontrol;

import java.time.LocalDate;
import java.time.Month;
import java.time.ZoneId;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;

public class AdminDateAccessControlVoter extends AdminAccessControlVoter {

    @Override
    public boolean vote(HttpServletRequest request) {

        Date date = new Date();
        LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        Month month = localDate.getMonth();

        return Month.OCTOBER.equals(month) && super.vote(request);
    }
}
Example 5. Via an XML Catalog file

Use the AdminDateAccessControlVoter to control access to the benefits_selections <relationship> by nesting an <access_control_voter> within a <relationship> element. The <relationship> will be available within the Pull Reports REST API if the user has the ADMIN role and the API request is in October.

<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="http://www.pullreports.com/catalog-1.5.0" id="employee" name="Employee Reports">
    <report id="employee" name="Employees">
        <access_control_voter voter="com.pullreports.examples.accesscontrol.AdminOrUserAccessControlVoter"/>
        <table id="employee" name='company.employee' displayName="Employee"> 
            <column id="name" name="employee_name" displayName="Employee Name"/>
            <column id="salary" name="salary" displayName="Salary" paramType="java.lang.Double">
                <access_control_voter voter="com.pullreports.examples.accesscontrol.AdminAccessControlVoter"/>
            </column>
            <relationship cardinality="one">
                <access_control_voter voter="com.pullreports.examples.accesscontrol.AdminDateAccessControlVoter"/>
                <join_column columnName="employee_name" referencedColumnName="name"/>
                <table id="benefits_selections" displayName="Benefits Selections" name="company.benefits_selections">
                    <column id="health_care_coverage" name="health" displayName="Health Care Coverage Level"/>
                    <column id="dental_care_coverage" name="dental" displayName="Dental Care Coverage Level"/>
                </table>
            </relationship>
        </table>
    </report>
</catalog>

Example 6. Via the Catalog Configuration Java API

The following example is an identical Catalog Configuration Java API configuration.

package com.pullreports.examples.accesscontrol;

import com.pullreports.model.Cardinality;
import com.pullreports.model.ColumnId;
import com.pullreports.model.JoinColumn;
import com.pullreports.model.TableId;
import com.pullreports.model.config.ColumnConfiguration;
import com.pullreports.model.config.ColumnConfiguration.ColumnConfigurationBuilder;
import java.util.Arrays;

import com.pullreports.model.config.JoinColumnsRelationshipConfiguration.JoinColumnsRelationshipConfigurationBuilder;
import com.pullreports.model.config.RelationshipConfiguration;
import com.pullreports.model.config.TableConfiguration;
import com.pullreports.model.config.TableConfiguration.TableConfigurationBuilder;

public class AccessControlVoterRelationshipExampleCatalogConfigurationFactory 
extends AccessControlVoterReportExampleCatalogConfigurationFactory {

    @Override
    protected TableConfigurationBuilder makeEmployeeTableConfigurationBuilder(){
        ColumnConfiguration healthColumnConfiguration = new ColumnConfigurationBuilder(
            new ColumnId("health_care_coverage"),"health")
            .setDisplayName("Health Care Coverage Level").build();

        ColumnConfiguration dentalColumnConfiguration = new ColumnConfigurationBuilder(
            new ColumnId("dental_care_coverage"),"dental")
            .setDisplayName("Dental Care Coverage Level").build();

        TableConfiguration benefitsSelections = new TableConfigurationBuilder(
            new TableId("benefits_selections"),"Benefits Selections"
            ,Arrays.asList(new ColumnConfiguration[]{healthColumnConfiguration,dentalColumnConfiguration}))
            .setName("company.benefits_selections").build();

        RelationshipConfiguration benefitsSelectionsRelationship = 
            new JoinColumnsRelationshipConfigurationBuilder(
            benefitsSelections,Arrays.asList(new JoinColumn[]{new JoinColumn("employee_name","name")}))
            .setCardinality(Cardinality.ONE)
            .setAccessControlVoter(new AdminDateAccessControlVoter()).build();

        return super.makeEmployeeTableConfigurationBuilder()
            .setRelationshipConfigurations(Arrays.asList(new RelationshipConfiguration[]{benefitsSelectionsRelationship}));
    }
}
                

Parents

<catalog>
<column>
<relationship>
<report>

Attributes

voter

Fully qualified name of a Java class which implements AccessControlVoter. The class must have a public, no argument constructor.