Module: Authorization::AuthorizationInController::ClassMethods
- Defined in:
- lib/declarative_authorization/in_controller.rb
Instance Method Summary collapse
-
#all_filter_access_permissions ⇒ Object
Collecting all the ControllerPermission objects from the controller hierarchy.
-
#filter_access_to(*args, &filter_block) ⇒ Object
Defines a filter to be applied according to the authorization of the current user.
Instance Method Details
#all_filter_access_permissions ⇒ Object
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.
249 250 251 252 253 254 255 256 257 258 259 260 |
# File 'lib/declarative_authorization/in_controller.rb', line 249 def # :nodoc: ancestors.inject([]) do |perms, mod| if mod.respond_to?(:filter_access_permissions) perms + mod..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 < ApplicationController
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
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
Without the :attribute_check
option, no constraints from the authorization rules are enforced because for some actions (collections, new
, create
), there is no object to evaluate conditions against. To allow attribute checks on all actions, it is a common pattern to provide custom objects through before_filters
:
class BranchesController < ApplicationController
before_filter :load_company
before_filter :new_branch_from_company_and_params,
:only => [:index, :new, :create]
filter_access_to :all, :attribute_check => true
protected
def new_branch_from_company_and_params
@branch = @company.branches.new(params[:branch])
end
end
NOTE: before_filters
need to be defined before the first filter_access_to
call.
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 use a context object from one of the following sources (in that order):
-
the method from the :
load_method
option, -
an instance variable named after the singular of the context (by default from the controller name, e.g. @post for PostsController),
-
a find on the context model, using
params
[:id] as id value.
Any of these 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]) }
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'lib/declarative_authorization/in_controller.rb', line 217 def filter_access_to (*args, &filter_block) = args.last.is_a?(Hash) ? args.pop : {} = { :require => nil, :context => nil, :attribute_check => false, :model => nil, :load_method => nil }.merge!() privilege = [:require] context = [: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 .each do |perm| perm.remove_actions(actions) end << ControllerPermission.new(actions, privilege, context, [:attribute_check], [:model], [:load_method], filter_block) end |