Executando verificação de segurança...
1

Postgre + Row Level Security (problemas com variavel Postgre no AdonisJS)

Estou desenvolvendo uma aplicação em nodejs (Adonis) com Postgre, onde será um multi-tenant compartilhado, ou seja, todas tabelas com uma coluna tenant_id.

Pra uma maior segurança, optei por utilizar o RLS (Row Level Security) do Postgre.

Basicamente, em toda migração eu crio uma política assim:
CREATE POLICY tenant_isolation_policy ON ${table} USING(tenant_id = current_setting('app.tenant_id')::uuid) WITH CHECK(tenant_id = current_setting('app.tenant_id')::uuid)

Tudo está funcionando bem, porém, minha dúvida é na questão de setar a variavel app.tenant_id.
Se eu utilizar um middleware pegando o módulo do Adonis Database, ficaria assim:
await Database.rawQuery(SET app.tenant_id = '${tenant_id}');

E funciona bem, porém, ao ter 2 usuários conectados em contas distintas simultaneamente, parece que eles compartilham essa mesma variável (por conta da pool da database, me aparenta que eles utilizam a mesma instância de conexão do banco ou algo do tipo).

Vocês teriam alguma ideia do que fazer?

Funcionaria se no middleware eu fizesse uma nova conexão ao banco de dados passando no nome da conexão algo relacionando ao tenant, e passasse essa variavel da conexão pra utilizar nos controllers, mas creio que essa seja uma má prática, pq ele já mantinha uma conexão anteriormente.

Agradeço <3

Carregando publicação patrocinada...
1

Dá uma olhada nesse artigo: Multi-tenant data isolation with PostgreSQL Row Level Security
. Durante o exemplo de conexão creio que vai dar uma resposta boa para ti.

Sobre a pergunta, acho que vai ter que usar o middleware para saber quem tá connectando e só depois disso add na sessao da conexao do DB. Ele dá uma dica de usar sessão no banco de dados. Creio que pode trazer pro app para assim que se connectar no controler ele setar o tenant para aquela request completa e depois já morrer essa "sessão"

1

Agradeço muito a sua resposta!

Então, já tinha lido essa documentação, me esclareceu algumas dúvidas, mas no ponto de setar a variavel apenas pra uma conexão não.

Não sei se você já utilizou o Adonis, mas ele utiliza o Knex (https://knexjs.org/guide), então cheguei próximo a esse ponto:

const connectionNode = Database.manager.get('pg');
const pool = connectionNode?.connection?.pool;
pool?.on('acquireSuccess', async function (eventId, resource) {
await resource.query(SET app.tenant_id = '${tenant_id}');
});

A principio ele pega a pool atual e no sucesso seta a variavel, mas mesmo assim acaba setando pra todos.

1

tenta algo assim:

    const connectionConfig = { ...this.getDefaultConfig() };
     connectionConfig.connection.database = database;
     this.config.set(`database.${database}`, connectionConfig);
1