fix: use find_by! to return 404 for invalid tokens#2529
fix: use find_by! to return 404 for invalid tokens#2529mroderick wants to merge 1 commit intocodebar:masterfrom
Conversation
- Changed find_by to find_by! in before_action set_* methods to raise ActiveRecord::RecordNotFound (which Rails converts to 404) instead of returning nil and causing NoMethodError High priority (production crash): - workshop_invitation_concerns.rb - WorkshopInvitation lookup - admin/meeting_invitations_controller.rb - MeetingInvitation lookup - admin/invitations_controller.rb - workshop invitation lookup Medium priority (potential 500 errors): - admin/meetings_controller.rb - Meeting lookup by slug - events_controller.rb - Event lookup by slug - admin/events_controller.rb - Event lookup by slug Lower priority: - invitations_controller.rb:80 - MeetingInvitation lookup in cancel_meeting - contact_preferences_controller.rb:11 - Contact lookup in update - feedback_controller.rb:22 - FeedbackRequest lookup in submit
cf7bd6d to
561b644
Compare
|
|
||
| def set_event | ||
| @original_event = Event.find_by(slug: params[:id]) | ||
| @original_event = Event.find_by!(slug: params[:id]) |
There was a problem hiding this comment.
IMHO: keep it without ! and instead handle the error to display a transparent error message?
class CodebarError < StandardError
def initialize(message)
super(message)
end
# ...
endFor the base controller:
rescue_from CodebarError do |_exception|
...
end| @original_event = Event.find_by!(slug: params[:id]) | |
| e = Event.find_by(slug: params[:id]) | |
| if e.nil? | |
| raise CodebarError.new("could not find event") | |
| @original_event = e | |
There was a problem hiding this comment.
I like the conventional ! to raise standard ActiveRecord errors which have a built-in 404 handling.
There was a problem hiding this comment.
But doesn't that make for rather bad UX? Assumes whoever reads it, knows what token we mean, etc.. I mean, I won't 👎🏼 this. Just don't think this is super great.
There was a problem hiding this comment.
Spelling this out, too: A good thing about this change is that we will get fewer logged errors to investigate - 404s won't show up in exception-tracking services.
Having said all that, yes, we could possibly sometime make failed authentication return something even more useful and legible to the client that offered a wrong token.
But this is a start.
There was a problem hiding this comment.
Let's get this one merged, so we can stop with the 5xx errors and have 4xx errors instead.
I've created a discussion to explore making the UX around errors better: #2572
Summary
Converts silent
nilreturns fromfind_bytofind_by!in before_action callbacks, causing Rails to return a proper 404 response instead of a 500 error when invalid tokens are accessed.Problem
In production, users visiting
/invitations/:tokenwith invalid tokens were seeing:This happened because:
InvitationController#showuses@invitation.memberon line 5@invitationvariable was set by a before_action usingfind_by(token: ...)find_byreturnsnilwhen no record matches (instead of raising an exception).memberonnilcausesNoMethodErrorRoot Cause Analysis
The issue was identified in
app/controllers/concerns/workshop_invitation_concerns.rb:25-27:This pattern existed in 9 locations across the codebase, using
find_byinstead offind_by!for token/slug lookups in before_action callbacks.Solution
Changed
find_bytofind_by!in all 9 locations. Thefind_by!method raisesActiveRecord::RecordNotFoundwhen no record is found, which Rails automatically converts to a 404 response.Files Changed
app/controllers/concerns/workshop_invitation_concerns.rbapp/controllers/admin/meeting_invitations_controller.rbapp/controllers/admin/invitations_controller.rbapp/controllers/admin/meetings_controller.rbapp/controllers/events_controller.rbapp/controllers/admin/events_controller.rbapp/controllers/invitations_controller.rbapp/controllers/contact_preferences_controller.rbapp/controllers/feedback_controller.rbTesting
All controller tests pass. Note: Some pre-existing test failures exist in the codebase (related to 'twitter' attribute on Member model), but these are unrelated to this fix.
Impact
This is more user-friendly and follows REST conventions - an invalid token represents a resource that doesn't exist, not a server error.
Audit Notes
A broader audit of the codebase was performed to identify similar patterns. All
find_bycalls in before_action callbacks that could cause nil-related crashes have been addressed.