question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Support for Postgres' SET command in raw mode/PG RLS policies in general

See original GitHub issue

Problem

I’m looking to use prisma for an api I’m working on that has certain security requirements. We have a shared database and schema for the application, so we use pg’s Row Level Security policies to limit row access based on a run-time variable.

I discovered that the SET command isn’t supported by prisma’s executeRaw option. For example:

await ctx.prisma.$executeRaw`SET jwt.claims.user_id = ${ctx.currentUser.userId}`;

Yields this error:

 "message": "\nInvalid `prisma.executeRaw()` invocation:\n\n\n  Raw query failed. Code: `42601`. Message: `db error: ERROR: syntax error at or near \"$1\"`",

Running the command without any variables works fine:

await ctx.prisma.$executeRaw`SET jwt.claims.user_id = 1`;

We are using @prisma/client and @prisma/cli version 2.8.0.

Suggested solution

Allow executeRaw to run the SET command.

Alternatives

An alternative solution, which I think is actually better but would likely require more work (?), would be to allow the client to apply configuration options to the database directly. OR, provide a hook after a connection is established to set a runtime variable. This would also address unreliable variables that may occur across multiple connections used by our resolvers.

Here is an example from knex. Here is one from postgraphile, which exposes pg_settings and is executed on each request.

In the meantime, I’d love to hear any suggestions on how others have solved this. Thanks for your consideration.

Additional context

Sample RLS policy

CREATE POLICY user_select_policy
  ON tags
  FOR SELECT
  USING (
    user_id = current_setting('jwt.claims.user_id')::BIGINT
  );

Basic model

model Tag {
  id                      Int              @default(autoincrement())
  name               String
  userId              Int              @map("user_id")
  createdAt        DateTime  @default(now()) @map("created_at")
  taggings         Tagging[]

  @@id([id, userId])
  @@unique([name, userId], name: "name_and_user")
  @@map("tags")
}

The relation table, taggings, also has a user id contraint and an identical security policy.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:5
  • Comments:8 (3 by maintainers)

github_iconTop GitHub Comments

8reactions
crubiercommented, Jan 8, 2021

Being able to SET things per query is very important to use Postgres RLS, which are the best way to have complex authorization rules. This is a must have for my use case (B2B / Enterprise Saas)

2reactions
webdebcommented, May 26, 2022

Sorry, just to add my two cents. this sounds like a feature request

// For example we could define how the session variable is structured

session Object {
  userId Int
  role String?
}

model Thing {
  name String
  secret String?
  vote Int

  @rowSecurity(insert, [session.role = admin or session.userId = userId], "Sorry, you are not authorised")
  @rowSecurity(update, [session.role = editor], [name], "Sorry, you are not authorised")
  @rowSecurity(read, true, [name, vote])
}

For sure there are more scenarios, need to look in details, but is this something the prisma team is interested about?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Documentation: 15: 5.8. Row Security Policies - PostgreSQL
To enable and disable row security for a given table, use the ALTER TABLE command. Each policy has a name and multiple policies...
Read more >
Row-Level Security - SQL Server | Microsoft Learn
Learn how Row-Level Security uses group membership or execution context to control access to rows in a database table in SQL Server.
Read more >
How to Secure PostgreSQL: Security Hardening Best ... - EDB
This article is intended as a comprehensive overview that will help you examine the security of your Postgres deployment from end to end....
Read more >
CREATE EXTERNAL SCHEMA - Amazon Redshift
The schema_name indicates the schema in a supported PostgreSQL database engine ... and authorization to the data catalog by setting either of the...
Read more >
Redwood and Supabase Auth Example - Contributing
I happened to run across this discussion yesterday asking for ' Support for Postgres' SET command in raw mode/PG RLS policies in general`....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found