class RuboCop::Cop::Betterment::AuthorizationInController

Constants

MSG_UNSAFE_CREATE

MSG_UNSAFE_CREATE = 'Model created/updated using unsafe parameters'.freeze

Attributes

unsafe_parameters[RW]
unsafe_regex[RW]

Public Class Methods

new(config = nil, options = nil) click to toggle source
Calls superclass method
# File lib/rubocop/cop/betterment/authorization_in_controller.rb, line 34
def initialize(config = nil, options = nil)
  super(config, options)
  config = @config.for_cop(self)
  @unsafe_parameters = config.fetch("unsafe_parameters", []).map(&:to_sym)
  @unsafe_regex = Regexp.new config.fetch("unsafe_regex", ".*_id$")
  @param_wrappers = []
end

Public Instance Methods

on_class(node) click to toggle source
# File lib/rubocop/cop/betterment/authorization_in_controller.rb, line 42
def on_class(node)
  Utils::MethodReturnTable.populate_index node
  Utils::MethodReturnTable.indexed_methods.each do |method_name, method_returns|
    method_returns.each do |x|
      name = Utils::Parser.get_root_token(x)
      @param_wrappers << method_name if name == :params || @param_wrappers.include?(name)
    end
  end
end
on_send(node) click to toggle source
# File lib/rubocop/cop/betterment/authorization_in_controller.rb, line 52
def on_send(node) # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity
  return if !model_new?(node) && !model_update?(node)

  node.arguments.each do |argument|
    if argument.send_type? || argument.variable?
      flag_literal_param_use(argument)
      flag_indirect_param_use(argument)
    elsif argument.hash_type?
      argument.children.select(&:pair_type?).each do |pair|
        _key, value = *pair.children
        flag_literal_param_use(value)
        flag_indirect_param_use(value)
      end
    end
  end
end

Private Instance Methods

contains_id_parameter?(params) click to toggle source
# File lib/rubocop/cop/betterment/authorization_in_controller.rb, line 135
def contains_id_parameter?(params)
  params.any? do |arg|
    suspicious_id?(arg)
  end
end
flag_indirect_param_use(node) click to toggle source

Flags objects being created/updated with unsafe params indirectly from params or through params.permit

# File lib/rubocop/cop/betterment/authorization_in_controller.rb, line 89
def flag_indirect_param_use(node) # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
  name = Utils::Parser.get_root_token(node)
  # extracted_params contains parameters used like:
  # def create
  #   Object.new(user_id: indirect_params[:user_id])
  # end
  # def indirect_params
  #   params.permit(:user_id)
  # end
  extracted_params = Utils::Parser.get_extracted_parameters(node, param_aliases: @param_wrappers)

  returns = Utils::MethodReturnTable.get_method(name) || []
  returns.each do |ret|
    # # propagated_params contains parameters used like:
    # def create
    #   Object.new indirect_params
    # end
    # def indirect_params
    #   params.permit(:user_id)
    # end
    propagated_params = Utils::Parser.get_extracted_parameters(ret, param_aliases: @param_wrappers)

    # # internal_params contains parameters used like:
    # def create
    #   Object.new(user_id: indirect_params)
    # end
    # def indirect_params
    #   params[:user_id]
    # end
    if ret.send_type? && ret.method?(:[])
      internal_params = ret.arguments.select { |x| x.sym_type? || x.str_type? }.map(&:value)
    else
      internal_returns = Utils::MethodReturnTable.get_method(Utils::Parser.get_root_token(ret)) || []
      internal_params = internal_returns.flat_map { |x| Utils::Parser.get_extracted_parameters(x, param_aliases: @param_wrappers) }
    end

    add_offense(node, message: MSG_UNSAFE_CREATE) if flag_indirect_param_use?(extracted_params, internal_params, propagated_params)
  end
end
flag_indirect_param_use?(extracted_params, internal_params, propagated_params) click to toggle source
# File lib/rubocop/cop/betterment/authorization_in_controller.rb, line 129
def flag_indirect_param_use?(extracted_params, internal_params, propagated_params)
  return contains_id_parameter?(extracted_params) if extracted_params.any?

  contains_id_parameter?(extracted_params) || contains_id_parameter?(internal_params) || contains_id_parameter?(propagated_params)
end
flag_literal_param_use(node) click to toggle source

Flags objects being created/updated with unsafe params directly from params or through params.permit

class MyController < ApplicationController

def create
  Object.create params.permit(:user_id)
  Object.create(user_id: params[:user_id])
end

end

# File lib/rubocop/cop/betterment/authorization_in_controller.rb, line 81
def flag_literal_param_use(node)
  name = Utils::Parser.get_root_token(node)
  extracted_params = Utils::Parser.get_extracted_parameters(node)
  add_offense(node, message: MSG_UNSAFE_CREATE) if name == :params && contains_id_parameter?(extracted_params)
end
suspicious_id?(symbol_name) click to toggle source

check a symbol name against the cop's config parameters

# File lib/rubocop/cop/betterment/authorization_in_controller.rb, line 142
def suspicious_id?(symbol_name)
  @unsafe_parameters.include?(symbol_name.to_sym) || @unsafe_regex.match(symbol_name) # symbol_name.to_s.end_with?("_id")
end