I think you need to put in place some authorization mechanism.
The best gem I know for this is declarative_authorization. I've personally used it on a production environment, and I'm satisfied with it. There's a railscast about it, too.
The idea is that you declare in one specific file (config/authorization_rules.rb
) the "roles and permissions". You say things like "a manager can read only the clients associated with it" or "an administrator can read and write all the users". In your case, it would look like this:
authorization do
role :guest do
# actions here can be done by everyone, even not logged in people
end
role :user do
includes :guest
# actions here can be done by logged people
end
role :manager do
includes :user #managers do everything users do, plus:
has_permission_on :sales_region, :to => :read do
if_attribute :id => is_in {user.sales_region_ids}
end
has_permission_on :users, :to => [:update, :read] do
if_attribute :id => is {user.user_ids_by_sales_region} #defined on the model
end
end
role :admin do
includes :user
has_permission_on [:sales_regions, :users], :to :manage
end
end
privileges do
privilege :manage do
includes :create, :read, :update, :delete
end
end
Once this is specified, you have modify your models so they use declarative_authorization
. Also, let's define the user_ids_by_sales_region
method
class User < ActiveRecord::Base
using_access_control # this enables DA
def users_by_sales_region
sales_regions.collect{ |sr| sr.users }.flatten.uniq
end
def user_ids_by_sales_region
users_by_sales_region.collect{ |u| u.id }
end
end
You must also have a current_user
method, and a way of getting the current user's role(s). See the "Providing the Plugin’s Requirements" section on the readme.
Then you can do what you want with with_permissions_to
:
manager = User.find(...)
manager.users.with_permissions_to(:read) # the users from his region
manager.users.with_permissions_to(:read).find(:all, conditions => { :active => true })
manager.users.with_permissions_to(:write) #returns no users, managers can't edit them
admin = User.find(...)
admin.users.with_permissions_to(:write) #will return all users
This means a little bit of effort at the beginning, but simplifies the application greatly later on. Also, you have additional functionalities, such as hiding/showing parts of views depending on the permissions the current user has, as well as forbidding access to specific controller actions.
Also, it should work just fine with paginations, etc.
There's another declarative authorization gem called cancan. I don't have experience with this one, but if it is done by Ryan Bates, it must be good (he's got a railscast for it, too). However, I don't think it allows model extensions, which is what you seem to need now.