@@ -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