@bobr3258

Как лучше делать row level security в Node.JS + SQL СУБД?

Будьте добры, посоветуйте, как оптимальнее всего сделать безопасность на уровне строк в Node.JS + SQL СУБД?

К примеру небольшая ERP система с разными филиалами. Каждый филиал видит накладные и клиентов только по себе.
Менеджер видит только своих клиентов, а руководитель всех. Соответсвенно, все отчеты должны быть ограничены также ролями.

-------------------------------------

Пока нашел, такие варианты:
(если в чем не прав, не судите строго)

На уровне приложения:
1. Добавлять WHERE предикаты к каждому запросу.
Плюсы: все работает быстро и просто. Можно делать сложные SELECT-ы для отчетов
Минусы: сложность в поддержке, если нужно добавить роль или изменить, нужно перелопачивать весь код.

2. ORM Sequilize с scopes в моделях.
Плюсы: простота в поддержке, добавил условие роли в scope и все. Можно перейти на другую СУБД без особых затрат.
Минусы: Проблемно сделать сложный запрос для отчета с join-ом десятка таблиц и агрегированными группировками.
Высокий порог входа для новых программистов не работавших с ним ранее. Возможны проблемы с производительностью.

3. Фильтрация полученных данных на js
Плюсы: все на JS, без сложных запросов к БД.
Минусы: не простая поддержка. Проблемы с производительностью и траффиком. Непросто делать pagination, count total, ...

На уровне СУБД:
4. на уровне View.
Плюсы: простая реализация. Высокая производительность
Минусы: На каждую роль своя вьюха. В приложении нужно определять к какой вьюхе запрос. При миграциях вьюхи нужно изменять. Во всех SELECT-ах нужно ставить переменную вместо имени таблицы.

5. Дергать stored procedurеs
Плюсы: все быстро
Минусы: подход считается устарелым, так уже вроде как немодно. Новые программисты должны изучать язык СУБД.

6. Использовать СУБД со встроенными row level security например Postgres (RLS)
Плюсы: все просто. Включили политики на уровне базы и все.
Минусы: у Sequilize могуть быть проблемы так как, для Postgres, нельзя передать переменную сессии через SET= . Это нужно для определения ролей RLS. Так как у ноды соединения постоянные или в пуле, после каждого запроса нужно её потом обнулять, чтоб другие сессии не получили прав предыдущей. (построитель запросов Knex умеет с SET=) . Либо как в php каждый раз создавать новое соединение и потом его удалять.
  • Вопрос задан
  • 268 просмотров
Решения вопроса 1
@karapet95
Мне думается, Sequilize тяжелый для таких вещей и сложных запросов.

Можете попробовать knex.
В одном месте создаете подзапрос с динамическими where условиями в зависимости от ролей пользователя. Потом в отчетах и других селектах обращаетесь не к таблице, а к ограниченному подзапросу. По такому принципу:
const ClientsSubQuery = knex.select(1).as('clients');
const query = knex.select('*').from(ClientsSubQuery);
console.log(query.toSQL());

Похоже на вьюшки, только без недостатков, все на стороне приложения и более функционально. Например, если пользователь имеет несколько ролей и нужно данные по их всем where-условиям на определенную таблицу.

Определиться нужно ли вам ORM можете глянув это видео:
https://www.youtube.com/watch?v=bkDUIIho70o

Можно и без ORM сделать хорошее приложение.
Если очень хочется, можете использовать Objection.js или Bookshelf.js. Это более понятные ORM (в отличии от Sequilize), основаные на knex и скорее всего совместимые с подходом показанным выше.

P.S.: knex умеет миграции и много чего другого. При желании, как и с ORM, вы свое приложение потом сможете переключить например с MySQL на Postgres или наоборот
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы