What is the best way to do scoped finds based on access control rules in Rails?

Posted by Rafael Szuminski on Stack Overflow See other posts from Stack Overflow or by Rafael Szuminski
Published on 2009-12-09T18:32:41Z Indexed on 2010/04/12 22:03 UTC
Read the original article Hit count: 219

Filed under:
|

Hi

I need to find an elegant solution to scoped finds based on access control rules. Essentially I have the following setup:

Users Customers AccessControl - Defines which user has access to another users data

Users need to be able to access not just their own customers but also shared customers of other users.

Obviously something like a simple association will not work:

has_many :customers

and neither will this:

has_many :customers, :conditions => 'user_id in (1,2,3,4,5)'

because the association uses with_scope and the added condition is an AND condition not an OR condition.

I also tried overriding the find and method_missing methods with the association extension like this:

has_many :customers do
  def find(*args)
    #get the user_id and retrieve access conditions based on the id
    #do a find based on the access conditions and passed args
  end 

  def method_missing(*args)
    #get the user_id and retrieve access conditions based on the id
    #do a find based on the access conditions and passed args
  end
end

but the issue is that I don't have access to the user object / parent object inside the extension methods and it just does not work as planned.

I also tried default_scope but as posted here before you can't pass a block to a default scope.

Anyhow, I know that data segmentation and data access controls have been done before using rails and am wondering if somebody found an elegant way to do it.

UPDATE: The AccessControl table has the following layout

user_id
shared_user_id

The customer table has this structure:

id
account_id
user_id
first_name
last_name

Assuming the the following data would be in the AccessControl table:

1  1
1  3
1  4
2  2
2  13
and so on...

And the account_id for user 1 is 13 I need to be able to retrieve customers that can be best described with the following sql statement:

select * from customers where (account_id = 13 and user_id = null) or (user_id in (1,3,4))

© Stack Overflow or respective owner

Related posts about ruby-on-rails

Related posts about activerecord