Module: RlsMultiTenant::RlsHelper
- Defined in:
- lib/rls_multi_tenant/rls_helper.rb
Constant Summary collapse
- IDENTIFIER_PATTERN =
PostgreSQL unquoted identifier: starts with a letter or underscore, followed by letters, digits or underscores.
/\A[a-zA-Z_][a-zA-Z0-9_]*\z/
Class Method Summary collapse
-
.disable_rls_for_table(table_name) ⇒ Object
Disable RLS on a table.
-
.enable_rls_for_table(table_name, tenant_column: RlsMultiTenant.tenant_id_column) ⇒ Object
Enable RLS on a table with a policy.
-
.rls_enabled?(table_name) ⇒ Boolean
Check if RLS is enabled on a table.
-
.rls_policies(table_name) ⇒ Object
Get all RLS policies for a table.
Class Method Details
.disable_rls_for_table(table_name) ⇒ Object
Disable RLS on a table
32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/rls_multi_tenant/rls_helper.rb', line 32 def disable_rls_for_table(table_name) table = quoted_table(table_name) policy = quoted_policy_name(table_name) # Drop policy connection.execute("DROP POLICY IF EXISTS #{policy} ON #{table}") # Disable RLS connection.execute("ALTER TABLE #{table} DISABLE ROW LEVEL SECURITY, NO FORCE ROW LEVEL SECURITY") Rails.logger&.info "✅ RLS disabled for table #{table_name}" end |
.enable_rls_for_table(table_name, tenant_column: RlsMultiTenant.tenant_id_column) ⇒ Object
Enable RLS on a table with a policy
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/rls_multi_tenant/rls_helper.rb', line 11 def enable_rls_for_table(table_name, tenant_column: RlsMultiTenant.tenant_id_column) table = quoted_table(table_name) column = quoted_column(tenant_column) policy = quoted_policy_name(table_name) # Enable RLS connection.execute("ALTER TABLE #{table} ENABLE ROW LEVEL SECURITY, FORCE ROW LEVEL SECURITY") # Create policy (drop if exists first) connection.execute("DROP POLICY IF EXISTS #{policy} ON #{table}") tenant_session_var = "rls.#{validated_identifier(RlsMultiTenant.tenant_id_column)}" policy_sql = "CREATE POLICY #{policy} ON #{table} " \ "USING (#{column} = NULLIF(current_setting(#{connection.quote(tenant_session_var)}, TRUE), '')::uuid)" connection.execute(policy_sql) Rails.logger&.info "✅ RLS enabled for table #{table_name} with policy #{table_name}_app_user" end |
.rls_enabled?(table_name) ⇒ Boolean
Check if RLS is enabled on a table
46 47 48 49 50 51 52 |
# File 'lib/rls_multi_tenant/rls_helper.rb', line 46 def rls_enabled?(table_name) result = connection.execute( "SELECT relrowsecurity, relforcerowsecurity FROM pg_class WHERE relname = #{connection.quote(table_name.to_s)}" ).first result&.dig('relrowsecurity') == true && result&.dig('relforcerowsecurity') == true end |
.rls_policies(table_name) ⇒ Object
Get all RLS policies for a table
55 56 57 58 59 60 |
# File 'lib/rls_multi_tenant/rls_helper.rb', line 55 def rls_policies(table_name) connection.execute( 'SELECT policyname, permissive, roles, cmd, qual FROM pg_policies ' \ "WHERE tablename = #{connection.quote(table_name.to_s)}" ) end |