<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 ReportsReport 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.6.1" id="employee" name="Employee Reports"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.pullreports.com/catalog-1.6.1
    https://www.pullreports.com/docs/xsd/pullreports-catalog-1.6.1.xsd">
    <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 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.ReportConfiguration;
import com.pullreports.model.config.TableConfiguration;

import javax.servlet.ServletContext;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class AccessControlVoterColumnExampleCatalogConfigurationFactory 
implements CatalogConfigurationFactory {

    @Override
    public CatalogConfiguration makeCatalog(ServletContext servletContext) {

        ReportConfiguration.Builder employeeReportBuilder = makeEmployeeReportConfigurationBuilder();
        
        List<ReportConfiguration> reportConfigurations =
                Collections.singletonList(employeeReportBuilder.build());

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

    protected ReportConfiguration.Builder makeEmployeeReportConfigurationBuilder(){

        TableConfiguration.Builder employeeTableBuilder = makeEmployeeTableConfigurationBuilder();

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

    protected TableConfiguration.Builder makeEmployeeTableConfigurationBuilder(){

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

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

        return new TableConfiguration.Builder(
                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.6.1" id="employee" name="Employee Reports"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.pullreports.com/catalog-1.6.1
    https://www.pullreports.com/docs/xsd/pullreports-catalog-1.6.1.xsd">
    <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 com.pullreports.model.CatalogId;
import com.pullreports.model.config.CatalogConfiguration;
import com.pullreports.model.config.ReportConfiguration;

import javax.servlet.ServletContext;
import java.util.Collections;
import java.util.List;

public class AccessControlVoterReportExampleCatalogConfigurationFactory 
extends AccessControlVoterColumnExampleCatalogConfigurationFactory {

    @Override
    public CatalogConfiguration makeCatalog(ServletContext servletContext) {

        ReportConfiguration.Builder employeeReportBuilder = makeEmployeeReportConfigurationBuilder();
        employeeReportBuilder.setAccessControlVoter(new AdminOrUserAccessControlVoter());
        
        List<ReportConfiguration> reportConfigurations =
                Collections.singletonList(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.6.1" id="employee" name="Employee Reports"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.pullreports.com/catalog-1.6.1
    https://www.pullreports.com/docs/xsd/pullreports-catalog-1.6.1.xsd">
    <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.JoinColumnsRelationshipConfiguration;
import com.pullreports.model.config.RelationshipConfiguration;
import com.pullreports.model.config.TableConfiguration;

import java.util.Arrays;
import java.util.Collections;

public class AccessControlVoterRelationshipExampleCatalogConfigurationFactory 
extends AccessControlVoterReportExampleCatalogConfigurationFactory {

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

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

        TableConfiguration benefitsSelections = new TableConfiguration.Builder(
            new TableId("benefits_selections"),"Benefits Selections"
            ,Arrays.asList(healthColumnConfiguration,dentalColumnConfiguration))
            .setName("company.benefits_selections").build();

        RelationshipConfiguration benefitsSelectionsRelationship = 
            new JoinColumnsRelationshipConfiguration.Builder(
            benefitsSelections, Collections.singletonList(new JoinColumn("employee_name","name")))
            .setCardinality(Cardinality.ONE)
            .setAccessControlVoter(new AdminDateAccessControlVoter()).build();

        return super.makeEmployeeTableConfigurationBuilder()
            .setRelationshipConfigurations(Collections.singletonList(benefitsSelectionsRelationship));
    }
}
                

Parents

<canned_query>
<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.