Class: RuboCop::Cop::DevDoc::Route::ResourcesRequireOnly

Inherits:
Base
  • Object
show all
Defined in:
lib/rubocop/cop/dev_doc/route/resources_require_only.rb

Overview

Always use ‘only:` for `resources` / `resource` in routes.rb.

## Rationale When defining routes in routes.rb, it is important to explicitly specify the desired actions using the ‘only` option. This helps prevent accidentally exposing actions that should not be accessible — leaving the default opens the full RESTful set, which often exposes routes the application has no controller action for, or routes that probably should be locked down.

‘only:` is preferred over `except:` because it is explicit about what is exposed. `except:` exposes everything not in the list, which is easier to misread when the action set changes.

Set ‘RequireOnly: false` to accept both `only:` and `except:`.

✔️
resources :job_applications, only: [:index, :new, :create]

Examples:

EnforcedStyle: RequireOnly (default)

# bad
resources :users
resources :users, except: [:destroy]

# good
resources :users, only: %i[index show]

EnforcedStyle: RequireOnly: false

# bad
resources :users

# good
resources :users, only: %i[index show]
resources :users, except: [:destroy]

Constant Summary collapse

MSG =
'Specify `only:` or `except:` for `%<method>s :%<name>s` to avoid exposing unintended actions.'.freeze
MSG_REQUIRE_ONLY =
'Specify `only:` for `%<method>s :%<name>s` ' \
'(`except:` is allowed only with `RequireOnly: false`).'.freeze
RESTRICT_ON_SEND =
%i[resources resource].freeze

Instance Method Summary collapse

Instance Method Details

#on_send(node) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
# File 'lib/rubocop/cop/dev_doc/route/resources_require_only.rb', line 45

def on_send(node)
  has_only = key_present?(node, :only)
  has_except = key_present?(node, :except)

  return if has_only
  return if has_except && !require_only?

  name = node.first_argument&.value || '?'
  msg = has_except && require_only? ? MSG_REQUIRE_ONLY : MSG
  add_offense(node.loc.selector, message: format(msg, method: node.method_name, name: name))
end