Module: Authorization::AuthorizationInController::ClassMethods

Defined in:
lib/in_controller.rb

Instance Method Summary collapse

Instance Method Details

#all_filter_access_permissionsObject

Collecting all the ControllerPermission objects from the controller hierarchy. Permissions for actions are overwritten by calls to filter_access_to in child controllers with the same action.



217
218
219
220
221
222
223
224
225
226
227
228
# File 'lib/in_controller.rb', line 217

def all_filter_access_permissions # :nodoc:
  ancestors.inject([]) do |perms, mod|
    if mod.respond_to?(:filter_access_permissions)
      perms + 
        mod.filter_access_permissions.collect do |p1| 
          p1.clone.remove_actions(perms.inject(Set.new) {|actions, p2| actions + p2.actions})
        end
    else
      perms
    end
  end
end

#filter_access_to(*args, &filter_block) ⇒ Object

Defines a filter to be applied according to the authorization of the current user. Requires at least one symbol corresponding to an action as parameter. The special symbol :all refers to all action. The all :all statement is only employed if no specific statement is present.

class UserController < ActionController
  filter_access_to :index
  filter_access_to :new, :edit
  filter_access_to :all
  ...
end

The default is to allow access unconditionally if no rule matches. Thus, including the filter_access_to :all statement is a good idea, implementing a default-deny policy.

When the access is denied, the method permission_denied is called on the current controller, if defined. Else, a simple “you are not allowed” string is output. Log.info is given more information on the reasons of denial.

def permission_denied
  flash[:error] = 'Sorry, you are not allowed to the requested page.'
  respond_to do |format|
    format.html { redirect_to(:back) rescue redirect_to('/') }
    format.xml  { head :unauthorized }
    format.js   { head :unauthorized }
  end
end

By default, required privileges are infered from the action name and the controller name. Thus, in UserController :edit requires :edit users. To specify required privilege, use the option :require

filter_access_to :new, :create, :require => :create, :context => :users

For further customization, a custom filter expression may be formulated in a block, which is then evaluated in the context of the controller on a matching request. That is, for checking two objects, use the following:

filter_access_to :merge do
  permitted_to!(:update, User.find(params[:original_id])) and
    permitted_to!(:delete, User.find(params[:id]))
end

The block should raise a Authorization::AuthorizationError or return false if the access is to be denied.

Later calls to filter_access_to with overlapping actions overwrite previous ones for that action.

All options:

:require

Privilege required; defaults to action_name

:context

The privilege’s context, defaults to controller_name, pluralized.

:attribute_check

Enables the check of attributes defined in the authorization rules. Defaults to false. If enabled, filter_access_to will try to load a context object employing either

  • the method from the :load_method option or

  • a find on the context model, using params[:id] as id value.

Any of these loading methods will only be employed if :attribute_check is enabled.

:model

The data model to load a context object from. Defaults to the context, singularized.

:load_method

Specify a method by symbol or a Proc object which should be used to load the object. Both should return the loaded object. If a Proc object is given, e.g. by way of lambda, it is called in the instance of the controller.

Example demonstrating the default behaviour:

filter_access_to :show, :attribute_check => true,
                 :load_method => lambda { User.find(params[:id]) }


185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/in_controller.rb', line 185

def filter_access_to (*args, &filter_block)
  options = args.last.is_a?(Hash) ? args.pop : {}
  options = {
    :require => nil,
    :context => nil,
    :attribute_check => false,
    :model => nil,
    :load_method => nil
  }.merge!(options)
  privilege = options[:require]
  context = options[:context]
  actions = args.flatten

  # collect permits in controller array for use in one before_filter
  unless filter_chain.any? {|filter| filter.method == :filter_access_filter}
    before_filter :filter_access_filter
  end
  
  filter_access_permissions.each do |perm|
    perm.remove_actions(actions)
  end
  filter_access_permissions << 
    ControllerPermission.new(actions, privilege, context,
                             options[:attribute_check],
                             options[:model],
                             options[:load_method],
                             filter_block)
end