Access control lists (ACL)
In Aidbox you can configure Access control lists using API constructor (beta).
aidbox.rest.acl
provides a set of operations supporting SQL :filter
s 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-engine
s
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/conditionalupdate
aidbox.rest.acl/delete
aidbox.rest.acl/conditionaldelete
aidbox.rest.acl/createwithfiltertableinsert
— create resource and create entry in filter tableaidbox.rest.acl/patientlevelbulkexport
aidbox.rest.acl/grouplevelbulkexport
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 onlyaidbox.rest.acl/filtertableinsertrowsql
is supportedfiltertable
: zen symbol defining filter tableparams
: sql parameters. See Access control lists (ACL).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 {{}}
syntax. Available variables:
params
can be referred with{{params.
syntax.. .}} {{filtertable}}
is the:filtertable
added to thefilter
{{targetresource}}
is the jsonb of a resource being checked{{targetid}}
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}