stffn / declarative_authorization

An unmaintained authorization plugin for Rails. Please fork to support current versions of Rails
MIT License
1.24k stars 233 forks source link

Let attribute checks work with PostgreSQL schemas #202

Closed t27duck closed 5 years ago

t27duck commented 9 years ago

When working with PostgreSQL, there are some gems that allow ActiveRecord models to work with multiple schemas. This practice is common for multi-tenant applications where one would want to separate client-specific information within their own schema.

The SQL syntax for accessing a different schema in a query uses dot notation.

SELECT * FROM myschema.mytable WHERE myschema.mytable.mycolumn = 1;

However, having ActiveRecord append the schema name to tables in all queries breaks attribute checks in declarative auth.

The attribute check code uses symbol bind variables for sanitation and passes them into ActiveRecord through finder_options[:conditions]. It would commonly look something like this:

[
  "(\"clients\".\"assigned_user_id\" = :clients__assigned_user_id_0)",
  {:clients__assigned_user_id_0=>1}
]

However when using PostgreSQL schemas, the table name from the ActiveRecord model comes back as public.clients resulting in the conditions array looking like this:

[
  "(\"public\".\"clients\".\"assigned_user_id\" = :public.clients__assigned_user_id_0)",
  {:"public.clients__assigned_user_id_0"=>1}
]

This causes ActiveRecord to not match up the bind variables with the SQL snippet resulting in a PostgrSQL query error.

To fix this, I use gsub to change the period into an underscore when building the bindvar variable. With this change, I get a conditions array that ActiveRecord will parse properly.

[
  "(\"public\".\"clients\".\"assigned_user_id\" = :public_clients__assigned_user_id_0)",
  {:public_clients__assigned_user_id_0=>1}
]