diff --git a/lib/declarative_authorization/in_controller.rb b/lib/declarative_authorization/in_controller.rb index fae894df..15b45613 100644 --- a/lib/declarative_authorization/in_controller.rb +++ b/lib/declarative_authorization/in_controller.rb @@ -3,15 +3,15 @@ module Authorization module AuthorizationInController - + def self.included(base) # :nodoc: base.extend(ClassMethods) base.hide_action :authorization_engine, :permitted_to?, :permitted_to! end - + DEFAULT_DENY = false - + # If attribute_check is set for filter_access_to, decl_auth_context will try to # load the appropriate object from the current controller's model with # the id from params[:id]. If that fails, a 404 Not Found is often the @@ -31,12 +31,12 @@ def self.failed_auto_loading_is_not_found= (new_value) def authorization_engine @authorization_engine ||= Authorization::Engine.instance end - + # If the current user meets the given privilege, permitted_to? returns true # and yields to the optional block. The attribute checks that are defined # in the authorization rules are only evaluated if an object is given # for context. - # + # # See examples for Authorization::AuthorizationHelper #permitted_to? # # If no object or context is specified, the controller_name is used as @@ -50,7 +50,7 @@ def permitted_to? (privilege, object_or_sym = nil, options = {}) false end end - + # Works similar to the permitted_to? method, but # throws the authorization exceptions, just like Engine#permit! def permitted_to! (privilege, object_or_sym = nil, options = {}) @@ -59,7 +59,7 @@ def permitted_to! (privilege, object_or_sym = nil, options = {}) # While permitted_to? is used for authorization, in some cases # content should only be shown to some users without being concerned - # with authorization. E.g. to only show the most relevant menu options + # with authorization. E.g. to only show the most relevant menu options # to a certain group of users. That is what has_role? should be used for. def has_role? (*roles, &block) user_roles = authorization_engine.roles_for(current_user) @@ -69,8 +69,8 @@ def has_role? (*roles, &block) yield if result and block_given? result end - - # Intended to be used where you want to allow users with any single listed role to view + + # Intended to be used where you want to allow users with any single listed role to view # the content in question def has_any_role?(*roles,&block) user_roles = authorization_engine.roles_for(current_user) @@ -80,7 +80,7 @@ def has_any_role?(*roles,&block) yield if result and block_given? result end - + # As has_role? except checks all roles included in the role hierarchy def has_role_with_hierarchy?(*roles, &block) user_roles = authorization_engine.roles_with_hierarchy_for(current_user) @@ -90,7 +90,7 @@ def has_role_with_hierarchy?(*roles, &block) yield if result and block_given? result end - + # As has_any_role? except checks all roles included in the role hierarchy def has_any_role_with_hierarchy?(*roles, &block) user_roles = authorization_engine.roles_with_hierarchy_for(current_user) @@ -100,7 +100,7 @@ def has_any_role_with_hierarchy?(*roles, &block) yield if result and block_given? result end - + protected def filter_access_filter # :nodoc: permissions = self.class.all_filter_access_permissions @@ -210,16 +210,16 @@ module ClassMethods # 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| @@ -228,7 +228,7 @@ module ClassMethods # 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+ @@ -252,10 +252,10 @@ module ClassMethods # 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 + # 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 @@ -263,14 +263,14 @@ module ClassMethods # 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+] + # [:+require+] # Privilege required; defaults to action_name - # [:+context+] + # [:+context+] # The privilege's context, defaults to decl_auth_context, which consists # of controller_name, prepended by any namespaces # [:+attribute_check+] @@ -283,19 +283,19 @@ module ClassMethods # * 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+] + # [:+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 + # 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. + # +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]) } - # - + # + def filter_access_to (*args, &filter_block) options = args.last.is_a?(Hash) ? args.pop : {} options = { @@ -313,11 +313,11 @@ def filter_access_to (*args, &filter_block) # prevent setting filter_access_filter multiple times skip_before_filter :filter_access_filter before_filter :filter_access_filter - + filter_access_permissions.each do |perm| perm.remove_actions(actions) end - filter_access_permissions << + filter_access_permissions << ControllerPermission.new(actions, privilege, context, options[:strong_parameters], options[:attribute_check], @@ -325,15 +325,15 @@ def filter_access_to (*args, &filter_block) options[:load_method], filter_block) end - + # Collecting all the ControllerPermission objects from the controller - # hierarchy. Permissions for actions are overwritten by calls to + # hierarchy. Permissions for actions are overwritten by calls to # filter_access_to in child controllers with the same action. def all_filter_access_permissions # :nodoc: ancestors.inject([]) do |perms, mod| if mod.respond_to?(:filter_access_permissions, true) - perms + - mod.filter_access_permissions.collect do |p1| + perms + + mod.filter_access_permissions.collect do |p1| p1.clone.remove_actions(perms.inject(Set.new) {|actions, p2| actions + p2.actions}) end else @@ -393,12 +393,12 @@ def all_filter_access_permissions # :nodoc: # filter_resource_access :additional_member => { :toggle_open => :update } # Would add a member action :+toggle_open+ to the default members, such as :+show+. # - # If :+collection+ is an array of method names filter_resource_access will - # associate a permission with the method that is the same as the method - # name and no attribute checks will be performed unless + # If :+collection+ is an array of method names filter_resource_access will + # associate a permission with the method that is the same as the method + # name and no attribute checks will be performed unless # :attribute_check => true # is added in the options. - # + # # You can override the default object loading by implementing any of the # following instance methods on the controller. Examples are given for the # BranchController (with +nested_in+ set to :+companies+): @@ -409,7 +409,7 @@ def all_filter_access_permissions # :nodoc: # [+load_branch+] # Used for +member+ actions. # [+load_company+] - # Used for all +new+, +member+, and +collection+ actions if the + # Used for all +new+, +member+, and +collection+ actions if the # +nested_in+ option is set. # # All options: @@ -507,7 +507,7 @@ def filter_resource_access(options = {}) collections = actions_from_option(options[:collection]).merge( actions_from_option(options[:additional_collection])) - no_attribute_check_actions = options[:strong_parameters] ? actions_from_option(options[:collection]).merge(actions_from_option([:create])) : collections + no_attribute_check_actions = options[:strong_parameters] ? collections.merge(actions_from_option([:create])) : collections options[:no_attribute_check] ||= no_attribute_check_actions.keys unless options[:nested_in] @@ -555,7 +555,7 @@ def filter_resource_access(options = {}) controller.send(:new_blank_controller_object, options[:context] || controller_name, options[:nested_in], options[:strong_parameters], options[:model]) end - end + end end load_method = :"load_#{controller_name.singularize}" @@ -595,7 +595,7 @@ def decl_auth_context prefixes = name.split('::')[0..-2].map(&:underscore) ((prefixes + [controller_name]) * '_').to_sym end - + protected def filter_access_permissions # :nodoc: unless filter_access_permissions? @@ -606,7 +606,7 @@ def filter_access_permissions # :nodoc: class_variable_set(:@@declarative_authorization_permissions, {}) unless filter_access_permissions? class_variable_get(:@@declarative_authorization_permissions)[self.name] ||= [] end - + def filter_access_permissions? # :nodoc: class_variable_defined?(:@@declarative_authorization_permissions) end @@ -632,7 +632,7 @@ def actions_from_option (option) # :nodoc: end end end - + class ControllerPermission # :nodoc: attr_reader :actions, :privilege, :context, :attribute_check, :strong_params def initialize (actions, privilege, context, strong_params, attribute_check = false, @@ -647,11 +647,11 @@ def initialize (actions, privilege, context, strong_params, attribute_check = fa @attribute_check = attribute_check @strong_params = strong_params end - + def matches? (action_name) @actions.include?(action_name.to_sym) end - + def permit! (contr) if @filter_block return contr.instance_eval(&@filter_block) @@ -659,18 +659,18 @@ def permit! (contr) object = @attribute_check ? load_object(contr) : nil privilege = @privilege || :"#{contr.action_name}" - contr.authorization_engine.permit!(privilege, + contr.authorization_engine.permit!(privilege, :user => contr.send(:current_user), :object => object, :skip_attribute_test => !@attribute_check, :context => @context || contr.class.decl_auth_context) end - + def remove_actions (actions) @actions -= actions self end - + private def load_object(contr) @@ -701,4 +701,3 @@ def load_object(contr) end end end -