Daniel Higginbotham
2006-Jun-26 04:37 UTC
[Rails] How to limit access to model objects based on role?
Hi all, I want to limit access to model objects based on the role of the logged in user. It seemed the most blunt way of doing this would be make copies of each controller which accessed the models and use one of the access control systems out there to limit access to the controllers. However, with 9 different controllers this seems like a terrible choice. Here''s what I''ve come up with. Each controller implements something like the following code. Basically, there''s a set_x_with_scope method which takes normal find() parameters, then passes them to X.find within X.with_scope. So, instead of having @category = Category.find(param[:id]), which would occur multiple times in the controller, I use set_category_with_scope(params[:id]), which sets @category and only allows access to data based on attributes of the current user. Right now, I use a collection of methods to build the options for :find in with_scope. Soon, I''m going to alter the methods so that their return values will depend on the user''s role. I hope all this make sense :) On top of all this, I''m using Ezra''s access control plugin to limit access to the controllers. So my question is: is there a better way to do this? class CategoriesController < ApplicationController access_control :DEFAULT => ''(Administrator | SuperUser)'' def edit set_category_with_scope(params[:id]) end def update set_category_with_scope(params[:id]) @category.update_attributes(params[:category]) end def set_category_with_scope(*args) Category.with_scope(:find => scoped_options) do @category = Category.find(*args) end end def scoped_finder_conditions @scoped_finder_conditions ||= {:conditions => "positions.company_id #{current_user.company_id}"} end def scoped_finder_include @scoped_finder_include ||= {:include => :position} end def scoped_options scoped_finder_conditions.merge(scoped_finder_include) end Thanks! Daniel