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}

Last updated