minion1227
dd707ec91b
fix(invitations): allow re-inviting after an unaccepted invite expires ( #2543 )
...
* fix(invitations): allow re-inviting after an unaccepted invite expires
An expired, never-accepted invitation still occupies the partial unique
index `index_invitations_on_email_and_family_id_pending` (predicate
`accepted_at IS NULL`), but the `pending` scope excludes it via the
`expires_at > now` clause. The duplicate-guard validation therefore
passes and the INSERT collides with the index, raising
ActiveRecord::RecordNotUnique — surfaced to the admin as a 500 with no
way to re-invite that address through the UI.
Remove the stale expired row inside the create transaction
(before_create) so the unique slot is freed and the re-invite succeeds.
It runs only after validations pass, so a still-pending (non-expired)
invitation can never be removed here. Add a controller-level rescue of
ActiveRecord::RecordNotUnique as a safety net against a concurrent
double-submit race.
Closes #2535
* refactor(invitations): scope RecordNotUnique rescue to the save
The method-level `rescue ActiveRecord::RecordNotUnique` wrapped the whole
create action, so any future write after @invitation.save (e.g.
accept_for) would silently be reported as a generic invite failure.
Extract save_invitation to scope the rescue to the save alone, and add a
regression test that drives the raced unique-index path directly.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-07-08 08:59:54 +02:00
..
2026-06-30 08:19:25 +02:00
2026-07-04 03:27:59 +02:00
2026-06-02 21:44:57 +02:00
2026-06-02 21:44:57 +02:00
2026-06-02 21:44:57 +02:00
2026-06-21 12:01:39 +02:00
2026-07-04 02:47:46 +02:00
2026-06-27 00:57:03 +00:00
2026-05-27 23:58:00 +02:00
2026-05-27 23:58:00 +02:00
2026-05-13 18:13:48 +02:00
2026-05-13 18:13:48 +02:00
2026-05-13 18:13:48 +02:00
2026-05-30 00:12:54 +02:00
2026-01-21 22:56:39 +01:00
2026-01-21 22:56:39 +01:00
2026-04-11 21:37:07 +02:00
2026-04-01 20:25:06 +02:00
2026-06-20 21:43:20 +02:00
2026-06-28 17:02:07 +02:00
2026-07-04 03:22:53 +02:00
2026-07-08 08:08:10 +02:00
2026-05-12 00:17:49 +02:00
2026-06-11 16:48:40 +02:00
2026-02-06 18:04:03 +01:00
2026-04-13 00:51:23 +02:00
2026-06-20 20:33:09 +02:00
2026-06-08 21:45:35 +02:00
2026-05-27 23:33:08 +02:00
2026-05-26 22:48:23 +02:00
2026-05-12 23:45:19 +02:00
2026-06-03 00:37:21 +02:00
2026-06-27 00:57:03 +00:00
2026-04-27 18:33:22 +02:00
2026-04-27 18:33:22 +02:00
2026-06-18 20:18:18 +02:00
2026-06-30 07:35:14 +02:00
2026-06-30 07:35:14 +02:00
2026-07-08 08:08:10 +02:00
2026-02-19 18:58:01 +01:00
2026-07-08 08:08:10 +02:00
2026-05-30 23:27:18 +02:00
2026-01-22 20:37:07 +01:00
2026-06-30 07:37:14 +02:00
2026-06-30 07:37:14 +02:00
2026-07-04 08:24:31 +02:00
2026-03-25 17:47:04 +01:00
2026-01-10 20:11:00 +01:00
2026-03-13 08:11:51 +01:00
2026-06-30 08:19:25 +02:00
2026-06-09 23:02:26 +02:00
2026-06-18 12:28:32 +02:00
2026-06-15 22:12:24 +02:00
2026-06-19 17:07:09 +02:00
2026-01-05 22:11:47 +01:00
2026-05-13 18:17:10 +02:00
2026-01-16 12:34:06 +01:00
2026-06-28 16:12:33 +02:00
2026-05-30 23:29:37 +02:00
2026-06-29 00:30:03 +02:00
2026-04-19 11:16:04 +02:00
2026-04-19 11:16:04 +02:00
2026-05-09 21:55:20 +02:00
2026-06-03 00:37:21 +02:00
2026-06-19 16:54:37 +02:00
2026-06-01 22:02:01 +02:00
2026-06-28 19:47:53 +00:00
2026-06-20 20:33:09 +02:00
2026-06-30 08:19:25 +02:00
2026-06-20 20:33:09 +02:00
2026-06-08 21:35:12 +02:00
2026-05-13 20:07:00 +02:00
2026-05-19 13:37:10 +02:00
2026-01-07 15:59:04 +01:00
2026-03-25 10:50:23 +01:00
2026-05-30 00:22:25 +02:00
2026-06-30 07:26:23 +02:00
2026-06-11 09:04:56 +02:00
2026-06-02 21:44:57 +02:00
2026-06-02 21:44:57 +02:00
2026-06-26 06:47:38 +02:00
2026-03-14 20:14:18 +01:00
2026-05-03 20:33:29 +02:00
2026-06-21 12:01:39 +02:00
2026-05-01 13:31:32 +02:00
2026-06-25 05:44:44 +02:00
2026-03-25 10:50:23 +01:00
2026-04-07 14:43:17 +02:00
2026-04-07 14:43:17 +02:00
2026-05-13 18:13:48 +02:00
2026-05-13 18:13:48 +02:00
2026-05-30 00:51:16 +02:00
2026-06-27 00:57:03 +00:00
2026-05-17 09:52:49 +02:00
2026-06-29 00:37:59 +02:00
2026-06-25 05:44:44 +02:00
2026-03-19 15:17:55 +01:00
2026-04-07 16:28:01 +02:00
2026-04-01 20:25:06 +02:00
2026-04-01 20:25:06 +02:00
2026-05-13 18:13:48 +02:00
2026-05-18 20:49:28 +02:00
2026-03-25 10:50:23 +01:00
2026-06-20 20:33:09 +02:00
2026-05-17 16:55:01 +02:00
2026-05-31 16:24:01 +02:00
2026-07-08 08:08:10 +02:00
2026-06-04 19:53:52 +02:00
2026-05-31 22:17:56 +02:00
2026-06-16 10:51:51 +02:00
2026-03-29 17:30:12 +02:00
2026-04-13 00:51:23 +02:00
2026-02-11 15:22:56 +01:00
2026-01-09 19:38:04 +01:00
2026-01-21 17:16:51 +01:00
2026-06-28 17:02:07 +02:00
2026-06-30 06:55:29 +02:00
2026-06-30 07:26:23 +02:00
2026-06-30 07:26:23 +02:00
2026-05-12 23:45:19 +02:00
2026-05-12 23:45:19 +02:00
2026-05-12 23:45:19 +02:00
2026-06-04 11:48:44 +02:00
2026-06-04 11:48:44 +02:00
2026-06-16 17:13:03 +02:00
2026-06-27 00:57:03 +00:00
2026-03-19 15:17:55 +01:00
2026-05-17 09:52:49 +02:00
2026-06-27 00:57:03 +00:00
2026-06-27 00:57:03 +00:00
2026-05-05 01:04:29 +02:00
2026-07-08 08:59:54 +02:00
2026-01-23 22:05:28 +01:00
2026-05-12 00:22:37 +02:00
2026-05-12 00:22:37 +02:00
2026-06-01 22:00:48 +02:00
2026-06-11 20:26:40 +02:00
2026-07-08 08:08:10 +02:00
2026-05-12 12:18:17 +02:00
2026-04-09 18:33:59 +02:00
2026-06-06 16:33:32 +02:00
2026-03-19 15:17:55 +01:00
2026-05-03 10:56:31 +02:00
2026-06-14 22:09:02 +02:00
2026-05-12 00:00:49 +02:00
2026-02-06 18:04:29 +01:00
2026-07-04 08:24:31 +02:00
2026-06-09 23:02:26 +02:00
2026-06-04 23:11:43 +02:00
2026-05-17 09:52:49 +02:00
2026-05-28 14:55:21 +02:00
2026-05-05 01:04:29 +02:00
2026-06-28 16:12:33 +02:00
2026-06-20 20:33:09 +02:00
2026-05-05 01:12:48 +02:00
2026-06-03 00:04:32 +02:00
2026-05-17 09:52:49 +02:00
2026-05-14 21:56:49 +02:00
2026-05-17 09:52:49 +02:00
2026-06-19 17:07:09 +02:00
2026-01-23 22:05:28 +01:00
2026-06-19 17:07:09 +02:00
2026-06-25 05:38:06 +02:00
2026-06-28 16:12:33 +02:00
2026-05-30 23:29:37 +02:00
2026-06-29 00:30:03 +02:00
2026-05-17 09:52:49 +02:00
2026-05-09 21:55:20 +02:00
2026-05-05 00:47:45 +02:00
2026-05-17 09:52:49 +02:00
2026-01-23 18:55:51 +01:00
2026-06-04 11:48:44 +02:00
2026-06-29 00:47:09 +02:00
2026-02-23 17:43:00 -05:00
2026-05-13 20:07:00 +02:00
2026-05-12 23:45:19 +02:00
2026-05-13 20:07:00 +02:00
2026-06-30 11:55:59 +05:30
2026-06-30 18:00:13 +00:00
2026-07-04 03:13:39 +02:00
2026-06-20 20:33:09 +02:00
2026-06-20 20:33:09 +02:00
2026-05-03 20:33:29 +02:00
2026-07-01 01:50:20 +02:00
2026-02-11 15:22:56 +01:00
2026-05-03 22:13:28 +02:00
2026-06-16 08:32:17 +02:00