Prisma с политиками Supabase RLS
Для недавней задачи мне пришлось настроить Prisma для учета политик RLS (безопасность на уровне строк), настроенных в Supabase. Этого, как вы знаете, трудно достичь, так как по умолчанию Prisma открывает прямое соединение с базой данных, и это также с пользователем postgres
, у которого есть разрешения на обход любой политики RLS.
Это краткое описание того, как я решил эту проблему и заставил Prisma работать с политиками RLS, настроенными в Supabase.
Беремся за роль
Первым шагом было убедиться, что Prisma не подключается к базе данных как пользователь postgres
. Для этого я настроил новую роль, которая будет иметь LOGIN
разрешений (чтобы позволить Prisma использовать эти учетные данные) и пароль.
CREATE ROLE myprismauser LOGIN PASSWORD 'testPWD1'
Как только это было сделано, я обновил URL-адрес базы данных, который использует Prisma, добавив эти данные.
DATABASE_URL=postgresql://myprismauser:testPWD1@db.mydbstr.supabase.co:5432/postgres
Когда я проверил это с помощью простого npx prisma db pull
, я получил ответ о том, что в базе данных нет таблиц. Это произошло потому, что к роли нужно было добавить дополнительные разрешения. (Обратитесь к этой проблеме Github — https://github.com/prisma/prisma/issues/3041)
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public to myprismauser; GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public to myprismauser; GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public to myprismauser;
Вот и все, роль настроена и готова к использованию.
Здесь важно отметить, что я не использую схему Supabase
auth
для управления политикой. Вместо этого я буду использовать пользовательские переменные для управления доступом, поэтому, если вы ищете способ связать Supabase Auth с Prisma, эта статья не для вас. (Я скоро напишу еще один о том, как это сделать, короче говоря, просто установитеcurrent_user_id
на идентификатор Supabase вошедшего пользователя)
Политика RLS
Теперь, что касается фактической политики RLS, я настроил тестовую таблицу test_rls
, на которой я установил новую политику для управления SELECT
.
Эта политика возвращает все строки, в которых переменная app.current_role
равна столбцу role
в таблице test_rls
.
Реализация Призмы
С этой настройкой мне теперь нужно было настроить Prisma для установки этой переменной перед запросом. Я нашел это решение в очень полезной ветке — https://github.com/prisma/prisma/issues/5128, пожалуйста, обязательно прочитайте ее полностью, так как она дает хорошее представление о том, как работает это решение, и о любых потенциальных возможностях. недостатки и др.
Я использую фреймворк Serverless для настройки Graphql API, который использует Prisma для управления доступом к данным. Я не буду вдаваться в подробности о том, как устанавливается свойство userRole
, так как это будет зависеть от логики вашего собственного приложения. Кроме того, как указано в приведенной выше проблеме с Git, это должно быть перемещено в промежуточное программное обеспечение, но я показываю преобразователь здесь только для того, чтобы показать, как его можно использовать.
getTestRLSData: async ({ prisma, userRole = "" }) => { const resp = await prisma.$transaction([ prisma.$executeRawUnsafe(`SET app.current_role = ${userRole}`), prisma.test_rls.findMany(), ]); return resp; },
Причина, по которой я использовал executeRawUnsafe
вместо executeRaw
, заключалась в том, что при его использовании я получал ошибку. executeRawUnsafe
, как следует из названия, небезопасно использовать, так как оно открывает приложение для атак SQL-инъекций. Будьте предельно осторожны при использовании этого и, если возможно, избегайте его вообще. Подробнее о его использовании читайте здесь — https://www.prisma.io/docs/concepts/components/prisma-client/raw-database-access#executerawunsafe
Приведенный выше преобразователь теперь позволяет мне выбирать строки на основе роли пользователя.
Если у вас есть какие-либо мысли о том, как улучшить эту настройку, или вы видите какие-либо потенциальные недостатки, не стесняйтесь оставлять комментарии. Я хотел бы услышать ваши мысли по этому поводу.