Aidbox
Search
K

Access control lists (ACL)

Access control lists with API constructor
In Aidbox you can configure Access control lists using API Constructor.
aidbox.rest.acl provides a set of operations supporting SQL :filters to be added on each request. :filters can be used to restrict access to resources

Examples

Code examples on this page are taken from the ACL and the multitenancy example projects

Overview

Available aidbox.rest/op-engines

Expects the same as regular FHIR API engines and also a :filter
  • aidbox.rest.acl/search
  • aidbox.rest.acl/create
  • aidbox.rest.acl/read
  • aidbox.rest.acl/update
  • aidbox.rest.acl/conditional-update
  • aidbox.rest.acl/delete
  • aidbox.rest.acl/conditional-delete
  • aidbox.rest.acl/create-with-filter-table-insert — create resource and create entry in filter table
  • aidbox.rest.acl/patient-level-bulk-export
  • aidbox.rest.acl/group-level-bulk-export

Example

search-observation
{:zen/tags #{aidbox.rest/op}
:engine aidbox.rest.acl/search
:resource "Observation"
:format "fhir"
:filter observation-filter}

Filter

An ACL operation requires :filter to be specified. A filter requires to define :expression which will be added to a SQL formed by the operation. :expression is made of templates joined with :and or :or operators. A filter optionally accepts :filter-table

Example

observation-filter
{:zen/tags #{aidbox.rest.acl/filter}
:filter-table acl-box.acl/acl-table
:expression [:and acl-box.acl/user-condition
acl-box.acl/subject-conditon]}

Filter table insert

aidbox.rest.acl/create-with-filter-table-insert engine requires :filter-table-insert property which links operation with the schema tagged with aidbox.rest.acl/filter-table-insert.
insert-into-filter-table schema has the following keys:
  • engine: currently only aidbox.rest.acl/filter-table-insert-row-sql is supported
  • filter-table: zen symbol defining filter table
  • params: sql parameters. See Parameter section.
  • values: values to insert in row. This property value is a map in which keys are column names and values are sql substrings for values.

Example

insert-into-filter-table
{:zen/tags #{aidbox.rest.acl/filter-table-insert}
:engine aidbox.rest.acl/filter-table-insert-row-sql
:filter-table acl-box.acl/acl-table
:params {:user-id acl-box.acl/user-id-param}
:values {:id "gen_random_uuid()"
:txid "nextval('transaction_id_seq'::text)"
:status "'created'"
:resource "jsonb_build_object('patient', jsonb_build_object('resourceType', 'Patient',
'id', {{target-id}}::text),
'user', jsonb_build_object('resourceType', 'User',
'id', {{params.user-id}}::text))"}}

Filter table

Filter table defines SQL table to be joined or searched in with SQL templates.

Example

acl-table
{:zen/tags #{aidbox.rest.acl/filter-table}
:schema "public" ;; Custom resource table acl-box.custom-resources/PatientAccess
:name "patientaccess"}

Template

Defines SQL template string. Accepts params. In the template string you can refer to variables with {{<var>}} syntax. Available variables:
  • params can be referred with {{params.<path>.<to>.<param>}} syntax.
  • {{filter-table}} is the :filter-table added to the filter
  • {{target-resource}} is the jsonb of a resource being checked
  • {{target-id}} is the id of the resource

Example

user-condition
{:zen/tags #{aidbox.rest.acl/sql-template}
:params {:user-id user-id-param}
:template "{{filter-table}}.resource#>>'{user, id}' = {{params.user-id}}"}
subject-conditon
{:zen/tags #{aidbox.rest.acl/sql-template}
:template "{{target-resource}}#>>'{subject, id}' = {{filter-table}}.resource#>>'{patient, id}'"}
id-conditon
{:zen/tags #{aidbox.rest.acl/sql-template}
:template "{{target-id}} = {{filter-table}}.resource#>>'{patient, id}'"}

Parameter

Defines a path in a request where to get data. The data can be used in a SQL template

Example

user-id-param
{:zen/tags #{aidbox.rest.acl/request-param}
:source-schema {:type zen/string}
:path [:user :id]}

Conditional CRUD

By default, aidbox.rest.acl/create, aidbox.rest.acl/conditional-update, aidbox.rest.acl/conditional-delete engines don't make ACL checks on underlying searches. That can lead to "multiple matches" error even when a user doesn't have access to some resources. Such behavior could be overwritten by acl-checks-on-search? parameter.

Example

observation-conditional-delete
{:zen/tags #{aidbox.rest/op}
:engine aidbox.rest.acl/conditional-delete
:resource "Observation"
:format "fhir"
:filter observation-filter
:acl-checks-on-search? true}