Skip to content

Restrict API index sorting to the resource's own columns - #2228

Merged
moveson merged 1 commit into
masterfrom
oveson/claude/api-index-sort-columns
Aug 19, 2026
Merged

Restrict API index sorting to the resource's own columns#2228
moveson merged 1 commit into
masterfrom
oveson/claude/api-index-sort-columns

Conversation

@moveson

@moveson moveson commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes the production 500 captured in Scout error group 123484: GET /api/v1/event_groups?sort=-scheduled_start_time raised PG::UndefinedColumn because scheduled_start_time is not an event_groups column.

Why not tighten the allowlist in the parameters classes

PreparedParams#sort validates against permitted_query, and several resources (event groups, events, courses, lotteries) deliberately union nested-resource fields into permitted_query — the HTML presenters rely on that to sort a parent's efforts (e.g. the spread's last_name,first_name column sort runs under EventParameters). Restricting permitted_query per class would break those views.

The fix

The bug only bites where the sort is applied to the resource's own table: the generic Api::V1::BaseController#index and the raw times index. Those now order by column_sort — the prepared sort hash sliced to controller_class.column_names — so a permitted-but-foreign sort field is silently ignored, consistent with how non-permitted sort fields are already silently dropped.

Rubocop cleanup

CI runs rubocop on whole changed files, so the pre-existing offenses in the two touched specs are cleared as well: response.parsed_body conversions, layout fixes, a duplicate let(:event_group), an if-worded context, and let! setup converted to before (or removed where the fixture reads were dead).

Resolves #2225

Testing

  • New specs: event_groups index with sort=-scheduled_start_time and raw_times index with sort=effort_last_name both return 200 and ignore the sort; all four new examples (login + JWT strategies) verified to fail with PG::UndefinedColumn against the pre-fix code
  • Full spec/controllers/api/v1 suite: 391 examples, 0 failures
  • rubocop clean on touched files

🤖 Generated with Claude Code

The sort allowlist in PreparedParams checks permitted_query, which for
several resources unions in nested-resource fields so presenters can
sort a parent's efforts. When one of those foreign fields reached the
generic API index ORDER BY, Postgres raised UndefinedColumn and the
request 500ed (e.g. /api/v1/event_groups?sort=-scheduled_start_time).

Slice the sort hash to the controller class's column names in the API
base controller index and the raw times index, so foreign fields are
silently ignored like non-permitted fields already are.

Also clear pre-existing rubocop offenses in the touched files
(response.parsed_body, hash literal spacing, let! setup, and a
duplicate let in the raw times spec).

Resolves #2225

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@moveson
moveson merged commit 9df4ef0 into master Aug 19, 2026
7 checks passed
@moveson
moveson deleted the oveson/claude/api-index-sort-columns branch August 19, 2026 17:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

API 500: event_groups index accepts sort fields that are not event_groups columns

1 participant