Auto-ban duplicate users when a user is banned
What does this MR do and why?
Related to https://gitlab.com/gitlab-org/modelops/anti-abuse/team-tasks/-/issues/814
This MR implements the functionality when a user is banned to automatically ban other users that have the same detumbled email address. Email providers allow alternative addressing schemes that allow a user to modify their email address without changing the mailbox that the email is ultimately routed to. For example, user+123@gmail.com
and user+456@gmail.com
will both ultimately resolve to user@gmail.com
.
Database changes
Change: Added Users.by_detumbled_emails
scope
Single Detumbled Email
Raw SQL
SELECT "users".* FROM "users"
INNER JOIN "emails" ON "emails"."user_id" = "users"."id"
WHERE "emails"."detumbled_email" = 'user@gitlab.com'
Explain
https://postgres.ai/console/gitlab/gitlab-production-main/sessions/31992/commands/98961
Nested Loop (cost=1.00..7.03 rows=1 width=1487) (actual time=0.050..0.072 rows=3 loops=1)
Buffers: shared hit=19
I/O Timings: read=0.000 write=0.000
-> Index Scan using index_emails_on_detumbled_email on public.emails (cost=0.56..3.58 rows=1 width=4) (actual time=0.025..0.028 rows=3 loops=1)
Index Cond: (emails.detumbled_email = 'user@gitlab.com'::text)
Buffers: shared hit=7
I/O Timings: read=0.000 write=0.000
-> Index Scan using users_pkey on public.users (cost=0.44..3.46 rows=1 width=1487) (actual time=0.012..0.012 rows=1 loops=3)
Index Cond: (users.id = emails.user_id)
Buffers: shared hit=12
I/O Timings: read=0.000 write=0.000
Multiple Detumbled Emails
Raw SQL
SELECT "users".* FROM "users"
INNER JOIN "emails" ON "emails"."user_id" = "users"."id"
WHERE "emails"."detumbled_email" IN ('user@gitlab.com', 'user@example.com')
Explain
https://postgres.ai/console/gitlab/gitlab-production-main/sessions/31992/commands/98959a
Nested Loop (cost=1.00..14.06 rows=2 width=1487) (actual time=12.729..28.820 rows=3 loops=1)
Buffers: shared hit=8 read=18
I/O Timings: read=28.478 write=0.000
-> Index Scan using index_emails_on_detumbled_email on public.emails (cost=0.56..7.15 rows=2 width=4) (actual time=8.302..18.350 rows=3 loops=1)
Index Cond: (emails.detumbled_email = ANY ('{user@gitlab.com,user@example.com}'::text[]))
Buffers: shared hit=4 read=10
I/O Timings: read=18.182 write=0.000
-> Index Scan using users_pkey on public.users (cost=0.44..3.46 rows=1 width=1487) (actual time=3.476..3.476 rows=1 loops=3)
Index Cond: (users.id = emails.user_id)
Buffers: shared hit=4 read=8
I/O Timings: read=10.296 write=0.000
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 |
---|---|
How to set up and validate locally
Numbered steps to set up and validate the change are strongly suggested.
Example below:
- In rails console enable the auto_ban_via_detumbled_email feature
Feature.enable(:auto_ban_via_detumbled_email)
- Create a user with a tumbled email (i.e.
user+1@example.com
) - Create another user with the same tumbled email (i.e.
user+2@example.com
). - Ban one of the new users. The other user should be automatically banned as well.
- Retry the tests but add one of the users to a paid top-level namespace. When you ban the other user, the user in the paid namespace should be exempt from being auto-banned.