Skip to content

Make user deletion FK-safe: extend deletable? coverage#1704

Open
maebeale wants to merge 2 commits into
mainfrom
maebeale/user-destroy-deletable-coverage
Open

Make user deletion FK-safe: extend deletable? coverage#1704
maebeale wants to merge 2 commits into
mainfrom
maebeale/user-destroy-deletable-coverage

Conversation

@maebeale

Copy link
Copy Markdown
Collaborator

What is the goal of this PR and why is this important?

  • Fixes the Honeybadger error where UsersController#destroy raised ActiveRecord::InvalidForeignKey (e.g. resources.created_by_id) when deleting a user who still owns records.
  • Main already prevents deletion via User#deletable? (Prevent deletion of users with associated records #1295), but deletable? only checks 9 creator associations. Many other RESTRICT foreign keys to users (banners, authored comments, community news, created events, people, affiliations, user_permissions, self-referential users, blazer) are missed — so the Delete button shows, the user clicks, and only then hits the controller rescue and an alert. Misleading UX.

How did you approach the change?

  • Commit 1 (history): captures the original reassignment approach — reassign/nullify every FK to an orphaned user so the record can be destroyed.
  • Commit 2 (final): supersedes that in favor of main's prevent-deletion approach, extending deletable? to cover the remaining RESTRICT foreign keys so the Delete button is hidden whenever a user owns any blocking record, instead of relying on the rescue safety net.

Anything else to add?

  • The reassignment approach in commit 1 is intentionally superseded; it's kept for history per request.

maebeale and others added 2 commits June 17, 2026 12:05
Captures the reassignment approach to the user-destroy FK constraint
error (Honeybadger: UsersController#destroy raised InvalidForeignKey
on resources.created_by_id). Instead of preventing deletion, this
reassigns NOT NULL created_by/updated_by columns to the orphaned
user and nullifies nullable foreign keys across every table with an
FK to users, so the user can be destroyed without violating
constraints.

This is the exploratory approach; the following commit supersedes it
in favor of extending the prevent-deletion path already on main.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Supersedes the reassignment approach: drop the reassign_owned_records
callback and instead make User#deletable? comprehensive so the UI
reflects deletability accurately rather than leaning on the
controller's InvalidForeignKey rescue.

deletable? previously checked only 9 creator associations, so a user
who owned e.g. a banner, an authored comment, community news, a
created event/person, an affiliation, a self-referential created_by,
a notification they sent, or a blazer record passed the check, showed
the Delete button, and only then hit the rescue. It now checks every
RESTRICT foreign key to users (via model classes for mapped tables and
direct SQL for legacy tables: user_permissions and blazer_*).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

1 participant