Skip to content

Latest commit

 

History

History
174 lines (144 loc) · 6.82 KB

POSTGRES.md

File metadata and controls

174 lines (144 loc) · 6.82 KB

Database Overview

Here is the database service definition from docker-compose.yml:

  db:
    <<: *defaults
    image: postgres:15.3-alpine3.17
    ports:
      - '5432:5432'
    volumes:
      - tenancy_example_db_data:/var/lib/postgresql/data
      - type: bind
        source: ./db
        target: /docker-entrypoint-initdb.d
    environment:
      POSTGRES_PASSWORD: 07f019e661d8ca48c47bdffd255b12fe

The bind mount maps the db directory on the host to the docker entrypoint directory.

The two SQL files in ./db (1_schema.sql and 2_data.sql) are executed when the container is created, creating the schema and populating it with test data.

The tables:
create table if not exists public.tenants
(
    id bigserial primary key,
    display_name varchar,
    is_admin boolean default false
);

create table if not exists public.users
(
    id bigserial primary key,
    tenant_id bigint
        constraint users_tenants_id_fk
            references public.tenants
            on delete cascade,
    user_name varchar,
    password varchar
);

create table if not exists public.patients
(
    id bigserial primary key,
    tenant_id bigint
        constraint patients_tenants_id_fk
            references public.tenants
            on delete cascade,
    first_name varchar,
    last_name varchar,
    dob date
);

RLS function:

create or replace function fn.tenant_data_rls_check(row_tenant_id bigint) returns boolean
    language plpgsql
as
$$
BEGIN

IF current_setting('tenancy.bypass')::text = '1' THEN
    return true;
end if;

IF current_setting('tenancy.tenant_id')::integer = row_tenant_id THEN
    return true;
end if;

return false;
END;
$$;

tenant_data_rls_check takes a single argument, the value of 'tenant_id' (or 'id' for the tenants table) for the queried/mutated row.

Looking at the function body, you'll see that first it checks if the session value 'tenancy.bypass' is equal to '1', and if so it returns true, allowing the operation.

Next, it compares the session value 'tenancy.tenant_id' with the tenant_id value for the row. If equal, it allows the operation, otherwise the operation fails.

Policies:
create policy tenancy_policy on public.tenants
    as permissive
    for all
    using (fn.tenant_data_rls_check(id) = true)
    with check (fn.tenant_data_rls_check(id) = true);

create policy tenancy_policy on public.users
    as permissive
    for all
    using (fn.tenant_data_rls_check(tenant_id) = true)
    with check (fn.tenant_data_rls_check(tenant_id) = true);

create policy tenancy_policy on public.patients
    as permissive
    for all
    using (fn.tenant_data_rls_check(tenant_id) = true)
    with check (fn.tenant_data_rls_check(tenant_id) = true);

Note that 1_schema.sql enables these policies at the end of the script, so you don't need to do that yourself.

This SQL file populates the database with the following test data:

Tenants Test Data

iddisplay_nameis_admin
1user tenant 1false
2user tenant 2false
3user tenant 3false
4user tenant 4false
5user tenant 5false
6admin tenanttrue

Users Test Data

idtenant_iduser_namepassword
11t1 user1$2b$10$gra37ECOljK.6udDxfwAOOTSyeQSbo9I0zS6l6NoMR1mbE.9T.jF2
21t1 user2$2b$10$gra37ECOljK.6udDxfwAOOTSyeQSbo9I0zS6l6NoMR1mbE.9T.jF2
32t2 user1$2b$10$gra37ECOljK.6udDxfwAOOTSyeQSbo9I0zS6l6NoMR1mbE.9T.jF2
42t2 user2$2b$10$gra37ECOljK.6udDxfwAOOTSyeQSbo9I0zS6l6NoMR1mbE.9T.jF2
53t3 user1$2b$10$gra37ECOljK.6udDxfwAOOTSyeQSbo9I0zS6l6NoMR1mbE.9T.jF2
63t3 user2$2b$10$gra37ECOljK.6udDxfwAOOTSyeQSbo9I0zS6l6NoMR1mbE.9T.jF2
74t4 user1$2b$10$gra37ECOljK.6udDxfwAOOTSyeQSbo9I0zS6l6NoMR1mbE.9T.jF2
84t4 user2$2b$10$gra37ECOljK.6udDxfwAOOTSyeQSbo9I0zS6l6NoMR1mbE.9T.jF2
95t5 user1$2b$10$gra37ECOljK.6udDxfwAOOTSyeQSbo9I0zS6l6NoMR1mbE.9T.jF2
105t5 user2$2b$10$gra37ECOljK.6udDxfwAOOTSyeQSbo9I0zS6l6NoMR1mbE.9T.jF2
116t6 admin$2b$10$YJ3paQsDvg7ykcUEB6kmQetsGcaRfPzTwvpOEQSc565epW.P82lMO

Patients Test Data

idtenant_idfirst_namelast_namedob
11JohnDoe1984-02-11
21JimDoe1984-02-11
31BobDoe1992-05-13
41JerryDoe1984-02-11
51FranDoe1984-02-11
62JohnDoe1992-05-13
72JamesDoe1984-02-11
82JoshDoe1984-02-11
92HarryDoe1984-02-11
102MaryDoe1992-05-13
113JohnDoe1984-02-11
123JeoffreyDoe1984-02-11
133MaxDoe1984-02-11
143MinDoe1992-05-13
153PatroniusDoe1984-02-11
164JohnDoe1992-05-13
174JaneDoe1992-05-13
184HomerDoe1992-05-13
194MaggieDoe1992-05-13
204BartDoe1992-05-13
215JohnDoe1984-02-11
225WalkerDoe1992-05-13
235YeezyDoe1984-02-11
245Puff DaddyDoe1984-02-11
255The RockDoe1992-05-13