Learn to configure the <access_control_voter>
element for Pull Reports™ Ad Hoc
report and data service software.
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.
<access_control_voter>
to control column accessThe 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 jakarta.servlet.http.HttpServletRequest;
import com.pullreports.model.AccessControlVoter;
public class AdminAccessControlVoter implements AccessControlVoter{
@Override
public boolean vote(HttpServletRequest request) {
return request.isUserInRole("ADMIN");
}
}
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 Reports™ 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.7.0" id="employee" name="Employee Reports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.pullreports.com/catalog-1.7.0 https://www.pullreports.com/docs/xsd/pullreports-catalog-1.7.0.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>
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 jakarta.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");
}
}
<access_control_voter>
to control report accessBuilding from the previous example, the following AccessControlVoter
limits access to users with the USER
or ADMIN
role.
package com.pullreports.examples.accesscontrol;
import jakarta.servlet.http.HttpServletRequest;
public class AdminOrUserAccessControlVoter extends AdminAccessControlVoter {
@Override
public boolean vote(HttpServletRequest request) {
return request.isUserInRole("USER") || super.vote(request);
}
}
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.7.0" id="employee" name="Employee Reports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.pullreports.com/catalog-1.7.0 https://www.pullreports.com/docs/xsd/pullreports-catalog-1.7.0.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>
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 jakarta.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);
}
}
<access_control_voter>
to control relationship accessThe 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 jakarta.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);
}
}
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.7.0" id="employee" name="Employee Reports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.pullreports.com/catalog-1.7.0 https://www.pullreports.com/docs/xsd/pullreports-catalog-1.7.0.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>
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));
}
}
<canned_query> |
<catalog> |
<column> |
<relationship> |
<report> |
Fully qualified name of a Java class which implements AccessControlVoter. The class must have a public, no argument constructor.