| Module | Authorization::AuthorizationInController::ClassMethods |
| In: |
lib/in_controller.rb
|
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.
class UserController < ActionController
filter_access_to :index
filter_access_to :new, :edit
filter_access_to :all
...
end
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
respond_to do |format|
flash[:error] = 'Sorry, you are not allowed to the requested page.'
format.html { redirect_to(:back) rescue redirect_to('/') }
format.xml { head :unauthorized }
format.js { head :unauthorized }
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:
Any of these loading methods will only be employed if :attribute_check is enabled.
filter_access_to :show, :attribute_check => true,
:load_method => lambda { User.find(params[:id]) }
# File lib/in_controller.rb, line 125
125: def filter_access_to (*args, &filter_block)
126: options = args.last.is_a?(Hash) ? args.pop : {}
127: options = {
128: :require => nil,
129: :context => nil,
130: :attribute_check => false,
131: :model => nil,
132: :load_method => nil
133: }.merge!(options)
134: privilege = options[:require]
135: context = options[:context]
136: actions = args
137:
138: # TODO currently: default deny; make this configurable
139: # collect permits in controller array for use in one before_filter
140: unless class_variable_defined?(:@@permissions)
141: permissions = []
142: class_variable_set(:@@permissions, permissions)
143: before_filter do |contr|
144: all_permissions = permissions.select {|p| p.actions.include?(:all)}
145: matching_permissions = permissions.select {|p| p.matches?(contr.action_name)}
146: allowed = false
147: auth_exception = nil
148: begin
149: allowed = if !matching_permissions.empty?
150: matching_permissions.all? {|perm| perm.permit!(contr)}
151: elsif !all_permissions.empty?
152: all_permissions.all? {|perm| perm.permit!(contr)}
153: else
154: false
155: end
156: rescue AuthorizationError => e
157: auth_exception = e
158: end
159:
160: unless allowed
161: if all_permissions.empty? and matching_permissions.empty?
162: contr.logger.warn "Permission denied: No matching filter access " +
163: "rule found for #{contr.class.controller_name}.#{contr.action_name}"
164: elsif auth_exception
165: contr.logger.info "Permission denied: #{auth_exception}"
166: end
167: if contr.respond_to?(:permission_denied)
168: # permission_denied needs to render or redirect
169: contr.send(:permission_denied)
170: else
171: contr.send(:render, :text => "You are not allowed to access this action.")
172: end
173: end
174: end
175: end
176:
177: class_variable_get(:@@permissions).each do |perm|
178: perm.remove_actions(actions)
179: end
180: class_variable_get(:@@permissions) <<
181: ControllerPermission.new(actions, privilege, context,
182: options[:attribute_check],
183: options[:model],
184: options[:load_method],
185: filter_block)
186: end