Fix duplicate emails sent for PrAT and GrAT expiring tokens
What does this MR do and why?
Fix duplicate emails sent for PrAT and GrAT expiring tokens
When sending notifications to inherited members of a group or project, we sometimes send a duplicate of that email. This is because the finders may return multiple memebrship records for the same group / project hierarchy and user. These are usually filtered out by using distinct on user_id and invite_email , however it's possible for a user to be invited via email to a parent group and have a non-email direct membership in a subgroup or project. This will produce multiple Member records from the relevant Finder classes, and will result in duplicate emails being sent to the same user.
This change attempts to fix the above case for email notifications.
References
Please include cross links to any resources that are relevant to this MR. This will give reviewers and future readers helpful context to give an efficient review of the changes introduced.
- Functionality introduced in !174074 (merged)
- Original feature issue: #463016 (closed)
- Rollout issue with internal notes: #497743 (comment 2321523118)
MR acceptance checklist
Please evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
Screenshots or screen recordings
Screenshots are required for UI changes, and strongly recommended for all other merge requests.
| Before | After |
|---|---|
Database review
Postgres.ai private links:
tl;dr the only differences are the outer SELECT DISTINCT ON(user_id) and the lack of the paginated LIMIT 1000 from find_each
this branch:
master branch:
How to set up and validate locally
- Enable the feature flag for the group or instance-wide:
Feature.enable(:pat_expiry_inherited_members_notification, :instance) - Create or visit a group with an Ultimate license
- Invite a new user
test-userto the group as an owner by entering their email address in the invite box -test-usershould have a direct membership in the parent group "Invited by" the original user (the correspondingMembermodel should have something in theinvite_emailcolumn) - As
test-user, create a sub-group: test-subgroup -test-usershould now have a direct membership as "Owner" in test-subgroup - As
test-user, create a project in the sub-group: test-project - Create a project access token on test-project expiring in 5 days
- Run the
PersonalAccessTokens::ExpiringWorkereither via the Rails console (PersonalAccessTokens::ExpiringWorker.new.perform) or via selecting Enqueue now in the Sidekiq page:https://gdk.test:3443/admin/sidekiq/cron/personal_access_tokens_expiring_worker - Check letter-opener to ensure only one email is sent to
test-user
Related to #463016 (closed)