module Walruz module CoreExt module Array # @overload only_authorized_for(actor, options = {}) # Filters the +Walruz::Subject+ elements inside an array either by a policy or by an action on the _subject_. # This will execute the authorization policies using specified _actor_ and action/policy. # === Notes: # * If a policy is given, you have to use the policy label. # * If an action is given, you have to use the name of the action declared on the subject. # # @param [Walruz::Actor] actor The _actor_ that is going to be used on the authorization process # # @param [Hash] opts for the filtering process. # @option opts [Symbol] :action The name of the action to be executed on the list of subjects. # @option opts [Symbol] :policy The label of an specific policy that is going to be used. # # @return [Array<Walruz::Subject>] An array with the authorized subjects. # # @raise [Walruz::ActionNotFound] if the opts[:action] is not specified on the subject or # if the opts[:policy] label identifying the policy is not recognized # # @example Filtering a list of Posts by the read action specified on the Post class # Post.all.only_authorized_for(current_user, :action => :read) # # this will execute current_user.can?(:read, post) for each element of the array # # @example Filtering a list of Posts by a policy # Post.all.only_authorized_for(nil, :policy => :public_policy) # # This will execute the Policy with the label ":public_policy" on every post using the given actor # # @overload only_authorized_for(actor, action) # Filters the +Walruz::Subject+ elements inside an array by the action specified. # This will execute the authorization policies using specified actor and action on each _subject_ of the +Array+. # # @param [Walruz::Actor] actor The _actor_ that is going to be used on the authorization process # # @param [Symbol] action to be executed by the _actor_ on each _subject_ in the list. # # @return [Array<Walruz::Subject>] An array with the authorized of _subjects_. # # @raise [Walruz::ActionNotFound] if the _action_ specified is not declaredon the _subject_. # # @example Filtering a list of Posts by the read action specified on the Post class # Post.all.only_authorized_for(current_user, :read) # # this will execute current_user.can?(:read, post) for each element of the array # def only_authorized_for(actor, opts = {}) if opts.respond_to?(:[]) only_authorized_with_options(actor, opts) else # use the opts only_authorized_on_action(actor, opts) end end protected def only_authorized_with_options(actor, opts) raise ArgumentError.new("You have to specify either the :action or :policy option") if opts[:action] && opts[:policy] if opts[:action] self.select do |subject| actor.can?(opts[:action], subject) end elsif opts[:policy] policy_clz = Walruz.fetch_policy(opts[:policy]) self.select(&policy_clz.with_actor(actor)) else raise ArgumentError.new("The option hash requires either :action or :policy option") end end def only_authorized_on_action(actor, action) self.select do |subject| actor.can?(action, subject) end end end end end