module Authorization::Controller::DSL
Public Instance Methods
Returns the context for authorization checks in the current controller. Uses the controller_name and prepends any namespaces underscored and joined with underscores.
E.g.
AllThosePeopleController => :all_those_people AnyName::Space::ThingsController => :any_name_space_things
# File lib/declarative_authorization/controller/dsl.rb, line 166 def decl_auth_context prefixes = name.split('::')[0..-2].map(&:underscore) ((prefixes + [controller_name]) * '_').to_sym end
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 actions. 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 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 inferred 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_actions
:
class BranchesController < ApplicationController before_action :load_company before_action :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_actions
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
decl_auth_context
, which consists of controller_name, prepended by any namespaces - :
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 behavior:filter_access_to :show, :attribute_check => true, :load_method => lambda { User.find(params[:id]) }
# File lib/declarative_authorization/controller/dsl.rb, line 104 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, :strong_parameters => nil }.merge!(options) privilege = options[:require] context = options[:context] actions = args.flatten reset_filter! filter_access_permissions.each do |perm| perm.remove_actions(actions) end filter_access_permissions << ControllerPermission.new(actions, privilege, context, options[:strong_parameters], options[:attribute_check], options[:model], options[:load_method], filter_block) end
Disables authorization entirely. Requires at least one symbol corresponding to an action as parameter. The special symbol :all
refers to all actions. The all :all
statement is only employed if no specific statement is present.
# File lib/declarative_authorization/controller/dsl.rb, line 136 def no_filter_access_to(*args) filter_access_to args do true end end