Skip to content

Commit cbeb72f

Browse files
committed
fix: adjust RLS config into database controllet
1 parent 1f24229 commit cbeb72f

1 file changed

Lines changed: 21 additions & 19 deletions

File tree

app/controllers/concerns/row_level_security.rb

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,32 @@ module RowLevelSecurity
1010
def with_rls_context
1111
return yield unless current_user && current_organization
1212

13-
begin
14-
# Set PostgreSQL session variables for RLS
15-
# Using a transaction to ensure SET LOCAL works properly
16-
ActiveRecord::Base.connection.execute(
17-
"SET LOCAL app.current_user_id = '#{current_user.id}';"
18-
)
19-
ActiveRecord::Base.connection.execute(
20-
"SET LOCAL app.current_organization_id = '#{current_organization.id}';"
21-
)
22-
ActiveRecord::Base.connection.execute(
23-
"SET LOCAL app.user_role = '#{current_user.role}';"
24-
)
25-
rescue ActiveRecord::StatementInvalid => e
26-
# SET LOCAL might fail outside transactions on some poolers
27-
Rails.logger.warn("RLS SET LOCAL failed: #{e.message}. Using thread-local only.")
28-
end
29-
3013
# Set thread-local variable for application-level scoping
31-
# This is needed because PostgreSQL RLS doesn't apply to table owners (postgres user)
14+
# This is the primary mechanism since RLS might not work with poolers
3215
Thread.current[:current_organization_id] = current_organization.id
3316
Thread.current[:current_user_id] = current_user.id
3417
Thread.current[:current_user_role] = current_user.role
3518

36-
yield
19+
# Try to set PostgreSQL session variables for RLS
20+
# This works in direct connections but may fail with transaction-mode poolers
21+
ActiveRecord::Base.transaction do
22+
begin
23+
ActiveRecord::Base.connection.execute(
24+
"SET LOCAL app.current_user_id = '#{current_user.id}';"
25+
)
26+
ActiveRecord::Base.connection.execute(
27+
"SET LOCAL app.current_organization_id = '#{current_organization.id}';"
28+
)
29+
ActiveRecord::Base.connection.execute(
30+
"SET LOCAL app.user_role = '#{current_user.role}';"
31+
)
32+
rescue ActiveRecord::StatementInvalid => e
33+
# SET LOCAL might fail outside transactions on some poolers
34+
Rails.logger.warn("RLS SET LOCAL failed: #{e.message}. Using thread-local only.")
35+
end
36+
37+
yield
38+
end
3739
ensure
3840
# Reset PostgreSQL variables
3941
begin

0 commit comments

Comments
 (0)