Class: RuboCop::Cop::DevDoc::Auth::LoadResourceCurrentUserGuard
- Inherits:
-
Base
- Object
- Base
- RuboCop::Cop::DevDoc::Auth::LoadResourceCurrentUserGuard
- Defined in:
- lib/rubocop/cop/dev_doc/auth/load_resource_current_user_guard.rb
Overview
Require an early-return nil-guard before using current_user inside
the load-resource lifecycle method, and forbid safe-navigation (&.).
Rationale
glib_load_resource (or a similarly named hook) runs before the
Pundit policy. At that point current_user may still be nil — an
anonymous visitor hasn't been denied yet. Code that calls
current_user.foo without guarding first crashes for anonymous
visitors; code that uses current_user&.foo hides the problem with
soft nil-handling instead of making it explicit.
The correct pattern is an early-return guard at the top of any branch
that needs current_user:
✔️
def glib_load_resource
return unless current_user
@post = current_user.posts.find(params[:id])
end
Guarded branches within a case/if are also fine:
✔️
def glib_load_resource
case action_name.to_sym
when :new, :create
return unless current_user
@post = current_user.posts.new
when :index
# Nothing to do
end
end
glib's assert_current_user_present raises when current_user is nil,
so it guarantees non-nil just as well as the early return — and any
raise guard works like the return form:
✔️
def glib_load_resource
assert_current_user_present
@post = current_user.posts.find(params[:id])
end
✔️
def glib_load_resource
raise UnauthorizedError unless current_user
@post = current_user.posts.find(params[:id])
end
❌ Safe navigation — hides the pre-auth nil risk
def glib_load_resource
@post = current_user&.posts&.find(params[:id])
end
❌ Unguarded — crashes for anonymous visitors
def glib_load_resource
@post = current_user.posts.find(params[:id])
end
Configuration
LoadResourceMethodNames (default: [glib_load_resource]) — list of
method names where the guard rule applies. Projects standardising on a
different lifecycle method can add it here.
CurrentUserAssertionMethodNames (default:
[assert_current_user_present]) — calls that raise when current_user
is nil. A call to one of these before the first current_user use
satisfies the guard. Add project-specific assertion helpers here. NOTE:
the cop trusts the named method to actually raise on nil — a configured
name that doesn't will turn into a false negative.
NOTE: The cop performs structural analysis of the method body and does
not track aliasing. If you assign current_user to a local variable
and then call methods on that variable, the cop will not flag it —
reviewers must catch that pattern manually.
Constant Summary collapse
- MSG_SAFE_NAV =
'Avoid `current_user&.` inside `%<method>s` — use ' \ '`return unless current_user` then `current_user.` instead.'.freeze
- MSG_MISSING_GUARD =
'`current_user` is used without a prior ' \ '`return unless current_user` (or `assert_current_user_present`) ' \ 'guard in `%<method>s`. ' \ 'This method runs before the policy, so `current_user` may be nil.'.freeze
- NIL_CHECK_METHODS =
Predicates safe to call on a nil
current_user— acurrent_user.nil?etc. is not itself an unguarded use that risks NoMethodError. %i[nil? blank? present? empty?].freeze
- ABSENCE_CHECK_METHODS =
Predicates split by polarity, so a guard's exit branch can be matched to the path on which
current_useris nil.present?is a PRESENCE check (reversed fromnil?/blank?), sounless current_user.present?is a valid guard whileif current_user.present?is not. %i[nil? blank? empty?].freeze
- PRESENCE_CHECK_METHODS =
%i[present?].freeze
Instance Method Summary collapse
- #on_def(node) ⇒ Object (also: #on_defs)
Instance Method Details
#on_def(node) ⇒ Object Also known as: on_defs
127 128 129 |
# File 'lib/rubocop/cop/dev_doc/auth/load_resource_current_user_guard.rb', line 127 def on_def(node) check_load_resource_method(node) end |